java容器





java集合使用注意事项 :
1、判断所有集合内部的元素是否为空,使用 isEmpty() 方法,而不是 size()==0 的方式

2、在使用 java.util.stream.Collectors 类的 toMap() 方法转为 Map 集合时,一定要注意当 value 为 null 时会抛 NPE 异常。
3、不要在 foreach 循环里进行元素的 remove/add 操作。remove 元素请使用 Iterator 方式,如果并发操作,需要对 Iterator 对象加锁。

4、可以利用 Set 元素唯一的特性,可以快速对一个集合进行去重操作,避免使用 List 的 contains() 进行遍历去重或者判断包含操作。
5、使用集合转数组的方法,必须使用集合的 toArray(T[] array),传入的是类型完全一致、长度为 0 的空数组。

6、使用工具类 Arrays.asList() 把数组转换成集合时,不能使用其修改集合相关的方法, 它的 add/remove/clear 方法会抛出 UnsupportedOperationException 异常。传基本类型会传递数组地址。因为java值传递,而asList参数是泛型对象。

源码解读:
1、ArrayList
java集合常见异常fail-fast机制分析,fail-fast是在操作迭代器的时候产生的,如果操作迭代器遍历的时候list发生元素修改,那么就会抛出异常。


ArrayList 类里面有一个modCount,只要是涉及了改变ArrayList元素的个数的方法都会导致modCount的改变。从而导致和迭代器里面的expectedModCount不一致而抛出异常。Iterator迭代器自己改变元素的时候exceptedModCount才会改变。比如调用迭代器的add和remove方法。
解决方案:
方案一:在遍历过程中所有涉及到改变modCount值得地方全部加上synchronized或者直接使用Collections.synchronizedList(不推荐)
方案二:使用CopyOnWriteArrayList来替换ArrayList。
CopyOnWriteArrayList为什么能解决这个问题呢?CopyOnWrite容器即写时复制的容器。通俗的理解是当我们往一个容器添加元素的时候,不直接往当前容器添加,而是先将当前容器进行Copy,复制出一个新的容器,然后新的容器里添加元素,添加完元素之后,再将原容器的引用指向新的容器。CopyOnWriteArrayList中add/remove等写方法是需要加锁的,目的是为了避免Copy出N个副本出来,导致并发写。但是。CopyOnWriteArrayList中的读方法是没有加锁的。
我们只需要记住一句话,那就是CopyOnWriteArrayList是线程安全的,所以我们在多线程的环境下面需要去使用这个就可以了。
ArrayList每次扩容都会变为之前的1.5倍左右,除非小于最小需要的容量,如果小于,那么以最小需要的容量为准。



2、HashMap
get()方法先找到在数组中的位置(产生的hash对数组取模,这也是为啥hashmap大小是2的幂的原因),然后比较第一个的hash和key的hash是否相等,相等则比较值是否相等,用first.key==key是因为hashmap的key可以为null,如果是null,那么equals会抛出异常。

put方法:

HashMap的size是元素个数,threshold临界值是用size*临界因子得到的。

hashMap在java1.7及之前因为采用头插法在rehash过程中会出现死循环问题,1.8采用头插法解决了这个问题。


ConcurrentHashMap
1.7



1.8
key和value都不能为空

put逻辑:


这块儿源码没有仔细看,后面还要加强学习。
整理自:https://javaguide.cn/
浙公网安备 33010602011771号