容器主要包括 Collection 和 Map 两种,Collection 存储着对象的集合,而 Map 存储着键值对的映射表。Java容器概览 - 图2Java容器概览 - 图3

集合的类图图片.png

上图是目前我们已学的集合类图,大概可以看出以下几点:

  • 每个接口做的事情非常明确,比如:Serializable 只负责序列化,Cloneable 只负责拷贝,Map 只负责定义 Map 的接口,整个图看起来虽然接口众多,但职责都很清晰。
  • 复杂功能通过接口的继承来实现,比如:ArrayList 通过实现了 Serializable、Cloneable、RandomAccess、AbstractList、List 等接口,从而拥有了序列化、拷贝、对数组各种操作定义等各种功能。

上述设计的最大好处是:每个接口能力职责单一,众多的接口变成了接口能力的积累,假设我们想再实现一个数据结构类,我们就可以从这些已有的能力接口中,挑选出能满足需求的能力接口,进行一些简单的组装。

集合在 Java 7 和 8 的不同 & 改进

所有集合新增forEach方法

List、Set、Map 在 Java 8 版本中都增加了 forEach()。
ArrayList 的 forEach() 的底层源码实现如下:

  1. @Override
  2. public void forEach(Consumer<? super E> action) {
  3. Objects.requireNonNull(action);
  4. final int expectedModCount = modCount;
  5. @SuppressWarnings("unchecked")
  6. final E[] elementData = (E[]) this.elementData;
  7. final int size = this.size;
  8. for (int i=0; modCount == expectedModCount && i < size; i++) {
  9. action.accept(elementData[i]);
  10. }
  11. if (modCount != expectedModCount) {
  12. throw new ConcurrentModificationException();
  13. }
  14. }

forEach() 是被继承实现的,该方法是被定义在 Iterable 接口上的,Java 7 和 8 的 ArrayList 都实现了该接口,但在 Java 7 的 ArrayList 并没有发现有实现该方法,编译器也没有报错,这个主要是因为 Iterable 接口的 forEach() 被加上了 default 关键字,这个关键字只会出现在接口类中,被该关键字修饰的方法无需强制要求子类继承,但需要在接口中有默认实现。Iterable 接口中的 forEach 的底层源码实现如下:

  1. default void forEach(Consumer<? super T> action) {
  2. Objects.requireNonNull(action);
  3. for (T t : this) {
  4. action.accept(t);
  5. }
  6. }

List、Set、Map 接口中很多新增的方法都是这么做的,通过 default 关键字,让 Java 7 的集合子类无需实现 Java 8 中新增的方法。

ArrayList的不同

List 其它方面 Java7 和 8 并没有改动。
ArrayList 无参初始化时,Java 7 是直接初始化 10 的大小,Java 8 去掉了这个逻辑。
Java 8 中初始化时是空数组,在第一次 add 时才开始按照 10 进行扩容。
源码对比如下:
图片.png图片.png

HashMap的不同

  • 和 ArrayList 一样,Java 8 中 HashMap 在无参构造器中,丢弃了 Java 7 中直接把数组初始化 16 的做法,而是采用在第一次新增的时候,才开始扩容数组大小
  • hash 算法计算公式不同,Java 8 的 hash 算法更加简单,代码更加简洁

Map的综合知识

  • Java 8 的 HashMap 增加了红黑树的数据结构,一般 key 是 Java 的 API 时,比如说 String 这些 hashcode 实现很好的 API,很少出现链表转化成红黑树的情况,因为 String 这些 API 的 hash 算法够好了,只有当 key 是我们自定义的类,而且我们重写的 hashcode 算法非常糟糕时,才会真正使用到红黑树,提高我们的检索速度。
  • 也是因为 Java 8 新增了红黑树,所以几乎所有操作数组的方法的实现,都发生了变动,比如说 put、remove 等操作,可以说 Java 8 的 HashMap 几乎重写了所有方法,所以 Java 7 的很多问题都被 Java 8 解决了,比如:扩容时极小概率死锁,丢失数据等。
  • 新增了一些好用的方法

Map的综合知识

LinkedHashMap的不同

由于 Java8 的底层数据有变动,导致 HashMap 操作数据的方法几乎重写,也使 LinkedHashMap 的实现名称上有差异,但原理相同,