Java集合类的简单结构图:
事实上Collection的父接口为 Iterable
目的:简单的了解一下Java常用集合的特性以及内部实现。
参考博客: http://blog.sina.com.cn/s/blog_3fba24680100y2yr.html
常用List集合:
特性:
有顺序的,元素可以重复;
遍历:for,迭代;
排序:Comparable Comparator Collections.sort()
ArrayList:
用数组实现的List;
特点:查询效率高,增删效率低 轻量级 线程不安全;
部分源码分析:
构造:
这段源代码表示的是一个ArrayList的内部实现为一个Object数组,重载的两个构造方法,默认长度为10。
增加元素:
添加对象的代码块,size表示数组长度。后一个为添加集合对象的代码块。
删除元素:
首先检查下标是否越界,List删除后会自懂向前移动下标向前移动一位又是通过 System.arraycopy(elementData, index+1, elementData, index,numMoved);来实现。
那么ArrayList是怎么实现容量自增的呢?
ensureCapacityInternal(size+numNew)表示数组容量的自增函数,调用下面的函数:
LinkedList:
底层用双向循环链表实现的List;
特点:查询效率低,增删效率高;
构造:
对于定义来说没有数组,却有个Node对象来看看静态内部类Node的结构:
双向链表结构更像是一群牵着手的孩子只知道前后是谁。
添加元素:
就是一个Node持有另个一Node的引用,形成以个链条。
删除元素:
先找到元素再赋值为null,并接上前面的。
Vector:
底层用数组实现List接口的另一个类;
特点:重量级,占据更多的系统开销,线程安全;
Vector与ArrayList基本上一致,最大的差别于在一些方法上使用了synchronized关键字,使其变成线程安全。
----------------------------------------------------------------------------------
Set:
无顺序的,元素不可重复(值不相同);
遍历:迭代;
排序:SortedSet
HashSet:
采用哈希算法来实现Set接口;
唯一性保证:重复对象equals方法返回为true;
重复对象hashCode方法返回相同的整数,不同对象hashCode尽量保证不同(提高效率);
构造:
实际上的HashSet内部的实现为一个HashMap(下面看看HashMap的组成)。
添加元素:
由源代码块可以看出HashSet添加一个元素时,添加的值为HashMap的Key值,而一个Object对象却为一个Value值。
删除元素:
那么HashSet无序不重复的属性则来自于HashMap。
TreeSet:
在元素添加的同时,进行排序。也要给出排序规则;
唯一性保证:根据排序规则,compareTo方法返回为0,就可以认定两个对象中有一个是重复对象。
结构:
----------------------------------------------------------------------------------
Map:
元素是键值对:key唯一不可重复,value可重复;
遍历:先迭代遍历key的集合,再根据key得到value;
SortedMap:元素自动对key排序
HashMap:
轻量级,线程不安全,允许key或者value是null;
构造:
从构造方法分可以看出其为一个Entry数组
Entry主要属性:
该源码片段可以看出Entry以及key值一旦赋值就无法更改。
添加元素:
红色部分对于重复对象的比较,使用了key的hashcode,key指向的地址,以及其值是否相等。
容量自增:
Hashtable:
重量级,线程安全,不允许key或者value是null;
从源码可以看出与HashMap很相识,这是Hashmap为其轻量级的实现。
大量带有实际操作性的方法都为synchronized修饰。
Properties:Hashtable的子类,key和value都是String,同样为线程安全。
TreeMap:
集合是指一个对象可以容纳了多个对象(不是引用),这个集合对象主要用来管理维护一系列相似的对象。

