JAVA 集合框架
1、总览图
总览:(虚线箭头为依赖、虚线空心三角为实现、实线空心三角为继承)关于 UML 图表示可看此链接
Collection:
Map:
2、Iterator 、Iterable、ListIterator
Iterable 接口:
实现 Iterable 接口的类说明此类是可被迭代的参考此链接
里面有三个方法
第一个方法是需要实现类返回 Iterator 对象
还包含了一个 default 方法让实现此接口的类可进行 foreach 遍历
另一个 default 是并行迭代器,方便在并行环境进行迭代。
public interface Iterable<T> {
// 返回一个内部元素为T类型的顺序迭代器
Iterator<T> iterator();
// 对Iterable中的元素进行指定的操作
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
// 返回一个内部元素为T类型的并行迭代器
default Spliterator<T> spliterator() {
return Spliterators.spliteratorUnknownSize(iterator(), 0);
}
}
题外话:为何不建议在 foreach 中进行 remove 和 add 操作?
这涉及到迭代器内部类 Itr 修改次数和外部类修改次数不一致的问题具体可参考此链接 与 此链接
Iterator 接口:
迭代器对象包含三个方法:
boolean hasNext() 判断是否有下一个
E next() 返回下一个对象
default void remove() 删除容器中当前遍历到的对象,这个方法是 default 的,若实现类没有实现,则被调用时会抛出不支持删除异常
为何某些集合类只实现 Iterable 接口而不直接实现 Iterator 接口?
Iterator 是基于当前位置的(即当前游标cursor),如果是直接实现 Iterator,那么对于每个集合对象,游标是唯一的,你每次 next() 操作都是操作每个集合实例唯一的游标,这样会有很多操作不灵活。例如如果你要重新从头遍历,则不免要为 Iterator 新增诸如 reset() 方法。但是即便增加了这样的方法,对于每一个集合对象,都只能有一个游标指向,这样很不灵活。而实现了 Iterable 接口的话,则可以每次都生成一个 Iterator 对象,多个迭代器间不会互相干扰!仔细思考这样的设计,可以体会到其精妙之处。
ListIterator 接口
继承自 Iterator 用于拓展对 List 集合的遍历操作,新增了向前遍历的方法
3、List 常用子类
ArrayList(API)底层实现为数组,线程不安全
LinkedList(API)底层实现为链表,线程不安全
Vector(API)底层实现为数组,线程安全
以上三者详细可参考此链接
4、Set 常用子类
HashSet(API)底层实际封装了 HashMap 来进行集合操作、非线程安全、可存 null
TreeSet(API)底层实际封装了 TreeMap 来进行集合操作、非线程安全、不允许存 null
LinkedHashSet(API)底层实际就是 LinkedHashMap、非线程安全、可存 null
可以看到研究 Set 底层的话,实际还是去研究 Map 底层一些类的实现
5、Map 集合常用子类
HashMap(API、参考链接、参考链接2、参考链接3)底层为哈希表+链表/红黑树、无序结构、允许为null、非同步
LinkedHashMap(API、参考链接)底层为 HashMap + 双向链表、有序(访问顺序、插入顺序两种)、允许为null、非同步
TreeMap(API、参考链接)底层为红黑树、有序、不允许为null、非同步
ConcurrentHashMap(API)底层为 CAS+同步锁,数组+链表+红黑树、不允许为null、线程安全
6、Comparable 和 Comparator
1)Comparable 用来定义对象内部的自然排序规则,使得对象具有可比较性,在很多场合需要对象去实现这个接口,例如想要用 TreeSet 集合装自定义对象那么就必须要求对象实现 Comparable 接口,接口里面只有一个 comparaTo 方法。
2)Comparator 也是一个用于比较的接口,对象在不同的情况下可能需要不同的排序行为,可以采用策略模式,Comparator 相当于是策略接口,实现 Comparator 接口的相当于策略实现类,那么实现了 Comparable 接口的类中的 ComparaTo 方法使用用户传入的不同策略实现类(即不同的 Comparator)就可以实现不同的排序行为。