菜鸟学JAVA之——集合框架(二)(Set接口的实现类HashSet、LinkedHashSet、TreeSet)

ゝ一世哀愁。 2023-06-23 13:15 44阅读 0赞

Set接口

如果有人告诉你Set是无序的,那你可以直接回怼他这是错的,说法不严谨。

Set接口的实现类(都不能放重复值)

​ 1.HashSet(无序)

​ 2.LinkedHashSet(有序)

​ 3.TreeSet(有序)

没有ArraySet,这是因为Array是连续的,Set是不连续的;

  • Set与List的相同点,也是Collection的子接口,也是容器
  • Set才叫真正意义上的集合,List叫做列表
  • 集合与列表的区别:

    列表是一条一条记录的,而集合是围在一起的

    比如,有五个人,他们整整齐齐做一列就是列表,要是围一堆坐着就是集合,不知道谁是头,谁是尾

    Set集合是没有脚标的,所以Set里面也没有get方法,List有脚标,所以可以有get方法,List和Set是兄弟关系,这也正是Collection接口里没有get方法的原因。

  • 集合中不能放重复的对象,这是因为他没有脚标。所以Set集合可用来去重
  • Set有点像水壶,茶壶里煮饺子,倒不出来。要是想从Set里拿出来,则必须把所有的值都拿出来

HashSet是无序的,注意是HashSet不是Set

forezch在底层使用迭代器实现的

如果一个类没有迭代器,则它不能使用foreach循环

iterator.remove();不能连着使用

  • 怎么解释hashset是无序的,怎么解释set不能放重复元素?

    因为hashSet的底层是按照hash算法排列得到的数列,他是一个不可逆的算法。每个对象都有一个hashcode,hash算法通过hashcode来排数据,所以hashset无序。

    HashSet底层由HashMap实现,插入的元素被当做是HashMap的key,根据hashCode值来确定集合中的位置,在向HashMap中添加元素时,先判断key的hashCode值是否相同,如果相同,则调用equals()、==进行判断,若相同则覆盖原有元素;如果不同,则直接向Map中添加元素;

set的两个主要实现类,TreeSet和HashSet,底层存储结构都是用的map,而且是将set需要存储的值放在map的key里的,value是一个空的object对象。

在这里插入图片描述

  • 那有没有有序的set呢

    有,LinkedHashSet, 往里放的什么顺序,打印出来的就是什么顺序,以链表的形式存当前的元素,只是链表位置被hash了,但是它没有下标

    还有一个有序的set,TreeSet。按comparable升序排列,它的底层实现是二叉树

TreeSet有个约束,往它里面放到内容必须实现comparable接口

一、HashSet

在向HashMap中添加元素时,先判断key的hashCode值是否相同,如果相同,则调用equals()、==进行判断,若相同则覆盖原有元素;如果不同,则直接向Map中添加元素;

  1. public class Main {
  2. public static void main(String[] args) {
  3. Set<String> sets = new HashSet<>();
  4. sets.add("zhang");
  5. sets.add("ao");
  6. sets.add("qi");
  7. sets.add("zhang");
  8. sets.add("san");
  9. Iterator<String> iterator = sets.iterator();
  10. while (iterator.hasNext()) {
  11. System.out.println(iterator.next());
  12. } //输出:san qi zhang ao //无序的且不重复
  13. sets.remove("ao");//删除元素
  14. sets.clear(); //清空容器
  15. }
  16. }

二、LinkedHashSet(直接父类是 HashSet)

特点:存取有序,存储的元素不能重复。

  1. Set<String> sets = new LinkedHashSet<>();
  2. sets.add("a");
  3. sets.add("a");
  4. sets.add("a");
  5. sets.add("b");
  6. sets.add("b");
  7. sets.add("c");
  8. sets.add("d");
  9. for (String str:sets
  10. ) {
  11. System.out.println(str);
  12. }
  13. //输出a b c d

三、TreeSet( 底层结构为红黑树

与HashSet不同的是,TreeSet具有排序功能,分为自然排序(123456)和自定义排序两类,默认是自然排序;在程序中,我们可以按照任意顺序将元素插入到集合中,等到遍历时TreeSet会按照一定顺序输出–倒序或者升序;

方式一: 让元素所在的类实现Comparable接口,并重写CompareTo() 方法,并根据CompareTo()的返回值来进行添加元素

  • 返回正数:往二叉树的右边添加
  • 返回负数:往二叉树的左边添加
  • 返回 0 : 说明重复,不添加

方式二: 使用TreeSet的有参构造方法创建TreeSet对象的时候, 传入一个比较器 Comparator 进去, TreeSet在添加元素的时候, 根据比较器的compare()方法的返回值来添加元素。

  • 返回正数:往二叉树的右边添加
  • 返回负数:往二叉树的左边添加
  • 返回 0 : 说明重复,不添加

TreeSet存储元素对元素进行排序的源码解析
TreeSet在存储元素的时候会首先去判断是否有比较器存在(也就是判断比较器是否为null),如果存在:就会让比较器去调用compare(T t1, T t2)方法,去依次比较即将存入的值和已经存入TreeSet集合的值,如果返回正数:往二叉树右侧放;如果返回负数:往二叉树左侧放;如果返回 0 :不添加。如果不存在:底层就会把即将存入的元素自动提升为Comparable类型的对象(所以如果没有比较器的情况下,元素所在的类没有实现Comparable接口,在做自动提升类型的时候就会报类型转换错误),并让该对象调用CompareTo(T t)方法,和已经存入TreeSet集合的元素依次比较,如果返回正数:往二叉树右侧放;如果返回负数:往二叉树左侧放;如果返回 0 :不添加。所以,如果两种方式同时使用,底层会优先使用方式二(比较器的方式)。
在这里插入图片描述

学习参考:
https://blog.csdn.net/Qingai521/article/details/87968134
https://www.baidu.com/link?url=o4mGbw9BArl9kO8SxYj_9jYdwjO5FsfggK8FpB6CCxsj1SxlIhSRsx7_3mAu_2F3&wd=&eqid=a848f8fb0007e998000000035dfaf2c7

发表评论

表情:
评论列表 (有 0 条评论,44人围观)

还没有评论,来说两句吧...

相关阅读

    相关 JAVA——内部

    内部类 内部类:定义在一个类里面的类。一般的内部类包括:成员内部类、局部内部类、匿名内部类和静态内部类 ,下面我们说一下成员内部类和静态内部类 一、成员内部类 成

    相关 JAVA——继承

    继承 Java中, 类的继承是单一继承,也就是说,一个子类只能拥有一个父类,所以 extends 只能继承一个类。 继承关键字:extends意为扩展,继承就是子类对父

    相关 JAVA——前言

    一、硬件 一个电脑的核心是CPU,CPU看上去很大,其实只有很小的一片才是CPU,其他都是散热片。 主板:主板上有一个能承载CPU的管脚孔,每个管脚孔里有两个