JDK源码之集合

一 初识

1,在这里,集合类分为了Map和Collection两个大的类别。

2,处于图片左上角的那一块灰色里面的四个类(Dictionary、HashTable、Vector、Stack)都是线程安全的,可是它们都是JDK的老的遗留类。如今基本都不怎么使用了,都有了相应的取代类。当中Map是用来取代图片中左上角的那个Dictionary抽象类(Map的官方文档里面有说明)。官方推荐使用Map接口来取代它。相同对于HashTable。官方推荐ConcurrentHashMap来取代。接着以下的Vector是List以下的一个实现类。

3,接着最上面的粉红色部分是集合类全部接口关系图。当中Map的结构比較简单,而Collection的结构就相对复杂一些。Collection有三个继承接口:List、Queue和Set。接下来的绿色部分则是集合类的主要实现类了。这也是我们最常常使用的集合类了。

4,依照实现接口分类

实现Map接口的有:EnumMap、IdentityHashMap、HashMap、LinkedHashMap、WeakHashMap、TreeMap,
实现List接口的有:ArrayList、LinkedList
实现Set接口的有:HashSet、LinkedHashSet、TreeSet
实现Queue接口的有:PriorityQueue、LinkedList、ArrayQueue

5,依据底层实现的数据结构分类

底层以数组的形式实现:EnumMap、ArrayList、ArrayQueue
底层以链表的形式实现:LinkedHashSet、LinkedList、LinkedHashMap
底层以hash table的形式实现:HashMap、HashSet、LinkedHashMap、LinkedHashSet、WeakHashMap、IdentityHashMap
底层以红黑树的形式实现:TreeMap、TreeSet
底层以二叉堆的形式实现:PriorityQueue

6,最下方的一个整块都是java.util.concurrent包里面的类,依照包名我们就能够知道这个包里面的类都是用来处理Java编程中各种并发场景的。

7,下面这张图,是常用的集合的基本特性:

8,Hashtable VS HashMap

  • Hashtable是线程安全的,它的每个方法中都加入了Synchronize方法。在多线程并发的环境下,可以直接使用Hashtable,不需要自己为它的方法实现同步
  • HashMap不是线程安全的,在多线程并发的环境下,可能会产生死锁等问题。多线程环境下使用HashMap时就必须要自己增加同步处理
  • 虽然HashMap不是线程安全的,但是它的效率会比Hashtable要好很多。这样设计是合理的。在我们的日常使用当中,大部分时间是单线程操作的。HashMap把这部分操作解放出来了。当需要多线程操作的时候可以使用线程安全的ConcurrentHashMap。ConcurrentHashMap虽然也是线程安全的,但是它的效率比Hashtable要高好多倍。因为ConcurrentHashMap使用了分段锁,并不对整个数据进行锁定

9,ArrayList VS LinkedList

  • ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。 
  • 对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针。 
  • 对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据。

二 Collection

1,本质上来说,数据结构,实际上是设计一种容器,而容器的特性大体包括如下:

  • 容器中如何进行存储
  • 容器中的数据如何获取
  • 容器中的数据如何添加  
  • 容器中的数据如何遍历
  • 器中的数据如何搜索
  • 容器中的其他特性(判空,替换,排序,溢出,并发,同步,拆分,汇聚等等)

    Collection是容器的框架集,其中包含了我们经常使用的容器.

2,源码分析

public interface Collection<E> extends Iterable<E> {
    // Query Operations    原注释,不明意义

    //定义size方法,应返回size大小,最大值为Integer.MAX_VALUE
    int size();

    //定义isEmpty方法,用于返回是否为空
    boolean isEmpty();

    //定义contains方法,判断一个obj是否属于此集合
    boolean contains(Object o);

    //定义迭代器方法,返回一个迭代器对象
    Iterator<E> iterator();

    //定义转换为转换Obj数组的方法,返回一个obj数组
    Object[] toArray();

    //定义转换为泛型T数组的方法,返回一个指定泛型的数组
    <T> T[] toArray(T[] a);

    //定义add方法,添加一个元素e,并返回添加成功标志
    boolean add(E e);

    //定义remove方法,移除一个元素obj,并返回移除元素成功标志
    boolean remove(Object o);

    //定义containsAll方法,判断是否包含集合实例对象c
    boolean containsAll(Collection<?> c);

    //定义addAll方法,添加集合实例对象c到本实例中
    boolean addAll(Collection<? extends E> c);

    //定义removeAll方法,从本实例中移除集合实力对象c
    boolean removeAll(Collection<?> c);


    /**
     * jdk8新增
     * 大意为:
     * 定义removeIf方法,该方传递参数为函数式,传递内容是一个接口类型,该接口类型
     * 定义为一个filter函数,该函数用于传递给Objects.requireNonNull判断,然后调用
     * 迭代器,将满足该定义的filter的本实例中的元素移除
     * @since 1.8
     */
    default boolean removeIf(Predicate<? super E> filter) {
        Objects.requireNonNull(filter);
        boolean removed = false;
        final Iterator<E> each = iterator();
        while (each.hasNext()) {
            if (filter.test(each.next())) {
                each.remove();
                removed = true;
            }
        }
        return removed;
    }

    //定义retainAll方法,取本例与集合实例c的交集,判断交集元素数量是否大于0
    boolean retainAll(Collection<?> c);

    //定义clear方法,清除本例集合中的所有元素
    void clear();

    // Comparison and hashing    原注释,不明意义

    //不解释
    boolean equals(Object o);

    //定义hashCode方法,获取hashCode标记的方法
    int hashCode();

    /**
     *jdk8新增
     *大意为:
     *将迭代器拆分,重写自Iterable接口,从已知元素数量的本例中返回拆分后的迭代器
     *此方法返回的为本类本身
     *子类可能重写迭代器拆分,将一个集合的迭代拆分为多个集合的迭代交由多个线程
     * @since 1.8
     */
    @Override//重写父类
    default Spliterator<E> spliterator() {
        return Spliterators.spliterator(this, 0);
    }

    /**
     * jdk8新增
     * 大意为:
     * 将默认的迭代器拆分后的结果,聚合为流,该流并非io中的流,
     * 是一种类似于数据排序操作流
     * @since 1.8
     */
    default Stream<E> stream() {
        return StreamSupport.stream(spliterator(), false);
    }

    /**
     * jdk8新增
     * 同上,但是具体其他的实现中,因为可并行,所以可能是线程不安全的
     * 
     * @since 1.8
     */
    default Stream<E> parallelStream() {
        return StreamSupport.stream(spliterator(), true);
    }

Oracle已经开始向接口中引入默认方法和静态方法,以此来减少抽象类和接口之间的差异。现在,我们可以为接口提供默认实现的方法了并且不用强制子类来实现它。如上方法前有default标识的方法,子类可不必实现(JDK1.8)

集合作为容器,其体系中的所有集合都包括了:

大小(size),判空(isEmpty),添加元素(add),删除元素(remove),是否包含(contains),转换数组(toArray),清空(clear),遍历与迭代(forEach(父接口中),iterator),是否相同(equals),哈希(hashCode),求交集(retainAll)
除此之外,提供了java8的分离接口,聚合接口,为了大容量集合的多线程操作

猜你喜欢

转载自blog.csdn.net/qq_35909080/article/details/83543204