JAVA常用集合解析
ArrayList : 
底层基于数组实现,在使用add方法添加元素时,首先校验集合容量,将新添加的值放入集合尾部并进行长度加一,进行自动扩容,扩容的操作时将数据中的所有元素复制到新的集合中。
在指定位置添加元素时
 public void add(int index, E element) {
		检查索引是否为0或者超出集合长度
        rangeCheckForAdd(index);
		将集合扩容,长度加1
        ensureCapacityInternal(size + 1);  // Increments modCount!!
		//从指定index位置开始将其后元素向后移动一位,空余出index位置
        System.arraycopy(elementData, index, elementData, index + 1,
                         size - index);
			给index赋值
        elementData[index] = element;
        size++;
    }
	
	从 ensureCapacityInternal 延申到此方法
	 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);
    }
  由此可见在创建arrayList集合时最好提前预估长度,以免不必要的扩容,提高性能。
  
  transient Object[] elementData;  集合中加transient是防止被自动序列化。因为arrayList是基于动态数组,可能不会使用数组的全部空间,在它的类中重写了序列化和反序列化方法
 HashMap: 线程不安全, 默认大小为16 负载因子0.75 当集合中元素大于 16*0.75时就会发生扩容。
            使用put方法后,会计算出key的hash值,然后根据数组长度取模运算出存放下标。
			              在数组长度有限的情况下会出现计算下标一致的情况(hash冲突)那么会在此
						  形成链表,采用头插法插入。当hash冲突严重时就会形成很长的链表,导致
						  查询效率低下。
						  在jdk1.8中,判断如果链表中元素长度如果大于8那么就将
						  链表转换为红黑树,从而优化的查询效率,由O(n)变为0(logn)
						  
			get方法,使用key值计算下标,如果下标相同,遍历链表调用equals()方法比较。
			在多线程中使用时,并发扩容时会导致形成环形链表,假如在寻找一个不存在的key时找到环形链表的index会出现死循环。
未完待续。。
 
                     
                    
                 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号