(3)Collection、List、Set、哈希表

(1)Collection 单列集合的顶层接口

List 有序 有索引 可重复

ArrayList

  • 底层是数组
  • 查询块(有索引,内存连续) 增删慢(长度不可变,每次修改都需要新建数组))
  • 线程不安全 效率高

LinkedList

  • 底层是链表
  • 查询慢(在内存内是分散的)
  • 增删快(通过修改关联的前后数据地址进行修改:本质上并没真的进行增减,只是修改了数据之间的关联的地址)
  • 线程不安全 效率

Vector

  • 底层是数组
  • 查询块 增删慢
  • 线程安全 效率低

Set 元素唯一

HashSet

  • 底层是哈希表 查询速度嗷嗷快
  • 无序 唯一
  • 通过hashCode方法和equals方法保证元素唯一

先判断hashCode方法

不同 添加到集合

相同 继续比较equals方法

不同 添加到集合

相同 不添加

LinkedHashSet

  • 底层是链表 + 哈希表
  • 链表保证元素有序 哈希表保证元素唯一
  • 通过hashCode方法和equals方法保证元素唯一

先判断hashCode方法

不同 添加到集合

相同 继续比较equals方法

不同 添加到集合

相同 不添加

  1. 查询多 ArrayList
  2. 增删多 LinkedList
  3. 保证唯一 HashSet
  4. 保证唯一有序 LinkedHashSet
  5. 什么都不知道 ArrayList

(2)哈希表的特点

HashSet集合存储数据的结构(哈希表)

什么是哈希表呢?

在JDK1.8之前,哈希表底层采用数组+链表实现,即使用数组处理冲突,同一hash值的链表都存储在一个数组里。 但是当位于一个桶中的元素较多,即hash值相等的元素较多时,通过key值依次查找的效率较低。而JDK1.8中,哈 希表存储采用数组+链表+红黑树实现,当链表长度超过阈值(8)时,将链表转换为红黑树,这样大大减少了查找 时间。

简单的来说,哈希表是由数组+链表+红黑树(JDK1.8增加了红黑树部分)实现的,如下图所示。

HashCode默认是取地址值,String和基本类型的包装类都重写了HashCode方法,所以取得 不是地址值。

String比较:先比较hashcode,如果不同就停止;如果相同,再调用equals

原因:String重写了HashCode方法,所以获取的不再是地址值,而是自定义的一个算法(源 码中可以看到这个算法);当hashCode值不同时, 两个字符串必定不相同,如果值相同,则这两个字符串不一定相同(如“abc”和“cba”,哈希码相同,但内容不同),需要再次调用equals方法比较

好处:减少equals方法的调用,提高性能。

(3)使用HashSet集合存储自定义元素

HashSet不能重复是因为底层做了排重,原理是先比较hashcode,再调用equals比较

对于自定义对象,使用Set,必须重写HashCode和equals方法(否则会出现重复)

如果不重写这两个方法,这个对象会调用Object的方法,而Object的hashcode获取的是地址值,必定不相同,也就无法去除重复。

(4)Collections 集合的工具类

public static void shuffle(List<?> list):打乱集合顺序。

public static <T> void sort(List<T> list):将集合中元素按照默认规则排序。

public static <T> void sort(List<T> list,Comparator<? super T> ):将集合中元素按照指定规则排序。

Comparator比较

相当于有个裁判 来进行判断

自定义规则来进行排序

参数1-参数2 升序

参数2-参数1 降序

猜你喜欢

转载自blog.csdn.net/lipeng_lipeng/article/details/85245457