JAVA核心基础之集合
一.集合有两种基础接口:Collection,Map
二.Collection下又分为List ,Set,Queue
三.List中常见的实现类有以下四种
1.ArrayList(非线程安全的)
public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable
...
int newCapacity = oldCapacity + (oldCapacity >> 1);
...
ArrayList–基于数组实现,默认初始容量为10(可用构造方法指定初始容量),以后每次扩容其1.5倍,最大容容量为 Integer.MAX_VALUE - 8。
2.LinkedList(非线程安全的)
public class LinkedList<E> extends AbstractSequentialList<E> implements List<E>, Deque<E>, Cloneable, java.io.Serializable
...
transient int size = 0;
...
基于链表结构实现,因其结构的特殊性,只要内存足够,它的大小可以无限。但是在源码中LinkedList使用了
来记录其大小,也就是说LinkedList也有最大容量限制的,也就是Integer.MAX_VALUE。
3.Vector**(线程安全的)**
public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable
基于数组实现,默认初始容量为10(可通过构造方法指定),最大容量为Integer.MAX_VALUE - 8,其中特殊的是,它有一个包含两个参数的构造方法
public Vector(int initialCapacity, int capacityIncrement)
第一个参数为初始容量,第二个参数为容量增长长度,
增长策略为:
int newCapacity = oldCapacity + ((capacityIncrement > 0) ? capacityIncrement : oldCapacity);
简单来说:如果给定的capacityIncrement > 0,那么就按给定的capacityIncrement来增长容量。
如果不指定,或者知道指定是 <= 0的数,则扩容长度为原来的2倍。
因为其所有public方法都加入了synchronized修饰,所以其线程安全。
4.Stack(线程安全的)
class Stack<E> extends Vector<E>
Stack 是 Vector 的子类,也就是说基于Vector实现,也是线程安全的,和Vector的增容策略是相同的
四.Set常见的实现类有以下三种:
1.HashSet
public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable, java.io.Serializable
..
private transient HashMap<E,Object> map;
...
基于HashMap(HashMap的子类)实现,默认初始容量为16,加载因子为0.75f,每次扩容为原来的两倍(HashMap的扩容策略)
public HashSet(int initialCapacity, float loadFactor)
可以指定初始容量和加载因子,最大容量为1 << 30,大约10亿,元素之间无序,存储也无序。
2.LinkedHashSet
public class LinkedHashSet<E> extends HashSet<E> implements Set<E>, Cloneable, java.io.Serializable
HashSet的子类,元素之间有序,但是存储无序(在内存上不一定连续).
3.TreeSet
public class TreeSet<E> extends AbstractSet<E>
implements NavigableSet<E>, Cloneable, java.io.Serializable
线程不安全的,基于TreeMap实现,是一个有序的集合,TreeSet中将元素按照升序排列,元素自身要实现Comparable接口。
五.Queue常见的实现类有以下几种
1.ArrayBlockingQueue
NIO中的东西不在这讲
2.ArrayDeque(非线程安全)
只提供了一个构造方法,初始容量必须由构造方法指定
3.LinkedBlockingDeque
NIO中的东西不在这讲
4.LinkedList
上面写过了,就不重复了
六.Map
实现Map的数据结构主要由键值对组成,以下主要介绍比较常用的类:
1.HashMap(线程不安全)
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;
默认初始容量16
static final int MAXIMUM_CAPACITY = 1 << 30;
最大容量2^30
static final float DEFAULT_LOAD_FACTOR = 0.75f;
默认装填因子:0.75f
void addEntry(int hash, K key, V value, int bucketIndex) {
...
resize(2 * table.length);
...
}
当每次达到 table.length * 0.75f 时进行扩容,每次扩容为原来的二倍 。
2.Hashtable(线程安全的)
public class Hashtable<K,V>
extends Dictionary<K,V>
implements Map<K,V>, Cloneable, java.io.Serializable {
初始容量为11
线程安全是因为其在所有 public 方法上加了synchronized修饰,锁住了当前对象的调用。
扩容策略:每次扩容 1 倍 + 1
int newCapacity = (oldCapacity << 1) + 1;
3.LinkedHashMap(非线程安全)
public class LinkedHashMap<K,V> extends HashMap<K,V> implements Map<K,V>
初始容量为16,加载因子:0.75f
public LinkedHashMap() {
super();
accessOrder = false;
}
4.ConcurrentHashMap(线程安全的)
本章介绍的是jdk1.7的分段锁的实现,jdk1.8采用了CAS的算法来实现ConCurrentHashMap的线程安全机制,
具体请参考:https://www.jianshu.com/p/21be831e851e
public class ConcurrentHashMap<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>, Serializable
static final float DEFAULT_LOAD_FACTOR = 0.75f;
默认加载因子为0.75f
static final int DEFAULT_INITIAL_CAPACITY = 16;
默认容量16,不可变
static final int DEFAULT_CONCURRENCY_LEVEL = 16;
并发等级 16(在一个瞬间最多允许16个线程同时操作),不可变
static final int MAXIMUM_CAPACITY = 1 << 30;
最大容量 2^30
static final int MIN_SEGMENT_TABLE_CAPACITY = 2;
最小分区表容量
static final int MAX_SEGMENTS = 1 << 16
最大分区个数
每段用一个HashMap来实现存储,这个类比较特殊,在JDK1.6/1.7/1.8中实现各不相同,ConcurrentHashMap采用了分段锁的思想,只有在每个分段内,才存在竞争,而在不同的分段,程序是可以并发执行的,默认分区数量为16.
* Like {@link Hashtable} but unlike {@link HashMap}, this class
* does **not** allow null to be used as a key or value.
和Hashtable有点像,但是和HashMap不同,这个类的键和值都不允许为null。
ConcurrentHashMap对外采用的是异步,但是在内部对每个分区采用的是同步的形式,与HashTable相比提高了其并发操作的能力。
HashMap和HashTable的区别
HashMap是非线程安全的,HashTable是线程安全的,因为HashTable使用了同步代码,所以就效率来说HashTable 小于 HashMap.
HashMap key 和value都允许存null,但是HashTable 不允许null值的存在。
ArrayList 和 LinkedList 区别
ArrayList基于数组实现,元素之间是有序的,在空间上是连续的
LinkedList基于链表实现,元素之间是有序的,在空间上不连续
List 和 set 的区别
List元素之间是有序的,存储也是有序的。
Set元素之间不一定有序的(LinkedHashSet元素之间有序),存储上无序