Java 核心集合容器全解

什么是集合?

顾名思义,集合就是用于存储数据的容器

集合框架是为表示和操作集合而规定的一种统一的标准的体系结构。任何集合框架都包含三大块内容:对外的接口、接口的实现和对集合运算的算法

集合的特点

  • 对象封装数据,多个对象需要用集合存储;

  • 对象的个数可以确定使用数组更高效,不确定个数的情况下可以使用集合,因为集合是可变长度

  • 有哪些常用的集合类

  • 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()的相关规定

  1. 如果两个对象相等,则 hashcode 一定也是相同的

  2. 两个对象相等,对两个 equals 方法返回 true

  3. 两个对象有相同的 hashcode 值,它们也不一定是相等的

  4. 综上,equals 方法被覆盖过,则 hashCode 方法也必须被覆盖

  5. 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);
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值