java集合

2016年07月18日

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一定是有序的.