Collection 类图
List接口
有序的:有序插入,可以通过下标访问元素,元素可以重复。
ArrayList
基于数组结构实现,查询快,增加删除效率慢。
源码分析:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 public class ArrayList <E> extends AbstractList <E> implements List <E>, RandomAccess, Cloneable, java.io.Serializable private static final int DEFAULT_CAPACITY = 10 ; transient Object[] elementData; private int size; private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; public ArrayList () { this .elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; } public boolean add (E e) { ensureCapacityInternal(size + 1 ); elementData[size++] = e; return true ; } private void ensureCapacityInternal (int minCapacity) { ensureExplicitCapacity(calculateCapacity(elementData, minCapacity)); } private static int calculateCapacity (Object[] elementData, int minCapacity) { if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { return Math.max(DEFAULT_CAPACITY, minCapacity); } return minCapacity; } private void ensureExplicitCapacity (int minCapacity) { modCount++; if (minCapacity - elementData.length > 0 ) grow(minCapacity); } private void grow (int minCapacity) { int oldCapacity = elementData.length; int newCapacity = oldCapacity + (oldCapacity >> 1 ); if (newCapacity - minCapacity < 0 ) newCapacity = minCapacity; if (newCapacity - MAX_ARRAY_SIZE > 0 ) newCapacity = hugeCapacity(minCapacity); elementData = Arrays.copyOf(elementData, newCapacity); } private static int hugeCapacity (int minCapacity) { if (minCapacity < 0 ) throw new OutOfMemoryError (); return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE; } } public class Arrays { public static <T> T[] copyOf(T[] original, int newLength) { return (T[]) copyOf(original, newLength, original.getClass()); } public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T []> newType) { @SuppressWarnings("unchecked") T[] copy = ((Object)newType == (Object)Object[].class) ? (T[]) new Object [newLength] : (T[]) Array.newInstance(newType.getComponentType(), newLength); System.arraycopy(original, 0 , copy, 0 , Math.min(original.length, newLength)); return copy; } } public final class System { public static native void arraycopy (Object src, int srcPos, Object dest, int destPos, int length) ;}
Set接口 Map接口 类图
HashMap 和 HashTable
方面
区别
线程安全
HashMap非线程安全,HashTable内部方法使用了 synchronized
修饰,线程安全。推荐使用 ConcurrentHashMap
效率
因为线程安全问题,HashMap 效率更高一点,不推荐使用 HashTable。
对空键和空值的支持
HashMap可以存储 null 的 key 和 value,但是只能存在一个键为 null,null 作为值可以有多个;HashTable不允许null key 和null value,否则会抛出 NullPointerException
。
初始容量和扩容大小
HashTable默认初始容量大小为 11
,每次扩容大小为原来的两倍加一(2n + 1
);HashMap默认初始容量为 16
,每次扩容大小为原来的两倍(2n
),HashMap的容量始终是2的幂次方大小 (tableSizeFor()
方法保证)。
底层数据结构
JDK1.8以后,HashMap底层数据结构变为 数组 + 链表 + 红黑树
,当链表长度大于阈值(8
)时,如果数组长度小于64
,那么会先进行数组的扩容,否则就会将链表转换成红黑树,从而减少搜索时间,提高效率。HashTable 始终是 数组 + 链表
。
HashMap 常用方法
方法
描述
put(K key,V value)
向HashMap集合中添加元素
get(Object key)
返回指定键所映射的值,没有该key 对应的值则返回null
size()
返回HashMap集合中的元素数量
clear()
清空HashMap集合
isEmpty()
判断HashMap集合中是否有数据,如果没有则返回true,否则返回false
remove(Object key)
删除HashMap集合中键为key 的数据并返回其所对应value 值
values()
返回HashMap集合中所有value组成的以Collection数据类型格式数据例如:Collection con = map.values();
getOrDefault()
获取指定 key 对应对 value,如果找不到 key ,则返回设置的默认值
keySet()
返回 hashMap 中所有 key 组成的集合视图。
遍历方式 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 public class Main { public static void main (String[] args) { Map<Integer, Integer> map = new HashMap <Integer, Integer>(); for (int i = 0 ; i < 10 ; i++) { map.put(i, i); } Set<Integer> keySets = map.keySet(); for (Integer keySet : keySets) { System.out.print(keySet + " " ); } Collection<Integer> values = map.values(); for (Integer value : values) { System.out.print(value + " " ); } Set<Map.Entry<Integer, Integer>> sets = map.entrySet(); for (Map.Entry<Integer, Integer> set : sets) { System.out.println("Key:" + set.getKey() + " value:" + set.getValue()); } } }
底层数据结构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 static class Node <K,V> implements Map .Entry<K,V> { final int hash; final K key; V value; Node<K,V> next; Node(int hash, K key, V value, Node<K,V> next) { this .hash = hash; this .key = key; this .value = value; this .next = next; }