java集合框架概述
一、前言
工作一年多了,自己也写了些代码学到了些东西,觉得有必要将所学到的知识记录下来。我觉得学习java不管学习到哪个阶段,JDK的源码都是很值得借鉴和学习的,从JDK源码中我们不仅能学习到最原滋原味的底层实现原理并且还能规范我们的代码风格。在java se jdk源码当中,我觉得最值得好好研究的是集合框架部分和java util并发包下的源码。
二、集合整体框架体系

备注说明:
1. Collection是保存单个元素的最大接口
2. Map是保存键值对(key-value)的顶层接口
3. List可以包含重复元素集合,Set类似数据中的集合不允许重复元素
4. List接口维护插入元素的顺序,Set接口不维护插入的顺序
5. Map接口和Collection接口没什么关系
6. Arrays和Collections是数组和集合框架的工具辅助类
7. 集合框架是借助各种数据结构和算法而实现的,数组、链表、散列函数、树、队列。
三、接口说明
Collection接口
public interface Collection<E> extends Iterable<E> {
//由Collection继承Iterator接口便知道所有Collection接口都可以实现迭代操作
// Query Operations
int size();
boolean isEmpty();
boolean contains(Object o);
Iterator<E> iterator();
Object[] toArray();
<T> T[] toArray(T[] a);
// Modification Operations
boolean add(E e);
boolean remove(Object o);
// Bulk Operations
boolean containsAll(Collection<?> c);
boolean addAll(Collection<? extends E> c);
boolean removeAll(Collection<?> c);
boolean retainAll(Collection<?> c);
void clear();
// Comparison and hashing
boolean equals(Object o);
int hashCode();
}
Map接口
/**
*
* java Map接口类似python中的字典,在java中称之为映射。
* Map接口借助hash散列函数来散列存储,所以无法保存插入的顺序,遍历该接口的的元素不太方便。通常借助entrySet方法转换后遍历。
*
*/
public interface Map<K,V> {
// Query Operations
int size();
boolean isEmpty();
boolean containsKey(Object key);
boolean containsValue(Object value);
V get(Object key);
// Modification Operations
V put(K key, V value);
V remove(Object key);
// Bulk Operations
void putAll(Map<? extends K, ? extends V> m);
void clear();
// Views
Set<K> keySet();
Collection<V> values();
Set<Map.Entry<K, V>> entrySet();
interface Entry<K,V> {
K getKey();
V getValue();
V setValue(V value);
boolean equals(Object o);
int hashCode();
public static <K extends Comparable<? super K>, V> Comparator<Map.Entry<K,V>> comparingByKey() {
return (Comparator<Map.Entry<K, V>> & Serializable)
(c1, c2) -> c1.getKey().compareTo(c2.getKey());
}
public static <K, V extends Comparable<? super V>> Comparator<Map.Entry<K,V>> comparingByValue() {
return (Comparator<Map.Entry<K, V>> & Serializable)
(c1, c2) -> c1.getValue().compareTo(c2.getValue());
}
public static <K, V> Comparator<Map.Entry<K, V>> comparingByKey(Comparator<? super K> cmp) {
Objects.requireNonNull(cmp);
return (Comparator<Map.Entry<K, V>> & Serializable)
(c1, c2) -> cmp.compare(c1.getKey(), c2.getKey());
}
public static <K, V> Comparator<Map.Entry<K, V>> comparingByValue(Comparator<? super V> cmp) {
Objects.requireNonNull(cmp);
return (Comparator<Map.Entry<K, V>> & Serializable)
(c1, c2) -> cmp.compare(c1.getValue(), c2.getValue());
}
}
// Comparison and hashing
boolean equals(Object o);
int hashCode();
}
Comparable和Comparator接口
此接口的作用是对集合中的元素进行排序,通常具有排序功能的集合里面存放的元素必须要实现上述接口中的一个,否则就会运行时就会报错,无法排序。
public interface Comparable<T> {
//只有这一个方法
//当前对象和另一个对象比较,该接口实现比较简介和优雅但是场景局限扩展不太方便
public int compareTo(T o);
}
@FunctionalInterface
public interface Comparator<T> {
//该方法是指定两个对象比较,该接口实现比较麻烦一些,但是使用场景更多扩展方便
int compare(T o1, T o2);
boolean equals(Object obj);
}
Comparable和Comparator接口可参考:
http://www.cnblogs.com/sunflower627/p/3158042.html
http://blog.youkuaiyun.com/mageshuai/article/details/3849143
Iterable接口
/**
* Implementing this interface allows an object to be the target of
* the "for-each loop" statement. See
*
* @param <T> the type of elements returned by the iterator
* @since 1.5
* @jls 14.14.2 The enhanced for statement
*/
public interface Iterable<T> {
/**
* Returns an iterator over elements of type {@code T}
* @return an Iterator.
*/
Iterator<T> iterator();
}
只要实现了Iterable接口就可以使用迭代操作遍历元素,在jdk1.5之前使用的是Enumeration枚举遍历。
四、Object对象的equals && hashCode
equals方法与hashCode方法在集合中显得尤为重要,所以,在这里我们也好好的理解一下,为后边的分析打下好的基础。 在每一个覆盖了equals方法的类中,也必须覆盖hashCode方法,因为这样会才能使得基于散列的集合能更好的运作。
Object规范规定
1. 在应用程序的执行期间,只要对象的equals方法的比较操作所用到的信息没有被修改,那么对这同一个对象调用多次hashCode方法都必须始终如一的返回同一个整数。在同一个应用程序的多次执行过程中,每次执行所返回的整数可以不一致。
2. 如果两个对象根据equals方法比较是相等的,那么调用者两个对象中的任意一个对象的hashCode方法都必须产生同样的整数结果。
3. 如果两个对象根据equals方法比较是不相等的,那么调用这两个对象中任意一个对象的hashCode方法,则不一定产生不同的整数结果。
散列函数来理解hashCode和equals关系,数学函数中的单射
相等的对象必须拥有相等的散列码。即equals相等,则hashcode相等,equals不相等,则hashcode不一定相等。一个好的hashCode函数倾向于为不相等的对象产生不相等的散列码,从而提升性能,不好的hashCode函数会让散列表退化成链表,性能急剧下降。
工具类Arrays和Collections
为了更便捷的操作集合的方法JDK提供了Arrays和Collections工具类来实现目的,里面的方法都是静态方法。
参考:
1. https://en.wikipedia.org/wiki/Java_collections_framework
2. http://beginnersbook.com/java-collections-tutorials/
3. http://www.ibm.com/developerworks/cn/java/j-lo-set-operation/index.html
4. https://docs.oracle.com/javase/7/docs/api/java/util/Collection.html
5. http://www.cnblogs.com/leesf456/p/5242814.html
6. http://blog.youkuaiyun.com/softwave/article/details/4166598