Collection集合框架体系
其中 RandomAcccess 接口是一个标记接口,无任何方法,用来标记子类支持快速随机访问.主要目的是为了允许对随机访问和顺序访问可定制不同的行为,从而达到更好的性能.
杂记
AbstractCollection.toArray() 方法
public Object[] toArray() {
// Estimate size of array; be prepared to see more or fewer elements
Object[] r = new Object[size()];
Iterator<E> it = iterator();
for (int i = 0; i < r.length; i++) {
if (! it.hasNext()) // fewer elements than expected
return Arrays.copyOf(r, i);
r[i] = it.next();
}
return it.hasNext() ? finishToArray(r, it) : r;
}
根据注释,这个方法会返回集合中所有元素, 元素的个数与iterator接口返回的元素个数一致, size()方法只是一个提示的作用. 这样做可以做可以保证在 collection 允许并发修改操作的时候,也能返回正确的值.
可以看到代码使用的是Arrays.copyOf()
方法,即对对象进行复制操作.所以如果, 使用代码测试了一下,toArray
方法已返回的情况下,修改 原始集合中的元素,是不会影响之前toArray
方法返回的结果的.Arrays.copyOf()
只会复制数组中的东西,如果数组里面是对象引用,则复制的就只是引用而已,两个引用指向同一个内存地址,修改集合中的对象的属性, 对toArray
的返回值是可见的.
JumboEnumSet 构造方法.
private long elements[];
JumboEnumSet(Class<E>elementType, Enum[] universe) {
super(elementType, universe);
elements = new long[(universe.length + 63) >>> 6];
}
JumboEnumSet用来存储超过 64 个值的枚举元素. elements中的每个long值表示8个枚举值,所以构建数值的个数就等于 universe.length/64 + (universe.length%64 == 0 ? 0:1) , 也就是源码中的 (universe.length + 63) »> 6.(第一眼没看懂为啥数组个数是这么多,然后睡了个午觉,灵光炸现,突然醒悟).
Queue方法差异
在priorityQueue实现上看:
add()
和offer()
并没有差别.add()
方法中直接调用的offer()
,并没有其他逻辑.remove()
和poll()
,在队列为空时,remove()
抛出NoSuchElementException
异常,poll()
返回null.element()
和peek()
,在队列为空时,element()
抛出NoSuchElementException
异常,peek()
返回null.
Vector和stack
vector和stack为了保证并发正确性,在所有public方法上加上了synchronized关键字,大多数情况下,这种加锁操作是多余的,所以使用ArrayList或者LinkedList的情况较多.
ArrayList 扩容策略
默认扩容老容量的1/2,如果还不够,就使用当前所需的最小容量.
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);
}
ArrayQueue 扩容策略
直接double
AbstractSequentialList
AbstractSequentialList 将 AbstractList 抛出的 NoSuchElementException
异常,都包装成了IndexOutOfBoundsException
.
TreeSet
TreeSet
内部直接持有了一个Map,所有放入的元素都是当作map的key,然后所有key都放置了同一个默认对象,真是机智
HashSet 和 LinkedHashSet
看了下HashSet
的构造器,它既可以构建持有HashMap的Set,也可以构建LinkedHashMap的Set.
LinkedHashSet
继承自HashSet
,并且只会构建持有LinkedHashMap的Set.
所以HashSet
内部元素可能是无序的,但是LinkedHashSet
一定是有序的.