目录
1、ArrayList
1.1 ArrayList 简介
- ArrayList 的底层是数组队列,相当于动态数组。与 Java 中的数组相比,它的容量能动态增长。
- ArrayList 实现java.io.Serializable 接口,这意味着ArrayList支持序列化,能通过序列化去传输。
- ArrayList 中的操作不是线程安全的!所以,建议在单线程中才使用 ArrayList,而在多线程中可以选择 Vector 或者 CopyOnWriteArrayList。
1.1 扩容机制
ArrayList初始长度为0,当第一次调用add后,长度变为10,当数组首次扩容的10个空间用完需要扩容后,会第二次走grow方法来扩容(每次扩容为1.5倍),它的底层是用数组实现的,所以查询速度相对LinkedList要快。
2、LinkedList
2.1 LinkedList 介绍
- LinkedList底层的链表结构使它支持高效的插入和删除操作;
- 它实现了Deque接口,使得LinkedList类也具有队列的特性;
- LinkedList不是线程安全的,如果想使LinkedList变成线程安全的,可以调用静态类Collections类中的synchronizedList方法:
List list=Collections.synchronizedList(new LinkedList(...));
3、HashMap
3.1 HashMap 介绍
- HashMap是一个散列桶(数组和链表),它存储的内容是键值对(key-value)映射。
- HashMap采用了数组和链表的数据结构,能在查询和修改方便继承了数组的线性查找和链表的寻址修改。
- HashMap是非synchronized,所以HashMap很快。
- HashMap可以接受null键和值,而Hashtable则不能(原因就是equlas()方法需要对象,因为HashMap是后出的API经过处理才可以)
3.2 为什么我们建议在定义HashMap的时候,就指定它的初始化大小呢?
在当我们对HashMap初始化时没有设置初始化容量,系统会默认创建一个容量为16的大小的集合。当HashMap的容量值超过了临界值(默认16*0.75=12)时,HashMap将会重新扩容到下一个2的指数幂(16->32)。HashMap扩容将要进行resize的操作,频繁resize,会导致降低性能。
3.3 HashMap什么时候扩容呢?
- 添加元素的时候会检查容器当前元素个数。当HashMap的容量值超过了临界值(默认16*0.75=12)时扩容。
- HashMap将会重新扩容到下一个2的指数幂(16->32)。
- 调用resize方法,定义长度为新长度(32)的数组,然后对原数组数据进行再Hash。这个过程是一个性能损耗点。
4、HashTable
4.1 HashTable 介绍
Hashtable 的函数都是同步的,这意味着它是线程安全的。它的key、value都不可以为null。此外,Hashtable中的映射不是有序的。
Hashtable 的实例有两个参数影响其性能:初始容量 和 加载因子( 0.75)。
4.2 Hashtable构造方法
//用指定初始容量和指定加载因子构造一个新的空哈希表
public Hashtable(int initialCapacity, float loadFactor)
//用指定初始容量和默认的加载因子 (0.75) 构造一个新的空哈希表
public Hashtable(int initialCapacity)
//默认构造函数,容量为 11,加载因子为 0.75
public Hashtable()
//构造一个与给定的Map具有相同映射关系的新哈希表
public Hashtable(Map< ? extends K, ? extends V> t)
4.3 Hashtable与HashMap的区别
Hashtable | HashMap |
---|---|
方法是同步的 | 方法是非同步的 |
基于Dictionary类 | 基于AbstractMap,而AbstractMap基于Map接口的实现 |
key和value都不允许为null,遇到null,直接返回 NullPointerException | key和value都允许为null,遇到key为null的时候,调用putForNullKey方法进行处理,而对value没有处理 |
hash数组默认大小是11,扩充方式是old*2+1 | hash数组的默认大小是16,而且一定是2的指数 |
4.4 多线程存在的问题
- 如果涉及到多线程同步时,建议采用HashTable
- 没有涉及到多线程同步时,建议采用HashMap
- Collections 类中存在一个静态方法:synchronizedMap(),该方法创建了一个线程安全的 Map 对象,并把它作为一个封装的对象来返回