jdk集合类
文章目录
一、简介
集合类是java开发的基础。在此进行整体框架性的介绍。
二、集合接口
集合类主要分为两大集合接口,分别是Collection接口和Map接口。
-
Collection接口下,主要有List(列表)、Set(集合)、Queue(队列)
-
Map接口,下面就是Map(hash),也就是键值对相关的集合。
三、集合实现
集合类底层存储实现主要有两种,分别是数组和链表。
3.1 数组实现
典型数组实现有ArrayList和HashMap,有默认初始值的。
3.1.1 ArrayList
ArrayList的初始值是10,当然也可以指定初始值,源码为:
private static final int DEFAULT_CAPACITY = 10;
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ELEMENTDATA;
} else {
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
数组的增加方式是在原长度的基础上增加0.5倍,也就是变为原来的1.5倍,源码如:
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}
触发数组增加的时机,是在列表添加新元素时判断的,通常当前容量加1,再与数组容量比,如果小了,则表示需要扩容了,源码为:
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
private void ensureCapacityInternal(int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}
3.1.2 HashMap
HashMap的数组初始值是16,源码为:
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16
数组增长的因子是0.75,源码为:
static final float DEFAULT_LOAD_FACTOR = 0.75f;
数组增加阈值是capacity * load factor,原码为:
/**
* The next size value at which to resize (capacity * load factor).
* @serial
*/
// If table == EMPTY_TABLE then this is the initial capacity at which the
// table will be created when inflated.
int threshold;
增长值为,2的位数且最小的,大于原容量的,原码为:
private void inflateTable(int toSize) {
// Find a power of 2 >= toSize
int capacity = roundUpToPowerOf2(toSize);
threshold = (int) Math.min(capacity * loadFactor, MAXIMUM_CAPACITY + 1);
table = new Entry[capacity];
initHashSeedAsNeeded(capacity);
}
增长触发点仍然是进行数据插入时。
其它集合实现类的数组实现方式,在此不细说。
3.2 链表实现
对于链接,是没有所谓初始值的,直接在链表头或链表尾添加,在此不细说。
四、集合java包
集合类主要集中在java.util包和java.util.concurrent包下。
4.1 java.util包
对于java.util包下的集合类,分为线程安全和非安全,线程安全的实现方式是在方法上加synchroniced关键字,控制粒度比较粗。
4.2 java.util.concurrent包
对于java.util.concurrent包下的集合类,里面的实现类是安全的,实现方式是通过lock锁,这种实现方式,控制粒度比较细,效率更高。而且像ConcurrentHashMap类,还对数据进行分段,锁也是加在各个分段上,因此效率更高。另外在有序集合上,还加入了SkipList(跳表)这种数据结构,进行快速查询,如ConcurrentSkipListMap,CurrentSkipListSet。