欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java Collection 学习笔记

程序员文章站 2022-06-13 20:24:26
...

Collection

先上一张图
Java Collection 学习笔记

其中:

  • 实线箭头表示继承关系,绿色实线箭头表示一个接口继承另一个接口。蓝色实线箭头表示一个类继承另外一个类。
  • 绿色虚线箭头表示实现一个接口。

Collection 接口定义

再来一张图:
Java Collection 学习笔记
查看源码:

public interface Collection<E> extends Iterable<E> {
// 省略....
}

可以看到他是一个泛型接口,E代表要存储的对象类型。它继承了Iterable接口,用于支持以迭代器Iterator的方法访问所持有的对象。iterator()方法就是Iterable接口所定义的,用于返回Iterator对象。而Iterator接口有hasNext()和next()方法,前者用于判断还有对象没,后者用于获取对象,并移动到下一位。

Collection接口定义了一些公用的方法, 比如获取容器大小,判断是否为空,判断是否包含给定的对象,转换成数组,添加一个对象,删除给定的对象,判断是否包含一个给定的Collection 对象,将给定的Collection对象所包含的全部实例添加到容器中,删除给定的Collection对象所包含的全部实例。清空容器等操作。
当然,少不了 equals(Object) 和 hashCode() 方法,他们是Object类的方法。而java中默认所有的类都继承Object类。
同时还有stream()和parallelStream()方法。

List, Set, Queue 是 Collection 类的子接口。AbstractCollection 实现了Collection 接口。

AbstractCollection

AbstractCollection是一个抽象类。抽象类就是说它实现了部分方法。可以看到,List,Set,Queue的添加方法是不一样的,所以它不会实现这个方法:

add(E e)
    public boolean add(E e) {
        throw new UnsupportedOperationException();
    }

但是因为有iterator()方法,它会返回一个Iterator对象,它抽象了访问对象的方式,可以通过hasNext() 方法和 next() 方法的联合使用完成对Collection持有对象的遍历,那不管是List,Set,还是Queue, 他们判断一个给定对象是否被包含的算法就是一样的。

contains(Object object) 方法
 public boolean contains(Object var1) {
    Iterator var2 = this.iterator();
    if (var1 == null) {
        while(var2.hasNext()) {
            if (var2.next() == null) {
                return true;
            }
        }
    } else {
        while(var2.hasNext()) {
            if (var1.equals(var2.next())) {
                return true;
            }
        }
    }

    return false;
}
toArray()

既然能够遍历,那转换成数组的算法也是一样的。

    public Object[] toArray() {
        // Estimate size of array; be prepared to see more or fewer elements
        Object[] r = new Object[size()];
        Iterator<E> it = iterator();
        for (int i = 0; i < r.length; i++) {
            if (! it.hasNext()) // fewer elements than expected
                return Arrays.copyOf(r, i);
            r[i] = it.next();
        }
        return it.hasNext() ? finishToArray(r, it) : r;
    }

toArray(T[] a)

@SuppressWarnings("unchecked")
    public <T> T[] toArray(T[] a) {
        // Estimate size of array; be prepared to see more or fewer elements
        int size = size();
        T[] r = a.length >= size ? a :
                  (T[])java.lang.reflect.Array
                  .newInstance(a.getClass().getComponentType(), size);
        Iterator<E> it = iterator();

        for (int i = 0; i < r.length; i++) {
            if (! it.hasNext()) { // fewer elements than expected
                if (a == r) {
                    r[i] = null; // null-terminate
                } else if (a.length < i) {
                    return Arrays.copyOf(r, i);
                } else {
                    System.arraycopy(r, 0, a, 0, i);
                    if (a.length > i) {
                        a[i] = null;
                    }
                }
                return a;
            }
            r[i] = (T)it.next();
        }
        // more elements than expected
        return it.hasNext() ? finishToArray(r, it) : r;
    }

既然能够遍历,那就可以删除给定对象

remove(Object o)

    public boolean remove(Object o) {
        Iterator<E> it = iterator();
        if (o==null) {
            while (it.hasNext()) {
                if (it.next()==null) {
                    it.remove();
                    return true;
                }
            }
        } else {
            while (it.hasNext()) {
                if (o.equals(it.next())) {
                    it.remove();
                    return true;
                }
            }
        }
        return false;
    }

containsAll(Collection<?> c)

还可以判断是否包含给定Collection集合的所有对象。

    public boolean containsAll(Collection<?> c) {
        for (Object e : c)
            if (!contains(e))
                return false;
        return true;
    }

addAll(Collection<? extends E> c)

还可以把给定的Collection集合的所有对象添加到自己当中,只不过是一个for循环而以,每次循环调用具体的添加方法。

    public boolean addAll(Collection<? extends E> c) {
        boolean modified = false;
        for (E e : c)
            if (add(e))
                modified = true;
        return modified;
    }

removeAll(Collection<?> c)

可以删除给定Collection集合的所有对象。

    public boolean removeAll(Collection<?> c) {
        Objects.requireNonNull(c);
        boolean modified = false;
        Iterator<?> it = iterator();
        while (it.hasNext()) {
            if (c.contains(it.next())) {
                it.remove();
                modified = true;
            }
        }
        return modified;
    }

retainAll(Collection<?> c)

retainAll 就是 removeAll的判断条件取反而已。

    public boolean retainAll(Collection<?> c) {
        Objects.requireNonNull(c);
        boolean modified = false;
        Iterator<E> it = iterator();
        while (it.hasNext()) {
            if (!c.contains(it.next())) {
                it.remove();
                modified = true;
            }
        }
        return modified;
    }

clear()

清空集合就是遍历,把找到的对象先移动到下一个对象 it.next(),然后在删除 it.remove()。

    public void clear() {
        Iterator<E> it = iterator();
        while (it.hasNext()) {
            it.next();
            it.remove();
        }
    }

toString()

借助迭代遍历实现toString.

    public String toString() {
        Iterator<E> it = iterator();
        if (! it.hasNext())
            return "[]";

        StringBuilder sb = new StringBuilder();
        sb.append('[');
        for (;;) {
            E e = it.next();
            sb.append(e == this ? "(this Collection)" : e);
            if (! it.hasNext())
                return sb.append(']').toString();
            sb.append(',').append(' ');
        }
    }

AbstractList, AbstractQueue, AbstractSet

他们都会继承AbstractCollection,同时实现自己对应的接口。比如:

public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {}
public abstract class AbstractSet<E> extends AbstractCollection<E> implements List<E> {}
public abstract class AbstractQueue<E> extends AbstractCollection<E> implements Queue<E> {}

AbstractList

要知道AbstarctList接口实现了什么方法,就要看List和Collection相比,它多提供了些什么方法。List和Set 和 Queue相比,它有Index这个概念。所以提供了两个方法,如果给定一个对象,可以从前往后找,返回找到的第一个Index。indexOf(Object object), 也可以从后往前找,返回遇到的一个对象的索引 lastIndexOf(Object). 当然,正是因为有index这个特性,List的literator 需要多那么一点东西:返回下一个index , 返回上一个index, 判断是否有前继,获取前继。源码如下:

public interface ListIterator<E> extends Iterator<E> {
    boolean hasNext();

    E next();

    boolean hasPrevious();

    E previous();

    int nextIndex();

    int previousIndex();

    void remove();

    void set(E var1);

    void add(E var1);
}

太晚了,下次继续。。。。

相关标签: Java Collection