1. Collection接口->List接口:接口特点是插入元素有序,元素可重复。主要的实现有:
a. ArrayList实现类:特点是-增加/删除慢,查询快;原理是-不错是使用数组实现的,默认初始大小为10;每次增长当前长度的50%。
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); }b. LinkList实现类:特点是-增加/删除快,查询慢;原理是-使用链表实现的并实现Deque接口,支持双向队列。
c. Vector实现类: 特点是-增加/删除慢,查询快;原理是-使用数组实现且同步的。
public synchronized boolean add(E e) { modCount++; ensureCapacityHelper(elementCount + 1); elementData[elementCount++] = e; return true; }
d. Stack实现类:stack类继承自Vector类,增加堆栈的常用操作。Deque接口提供了双向队列,双向队列可以实现堆栈的操作,官方更推荐使用Deque来实现堆栈操作而非Stack实现类。
2. Collection接口->Set接口:元素不能重复,重复的元素会被覆盖。
a. HashSet实现类:由Hash表支持,实际上是HashMap实现的。Set的值实际上时HashMap的key, HashMap的value是Object常量。
public HashSet() { map = new HashMap<>(); }
public boolean add(E e) { return map.put(e, PRESENT)==null; }
b. LinkedHashSet实现类:特点是-有顺序的既能保证插入的顺序也能保证迭代的顺序,线程不安全,初始大小为16;原理是-由Hash表和链接列表实现的,底层是Set接口和LinkedHashMap实现的,LinkedHashMap是在HashMap的基础上增加了before, after链表指针包含所有条目的双重链表来保证顺序。
static class Entry<K,V> extends HashMap.Node<K,V> { Entry<K,V> before, after; Entry(int hash, K key, V value, Node<K,V> next) { super(hash, key, value, next); } }
c. TreeSet实现类:特点是有序、非同步集合,多线程之间可以使用Collections.synchroinzedMap()来实现同步,运行速度比Hash集合慢,内部对元素操作的时间复杂度为O(logN),而HashMap/HashSet为O(1)。实现原理是-使用TreeMap实现的,TreeMap是使用红黑树实现的。
3. Map接口:特点是-提供键值映射关系,每一个键最多只能映射到一个值。
a. HashMap实现类:特点是-插入、查询、删除比较快,时间复杂度是大O(1);原理是-使用hash表实现,即结合了数组和链表数据结构的有点。哈希表最常见的实现方法叫拉链法,可以理解为“”链表的数组“”。hash表的数组中存储的是一个链表的头结点。默认初始容量《Entry数组》16,加载因子是0.75.一般的存储规则是通过hash(key)%len获得。里面有两个概念需要了解,一个是Hash碰撞一个是加载因子。
b. LinkedHashMap实现类:特点是-继承了HashMap效率低于HashMap的插入、删除、查询但是有序的,使用双重链表<Entry结构类型的 before, after>来保证数据的有序性。线程不安全。
c. TreeMap实现类:特点是有序、非同步集合,多线程之间可以使用Collections.synchroinzedMap()来实现同步,运行速度比Hash集合慢,内部对元素操作的时间复杂度为O(logN),而HashMap/HashSet为O(1)。实现原理是使用红黑树实现的。可参考这两篇文章: http://blog.youkuaiyun.com/ghsau/article/details/16890151 http://blog.youkuaiyun.com/vking_wang/article/details/14166593
d.WeakHashMap实现类:特点是-以弱键实现的基于哈希表的Map,当键不在正常使用时将自动移除条目。实现原理是-了解弱引用需要了解java.lang.ref中的引用对象类,。常用于检测对象状态以及对于很可能被回收,而且被防止在static字段里的全局对象。实现原理-通过WeakReference和ReferenceQueue实现的。
e.EumMap实现类:特点是-与枚举类型键一起使用的专用Map实现,枚举映射在内部是一个数组,数据结构紧凑高效。不允许null键,可以存在null值。和大多数collection一样,线程不同步。
public class EnumMapDemo { @Test public void em(){ EnumMap<EnumKey, Object> map = new EnumMap(EnumKey.class); map.put(EnumKey.LISI, "李四"); map.put(EnumKey.ZHANSAN, "张三"); for (Map.Entry<EnumKey, Object> enumKeyObjectEntry : map.entrySet()) { System.out.println(enumKeyObjectEntry.getKey() + " : " + enumKeyObjectEntry.getValue()); } } enum EnumKey { ZHANSAN, LISI; } }
4. concurrent并发包:
a. ConcurrentMap接口:提供其他原子putIfAbsent、remove、replace方法的Map。特性是-保持内存一致性效果;原理是使用了同步代码块。如下代码,如果使用ConcurrentHashMap就不会出问题,如果使用HashMap非同步,系统报错java.util.ConcurrentModificationException。代码如下:
public class MyTest { private int num = 0; // ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap(); Map<String, Integer> map = new HashMap(); @Test public void mt(){ for (int i = 0; i < 100; i++) new Thread(new Runnable() { @Override public void run() { num = num + 1; if (num%2==0) num = num + 2; map.put("a"+num, num); } }).start(); for (Map.Entry<String, Integer> stringIntegerEntry : map.entrySet()) { System.out.println(stringIntegerEntry.getKey() + " : " + stringIntegerEntry.getValue()); } } }
b. CopyOnWriteArraySet实现类:特点是-线程同步,在对数据进行并发读的时候不加锁提高数据读取效率。实现原理是-当数据内容要被修改的时候,会把真正内容Copy出去一个新的副本然后再修改一种懒惰策略。这种特性可以在非常多的并发场景中使用。并发容器多用于读多写少的并发场景。比如系统白名单、黑名单、商品类目的访问和更新场景。CopyOnWrite有很多优点,当然也有很多缺点: 由实现原理可以知道复制时内容占用是个问题、数据实时性也是一个问题。另详细介绍请参数 http://ifeve.com/java-copy-on-write/#more-10403