什么是集合?
顾名思义,集合就是用于存储数据的容器。
集合框架是为表示和操作集合而规定的一种统一的标准的体系结构。任何集合框架都包含三大块内容:对外的接口、接口的实现和对集合运算的算法。
集合的特点
-
对象封装数据,多个对象需要用集合存储;
-
对象的个数可以确定使用数组更高效,不确定个数的情况下可以使用集合,因为集合是可变长度
-
有哪些常用的集合类
-
Java 容器分为 Collection 和 Map 两大类,Collection 集合的子接口有 Set、List、Queue 三种子接口。
我们比较常用的是 Set、List,Map 接口不是 collection 的子接口。
Collection 集合主要有 List 和 Set 两大接口
List:一般使用最多的时ArrayList(数组实现) LinkList(双向循环链表实现)
ArrayList 和 LinkedList 的区别是什么?
-
数据结构实现:ArrayList 是动态数组的数据结构实现,而 LinkedList 是双向链表的数据结构实现。
-
随机访问效率:ArrayList 比 LinkedList 在随机访问的时候效率要高,因为 LinkedList 是线性的数据存储方式,所以需要移动指针从前往后依次查找。
-
增加和删除效率:在非首尾的增加和删除操作,LinkedList 要比 ArrayList 效率要高,因为 ArrayList 增删操作要影响数组内的其他数据的下标。
-
内存空间占用:LinkedList 比 ArrayList 更占内存,因为 LinkedList 的节点除了存储数据,还存储了两个引用,一个指向前一个元素,一个指向后一个元素。
-
线程安全:ArrayList 和 LinkedList 都是不同步的,也就是不保证线程安全;
综合来说,在需要频繁读取集合中的元素时,更推荐使用 ArrayList,而在插入和删除操作较多时,更推荐使用 LinkedList。
Set:一般最常用HashSet:唯一,无序。基于 HashMap 实现,底层采用 HashMap 保存数据。
-
HashSet
底层原理完全就是包装了一下HashMap
-
HashSet
的唯一性保证是依赖与hashCode()
和equals()
两个方法,所以存入对象的时候一定要自己重写这两个方法来设置去重的规则。 -
HashSet
中的元素都存放在HashMap
的key
上面,而value
中的值都是统一的一个 private static final Object PRESENT = new Object();
hashCode()与 equals()的相关规定:
-
如果两个对象相等,则 hashcode 一定也是相同的
-
两个对象相等,对两个 equals 方法返回 true
-
两个对象有相同的 hashcode 值,它们也不一定是相等的
-
综上,equals 方法被覆盖过,则 hashCode 方法也必须被覆盖
-
hashCode()的默认行为是对堆上的对象产生独特值。如果没有重写 hashCode(),则该 class 的两个对象无论如何都不会相等(即使这两个对象指向相同的数据)。
它不允许集合中有重复的值,当我们提到 HashSet 时,第一件事情就是在将对象存储在 HashSet 之前,要先确保对象重写 equals()和 hashCode()方法,这样才能比较对象的值是否相等,以确保 set 中没有储存相等的对象。
如果我们没有重写这两个方法,将会使用这个方法的默认实现。
Map
-
HashMap:JDK1.8 之前 HashMap 由数组+链表组成的,数组是 HashMap 的主体,链表则是主要为了解决哈希冲突而存在的(“拉链法”解决冲突)。
JDK1.8 以后在解决哈希冲突时有了较大的变化,当链表长度大于阈值(默认为 8)时,将链表转化为红黑树,以减少搜索时间。
Map原理 -
当我们往 Hashmap 中 put 元素时,利用 key 的 hashCode 重新 hash 计算出当前对象的元素在数组中的下标。
-
存储时,如果出现 hash 值相同的 key,此时有两种情况。
-
如果 key 相同,则覆盖原始值;
-
如果 key 不同(出现冲突),则将当前的 key-value 放入链表中
-
-
获取时,直接找到 hash 值对应的下标,在进一步判断 key 是否相同,从而找到对应值。
-
理解了以上过程就不难明白 HashMap 是如何解决 hash 冲突的问题,核心就是使用了数组的存储方式,然后将冲突的 key 的对象放入链表中,一旦发现冲突就在链表中做进一步的对比。
遍历集合Iterator
Iterator 接口提供遍历任何 Collection 的接口。我们可以从一个 Collection 中使用迭代器方法来获取迭代器实例。举例list,其他的集合基本一致
List<String> list = new ArrayList<>();
Iterator<String> it = list. iterator();
while(it. hasNext()){
String obj = it. next();
System. out. println(obj);
}