背景
- 想清楚为什么需要容量大小。因为集合容器底层依然是数组,而数组肯定是需要一个容量值的。
- 设置一个初始容量,防止因为扩容机制占有了很多的内存,但是又没有存储更多的对象,浪费了空间。
- 那如果不设置初始容量也可以吗? 答案:肯定可以的,只是我们很多做法有好的,也有不好的。
- 哪些java集合需要设置初始容量,而哪些集合根本没有必要设置初始容量呢?为什么有这样的区别?
过程
- 在给java容器设定初始容量的时候,最需要掌握的基础知识:java容器的扩容机制。
- HashMap, HashSet初始容量是16,扩容因子是0.75,扩容后是原来的2倍。
- ArrayList初始容量是10,扩容因子是1,扩容是原来的1.5倍。
- Vector初始容量是10,扩容因子是1,扩容后是原来的2倍。它的其他知识点:Vector是线程安全的。 synchronized。
- HashTable是线程安全的,它的底层实现是HashMap因此它的扩容机制跟HashMap是一样的。而它的线程安全是通过关键字synchronized实现的。
- CopyOnWriteArrayList的扩容机制跟ArrayList一样。 这个容器的其他知识点:防止读写并发出现的问题。 写的时候拷贝一个副本进行写。写完了后又把新的数组赋值给原来的变量即可。原来旧的因为没有被引用了,因此下次就被垃圾收集器回收调了。并且在写的时候,加了锁的,因此同一个时刻只能有一个线程在写。当然,同时可能有很多线程在读。
-
在使用集合容器的时候,给一个大概的初始容量。链表就没有必要给初始容量了。因为链表是一个可以无限长的集合容器,只需要构建节点之间的关系即可。
-
知道了每个容器的扩容机制后,然后也对当前的业务场景非常了解,知道大概一共可能会有多少个对象。这个时候我们才有资格给容器设置一个大概的初始容量。在不知道容器扩容机制,不知道当前业务场景,是没有资格给容器设定一个初始容量的。
-
对性能有很高要求的场景,才需要给容器设定一个初始容量。对很多业务场景其实意义不大,有意义但是不大。
小结
- 想清楚为什么需要容量。因为集合容器底层依然是数组,而数组肯定是需要一个容量值的。
- 其他细节知识:
- HashTable是线程安全的。采用关键字synchronized实现的。
- Vector是线程安全的。 采用关键字synchronized实现的。
- CopyOnWriteArrayList:防止读写并发出现的问题。 写的时候拷贝一个副本进行写。写完了后又把新的数组赋值给原来的变量即可。