事实上Collection的父接口为 Iterable
目的:简单的了解一下Java常用集合的特性以及内部实现。
参考博客: http://blog.sina.com.cn/s/blog_3fba24680100y2yr.html
常用List集合:
特性:
有顺序的,元素可以重复;
遍历:for,迭代;
排序:Comparable Comparator Collections.sort()
ArrayList:
用数组实现的List;
特点:查询效率高,增删效率低 轻量级 线程不安全;
部分源码分析:
构造:
- private transient Object[] elementData;
- public ArrayList(int initialCapacity) {
- super();
- if (initialCapacity < 0)
- throw new IllegalArgumentException("Illegal Capacity: "+
- initialCapacity);
- this.elementData = new Object[initialCapacity];
- }
- public ArrayList() {
- this(10);
- }
private transient Object[] elementData;
public ArrayList(int initialCapacity) {
super();
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
this.elementData = new Object[initialCapacity];
}
public ArrayList() {
this(10);
}
这段源代码表示的是一个ArrayList的内部实现为一个Object数组,重载的两个构造方法,默认长度为10。
增加元素:
- public boolean add(E e) {
- ensureCapacityInternal(size + 1); // Increments modCount!!
- elementData[size++] = e;
- return true;
- }
- public boolean addAll(Collection<? extends E> c) {
- Object[] a = c.toArray();
- int numNew = a.length;
- ensureCapacityInternal(size + numNew); // Increments modCount
- System.arraycopy(a, 0, elementData, size, numNew);
- size += numNew;
- return numNew != 0;
- }
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
public boolean addAll(Collection<? extends E> c) {
Object[] a = c.toArray();
int numNew = a.length;
ensureCapacityInternal(size + numNew); // Increments modCount
System.arraycopy(a, 0, elementData, size, numNew);
size += numNew;
return numNew != 0;
}
添加对象的代码块,size表示数组长度。后一个为添加集合对象的代码块。
删除元素:
- public E remove(int index) {
- rangeCheck(index);
- modCount++;
- E oldValue = elementData(index);
- int numMoved = size - index - 1;
- if (numMoved > 0)
- System.arraycopy(elementData, index+1, elementData, index,
- numMoved);
- elementData[--size] = null; // Let gc do its work
- return oldValue;
- }
public E remove(int index) {
rangeCheck(index);
modCount++;
E oldValue = elementData(index);
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // Let gc do its work
return oldValue;
}
首先检查下标是否越界,List删除后会自懂向前移动下标向前移动一位又是通过 System.arraycopy(elementData, index+1, elementData, index,numMoved);来实现。
那么ArrayList是怎么实现容量自增的呢?
ensureCapacityInternal(size+numNew)表示数组容量的自增函数,调用下面的函数:
- 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);
- }
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);
}
LinkedList:
底层用双向循环链表实现的List;
特点:查询效率低,增删效率高;
构造:
- transient Node<E> first;
- transient Node<E> last;
- public LinkedList() {
- }
- public LinkedList(Collection<? extends E> c) {
- this();
- addAll(c);
- }
transient Node<E> first;
transient Node<E> last;
public LinkedList() {
}
public LinkedList(Collection<? extends E> c) {
this();
addAll(c);
}
对于定义来说没有数组,却有个Node对象来看看静态内部类Node的结构:
- private static class Node<E> {
- E item;
- Node<E> next;
- Node<E> prev;
- Node(Node<E> prev, E element, Node<E> next) {
- this.item = element;
- this.next = next;
- this.prev = prev;
- }
- }
private static class Node<E> {
E item;
Node<E> next;
Node<E> prev;
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}
双向链表结构更像是一群牵着手的孩子只知道前后是谁。
添加元素:
- void linkLast(E e) {
- final Node<E> l = last;
- final Node<E> newNode = new Node<>(l, e, null);
- last = newNode;
- if (l == null)
- first = newNode;
- else
- l.next = newNode;
- size++;
- modCount++;
- }
void linkLast(E e) {
final Node<E> l = last;
final Node<E> newNode = new Node<>(l, e, null);
last = newNode;
if (l == null)
first = newNode;
else
l.next = newNode;
size++;
modCount++;
}
就是一个Node持有另个一Node的引用,形成以个链条。
删除元素:
- E unlink(Node<E> x) {
- // assert x != null;
- final E element = x.item;
- final Node<E> next = x.next;
- final Node<E> prev = x.prev;
- if (prev == null) {
- first = next;
- } else {
- prev.next = next;
- x.prev = null;
- }
- if (next == null) {
- last = prev;
- } else {
- next.prev = prev;
- x.next = null;
- }
- x.item = null;
- size--;
- modCount++;
- return element;
E unlink(Node<E> x) {
// assert x != null;
final E element = x.item;
final Node<E> next = x.next;
final Node<E> prev = x.prev;
if (prev == null) {
first = next;
} else {
prev.next = next;
x.prev = null;
}
if (next == null) {
last = prev;
} else {
next.prev = prev;
x.next = null;
}
x.item = null;
size--;
modCount++;
return element;
}
先找到元素再赋值为null,并接上前面的。
Vector:
底层用数组实现List接口的另一个类;
特点:重量级,占据更多的系统开销,线程安全;
Vector与ArrayList基本上一致,最大的差别于在一些方法上使用了synchronized关键字,使其变成线程安全。
----------------------------------------------------------------------------------
Set:
无顺序的,元素不可重复(值不相同);
遍历:迭代;
排序:SortedSet
HashSet:
采用哈希算法来实现Set接口;
唯一性保证:重复对象equals方法返回为true;
重复对象hashCode方法返回相同的整数,不同对象hashCode尽量保证不同(提高效率);
构造:
- private transient HashMap<E,Object> map;
- private static final Object PRESENT = new Object();
- public HashSet() {
- map = new HashMap<>();
- }
private transient HashMap<E,Object> map;
private static final Object PRESENT = new Object();
public HashSet() {
map = new HashMap<>();
}
实际上的HashSet内部的实现为一个HashMap(下面看看HashMap的组成)。
添加元素:
- public boolean add(E e) {
- return map.put(e, PRESENT)==null;
- }
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
由源代码块可以看出HashSet添加一个元素时,添加的值为HashMap的Key值,而一个Object对象却为一个Value值。
删除元素:
- public boolean remove(Object o) {
- return map.remove(o)==PRESENT;
- }
public boolean remove(Object o) {
return map.remove(o)==PRESENT;
}
那么HashSet无序不重复的属性则来自于HashMap。
TreeSet:
在元素添加的同时,进行排序。也要给出排序规则;
唯一性保证:根据排序规则,compareTo方法返回为0,就可以认定两个对象中有一个是重复对象。
结构:
- private transient NavigableMap<E,Object> m;
- private static final Object PRESENT = new Object();
private transient NavigableMap<E,Object> m;
private static final Object PRESENT = new Object();
----------------------------------------------------------------------------------
Map:
元素是键值对:key唯一不可重复,value可重复;
遍历:先迭代遍历key的集合,再根据key得到value;
SortedMap:元素自动对key排序
HashMap:
轻量级,线程不安全,允许key或者value是null;
构造:
- transient Entry[] table;
- public HashMap(int initialCapacity, float loadFactor) {
- if (initialCapacity < 0)
- throw new IllegalArgumentException("Illegal initial capacity: " +
- initialCapacity);
- if (initialCapacity > MAXIMUM_CAPACITY)
- initialCapacity = MAXIMUM_CAPACITY;
- if (loadFactor <= 0 || Float.isNaN(loadFactor))
- throw new IllegalArgumentException("Illegal load factor: " +
- loadFactor);
- // Find a power of 2 >= initialCapacity
- int capacity = 1;
- while (capacity < initialCapacity)
- capacity <<= 1;
- this.loadFactor = loadFactor;
- threshold = (int)(capacity * loadFactor);
- [color=red]table = new Entry[capacity];[/color]
- init();
- }
transient Entry[] table;
public HashMap(int initialCapacity, float loadFactor) {
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal initial capacity: " +
initialCapacity);
if (initialCapacity > MAXIMUM_CAPACITY)
initialCapacity = MAXIMUM_CAPACITY;
if (loadFactor <= 0 || Float.isNaN(loadFactor))
throw new IllegalArgumentException("Illegal load factor: " +
loadFactor);
// Find a power of 2 >= initialCapacity
int capacity = 1;
while (capacity < initialCapacity)
capacity <<= 1;
this.loadFactor = loadFactor;
threshold = (int)(capacity * loadFactor);
[color=red]table = new Entry[capacity];[/color]
init();
}
从构造方法分可以看出其为一个Entry数组
Entry主要属性:
- final K key;
- V value;
- Entry<K,V> next;
final K key;
V value;
Entry<K,V> next;
该源码片段可以看出Entry以及key值一旦赋值就无法更改。
添加元素:
- public V put(K key, V value) {
- if (key == null)
- return putForNullKey(value);
- int hash = hash(key.hashCode());
- int i = indexFor(hash, table.length);
- for (Entry<K,V> e = table[i]; e != null; e = e.next) {
- Object k;
- if ([color=red]e.hash == hash && ((k = e.key) == key || key.equals(k)[/color])) {
- V oldValue = e.value;
- e.value = value;
- e.recordAccess(this);
- return oldValue;
- }
- }
- modCount++;
- addEntry(hash, key, value, i);
- return null;
public V put(K key, V value) {
if (key == null)
return putForNullKey(value);
int hash = hash(key.hashCode());
int i = indexFor(hash, table.length);
for (Entry<K,V> e = table[i]; e != null; e = e.next) {
Object k;
if ([color=red]e.hash == hash && ((k = e.key) == key || key.equals(k)[/color])) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
}
modCount++;
addEntry(hash, key, value, i);
return null;
}
红色部分对于重复对象的比较,使用了key的hashcode,key指向的地址,以及其值是否相等。
容量自增:
- void resize(int newCapacity) {
- Entry[] oldTable = table;
- int oldCapacity = oldTable.length;
- if (oldCapacity == MAXIMUM_CAPACITY) {
- threshold = Integer.MAX_VALUE;
- return;
- }
- Entry[] newTable = new Entry[newCapacity];
- transfer(newTable);
- table = newTable;
- threshold = (int)(newCapacity * loadFactor);
- }
void resize(int newCapacity) {
Entry[] oldTable = table;
int oldCapacity = oldTable.length;
if (oldCapacity == MAXIMUM_CAPACITY) {
threshold = Integer.MAX_VALUE;
return;
}
Entry[] newTable = new Entry[newCapacity];
transfer(newTable);
table = newTable;
threshold = (int)(newCapacity * loadFactor);
}
Hashtable:
重量级,线程安全,不允许key或者value是null;
从源码可以看出与HashMap很相识,这是Hashmap为其轻量级的实现。
大量带有实际操作性的方法都为synchronized修饰。
Properties:Hashtable的子类,key和value都是String,同样为线程安全。
- public synchronized Object setProperty(String key, String value) {
- return put(key, value);
- }
public synchronized Object setProperty(String key, String value) {
return put(key, value);
}
TreeMap:
集合是指一个对象可以容纳了多个对象(不是引用),这个集合对象主要用来管理维护一系列相似的对象。