Java集合小总结

本文详细介绍了Java集合框架中List、Set、Map等核心接口的具体实现类,如ArrayList、LinkedList、HashSet、TreeSet、HashMap等,并对比了它们之间的差异,包括存储方式、线程安全性及应用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

注意:我在Android Studio中分别查看了android SDK自带的jdk和我自己下载的jdk1.8,所看到的源代码并不相同。但是实现原理都是一样的,个人认为Android带的更好懂一些啊哈哈


更新:应该是OpenJDK/OracleJDK/ApacheHarmony 的差别,我真的有点糊涂,谁给我理一理他们的关系,而且Android到底要用什么了


List

ArrayList

用数组存储数据,初始大小0->10/12->*150%,当数据更多时,容量扩大50%,不同步,线程不安全。ArrayList适合随机查找和遍历,不适合插入和删除。
add函数里,扩容声明新数组的一段代码:

Object[] newArray = new Object[s +
    (s < (MIN_CAPACITY_INCREMENT / 2) ?
     MIN_CAPACITY_INCREMENT : s >> 1)];

Vector

同ArrayList,初始大小为10,每次翻倍扩容。同步的,线程安全。因为同步的开销,效率低于ArrayList。

public synchronized void insertElementAt(E object, int location)

LinkedList

双向链表。可以被当作堆栈、队列或双端队列进行操作。非同步。
节点:

private static final class Link<ET> {
    ET data;

    Link<ET> previous, next;

    Link(ET o, Link<ET> p, Link<ET> n) {
        data = o;
        previous = p;
        next = n;
    }
}

Set

HashSet

数据不允许出现重复,判断方式需要对象重写equals()和hashCode()函数。实现原理是内部封装一个HashMap,仅使用key,value用this(android sdk)或一个静态Object(jdk1.8)代替。

TreeSet

同,基于TreeMap。


Map

HashMap

利用数组+链表存储键值对。通过key.hash&(length-1)作为下标将键值对找到数组中合适的位置,并将其加在该位置链表的末尾。线程不安全,允许null值的存在,效率高于HashTable。新加的节点会放在链表首。当两个key的hash值相同时,首先找到数组中对应的链表首,然后开始循环,如果key指向的对象和键值对中key指向的对象是同一个,或者两者equals()和hashCode()都相同,则认为找到了,返还value。

Hashtable

和HashMap类似,但继承自Dictionary,线程安全,但不能接受key==null。 初始大小为11,如下图:

public Hashtable() {this(11, 0.75f);}

ConcurrentHashMap

利用锁分段技术实现一定程度上线程安全的同时,提高访问效率。将存储数据分段(Segment),访问Segment时,需要获得锁,可以同时访问不同分段的数据。不是绝对线程安全的,get时,不加锁,put时会加锁,remove时也会加锁。
以下引用自方腾飞——《聊聊并发(四)——深入分析ConcurrentHashMap》:

ConcurrentHashMap是由Segment数组结构和HashEntry数组结构组成。Segment是一种可重入锁ReentrantLock,在ConcurrentHashMap里扮演锁的角色,HashEntry则用于存储键值对数据。一个ConcurrentHashMap里包含一个Segment数组,Segment的结构和HashMap类似,是一种数组和链表结构, 一个Segment里包含一个HashEntry数组,每个HashEntry是一个链表结构的元素, 每个Segment守护者一个HashEntry数组里的元素,当对HashEntry数组的数据进行修改时,必须首先获得它对应的Segment锁。

TreeMap

内部维护着一棵红黑树,保证了按大小顺序读出容器数据。

LinkedHashMap

LinkedHashMap 维护着一个运行于所有条目的双重链表。链表定义了迭代顺序(插入/访问)。不同步。允许使用 null 值和 null 键。

LinkedHashMap:public LinkedHashMap(int initialCapacity, float loadFactor, boolean accessOrder)

排序模式 :accessOrder。访问顺序: true;插入顺序: false。默认为插入顺序。
LinkedHashMap的一个用途时实现 LRU 缓存。LinkedHashMap 提供了removeEldestEntry(Map.Entry<K,V> eldest) 方法,默认返还false。可通过重写实现在需要删除的时候删除最旧的节点。


所有线程不安全的容器可以使用:Collections.synchronizedList/Map/Set(x)保证线程安全。


快速失败/安全失败(fast-fail/safe-fail)

  1. 安全失败基于对底层集合的拷贝,不受源集合上的修改的打扰。
  2. 当正在迭代的容器被另一个线程修改时,快速失败抛出异常:ConcurrentModicationException,安全失败不抛出该异常
  3. java.util包下都是快速失败,java.util.concurrent包下都是安全失败
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值