闲来无事,有空会继续写下 List LinkedList CopyOnWriteArrayList Set HashSet LinkedHashSet Map HashMap IdentityHashMap LinkedHashMap TreeMap ConcurrentHashMap Queue ArrayBlockingQueue LinkedBlockingQueue ConcurrentLinkedQueue 为节省空间对于非重点代码不作展现
ArrayList底层是由数组组成的一种数据结构,能够进行动态的增删改查html
ArrayList通常用于对数据的存储java
带上问题去找答案数组
从咱们使用ArrayList开始 new ArrayList<>(); public ArrayList() { super(); this.elementData = EMPTY_ELEMENTDATA; } private static final Object[] EMPTY_ELEMENTDATA = {}; private transient Object[] elementData; elementData为储存数据所用容器,经过默认构造方法建立的ArrayList容器为空
public boolean add(E e) { ensureCapacityInternal(size + 1); elementData[size++] = e;//size表示当前使用下表,直接将元素放入到elementData的指定位置 return true; } 指定位置的添加,设计到元素的后移 public void add(int index, E element) { rangeCheckForAdd(index);//检查是否超出 ensureCapacityInternal(size + 1); // Increments modCount!! System.arraycopy(elementData, index, elementData, index + 1, size - index);//元素后裔 elementData[index] = element; size++; } private void rangeCheckForAdd(int index) { if (index > size || index < 0) throw new IndexOutOfBoundsException(outOfBoundsMsg(index));//很常见的异常 }
public E remove(int index) { rangeCheck(index); checkForComodification(); E result = parent.remove(parentOffset + index); this.modCount = parent.modCount; this.size--; return result; } final void checkForComodification() { if (modCount != expectedModCount)//针对在对于list进行遍历时进行其余操做,modCount会改变,而expectedModCount值在listInterator时给定的会抛出异常 throw new ConcurrentModificationException(); }
public E get(int index) { rangeCheck(index);//这就没啥好多的了 return elementData(index); }
public boolean add(E e) { ensureCapacityInternal(size + 1); // Increments modCount!! elementData[size++] = e; return true; } private void ensureCapacityInternal(int minCapacity) { if (elementData == EMPTY_ELEMENTDATA) { //若是容器为空,初始化容器,两个值中取最大值 minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); } ensureExplicitCapacity(minCapacity); } private void ensureExplicitCapacity(int minCapacity) { modCount++;//操做次数+1 // 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);// oldCapacity + oldCapacity*0.5 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);//扩容 } private static int hugeCapacity(int minCapacity) { if (minCapacity < 0) // overflow //若是为负数抛出内存溢出错误 throw new OutOfMemoryError(); return (minCapacity > MAX_ARRAY_SIZE) ? //尚未为负数,那么元素最大大小改成int的最大值,注意MAX_ARRAY_SIZE为最大值-8 Integer.MAX_VALUE : MAX_ARRAY_SIZE; } private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
ArrayList不是线程安全的安全
以添加为例 elementData[size++] = e; 一个 ArrayList ,在添加一个元素的时候,它可能会有两步来完成: 1. 在 Items[Size] 的位置存放此元素; 2. 增大 Size 的值。 在单线程运行的状况下,若是 Size = 0,添加一个元素后,此元素在位置 0,并且 Size=1; 而若是是在多线程状况下,好比有两个线程,线程 A 先将元素存放在位置 0。可是此时 CPU 调度线程A暂停,线程 B 获得运行的机会。线程B也向此 ArrayList 添加元素,由于此时 Size 仍然等于 0 (注意哦,咱们假设的是添加一个元素是要两个步骤哦,而线程A仅仅完成了步骤1),因此线程B也将元素存放在位置0。而后线程A和线程B都继续运行,都增长 Size 的值。 那好,如今咱们来看看 ArrayList 的状况,元素实际上只有一个,存放在位置 0,而 Size 却等于 2。这就是“线程不安全”了。