JDK集合框架--综述

     接下来的几篇博客总结一下对jdk中常用集合类知识,本篇博客先整体性地介绍一下集合及其主要的api:

  从整体上来说,集合分两大类collection和map:

首先来看看Collection:

  collection主要分为set(无序)和list(有序)两大类,这里分别以HashSet和ArrayList为例,分析:

  

 以上是使用idea生成的类图:

  collection继承了接口Iterable,用于获取迭代器(Iterator接口的实现类实例),Iterator的实现类都是集合类中的内部类;

    

Iterator接口主要用于遍历集合中的元素,接下来看看collection接口

  

主要都是一些对集合中元素的添加,移除,查找等基础方法,然后看看都继承了collection的set和list接口:

  左边是list,右边是set,可以看到set接口并没有添加新的方法,所有方法都是覆盖collection的,并没有拓展父类;然后看看list的方法,用红线圈的起来的是set方法所没有的,其实从这些list特有的方法中,就能看出list和set的区别所在,这些方法无非就是通过索引值获取元素或者获取一个元素的索引值,索引就是元素在集合中的序号,说明list是有序集合,而set是无序集合。

  AbstractCollection是一个抽象类,该类中简单地实现了Collection接口中多数的方法,留下两个抽象方法

 public abstract Iterator<E> iterator();//获取迭代器
 public abstract int size();//元素个数

其他的方法基本上是根据子类所实现的iterator()获取

迭代器(用到模板方法设计模式),然后遍历元素来实现,比如判断集合中是否含有某元素的contains:

public boolean contains(Object o) {
        Iterator<E> it = iterator();//子类实现
        if (o==null) {
            while (it.hasNext())
                if (it.next()==null)
                    return true;
        } else {
            while (it.hasNext())
                if (o.equals(it.next()))
                    return true;
        }
        return false;
    }

这里需要注意add(E e)方法:

/**
     * {@inheritDoc}
     *
     * <p>This implementation always throws an
     * <tt>UnsupportedOperationException</tt>.
     *
     * @throws UnsupportedOperationException {@inheritDoc}
     * @throws ClassCastException            {@inheritDoc}
     * @throws NullPointerException          {@inheritDoc}
     * @throws IllegalArgumentException      {@inheritDoc}
     * @throws IllegalStateException         {@inheritDoc}
     */
    public boolean add(E e) {
        throw new UnsupportedOperationException();
    }

这个方法默认的实现是抛出异常,子类如果没有重写,该方法会抛出UnsupportedOperationException异常(比如:java.util.Arrays#asList()方法,返回的list对象的类就没有覆盖add(E e));

最后看看AbstractList和AbstractSet:

  AbstractList实现list,由于list是有序的,可以通过索引访问的方式获取到下一个元素,所以AbstractList通过给出了一种最简单通用的实现迭代器的方法:

private class Itr implements Iterator<E> {
        /**
         * Index of element to be returned by subsequent call to next.
         */
        int cursor = 0;

        /**
         * Index of element returned by most recent call to next or
         * previous.  Reset to -1 if this element is deleted by a call
         * to remove.
         */
        int lastRet = -1;

        /**
         * The modCount value that the iterator believes that the backing
         * List should have.  If this expectation is violated, the iterator
         * has detected concurrent modification.
         */
        int expectedModCount = modCount;

        public boolean hasNext() {
            return cursor != size();
        }

        public E next() {
            checkForComodification();
            try {
                int i = cursor;
                E next = get(i);//通过索引获取下一个元素
                lastRet = i;
                cursor = i + 1;
                return next;
            } catch (IndexOutOfBoundsException e) {
                checkForComodification();
                throw new NoSuchElementException();
            }
        }

        public void remove() {
            if (lastRet < 0)
                throw new IllegalStateException();
            checkForComodification();

            try {
                AbstractList.this.remove(lastRet);//
                if (lastRet < cursor)
                    cursor--;
                lastRet = -1;
                expectedModCount = modCount;
            } catch (IndexOutOfBoundsException e) {
                throw new ConcurrentModificationException();
            }
        }

        final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }
    }

由于子类中用于存储元素的数据结构不同,通过索引获取值得方法可能不同,比如数组和链表,后续的文章会深入讲到,所以get(int index) 和size()依然是个抽象方法没有实现;

AbstractSet只是重写了三个方法,没什么特别:

  

再来看看Map:

    

类图层次机构比较简单,没什么特殊;看看Map接口定义的方法:

  

Map类型相对来说其接口规范,比较统一,不需要后代接口拓展,就是说所有具体的实现类只需要实现Map中操作集合的方法即可。

    

  

原文地址:https://www.cnblogs.com/qzlcl/p/10884175.html