zoukankan      html  css  js  c++  java
  • Java集合(二)、Collection接口介绍

    一、Collection 接口概述

    Collection是一个接口,继承自Iterable。我们先看一下Iterable接口的源码

    package java.lang;
    
    import java.util.Iterator;
    import java.util.Objects;
    import java.util.Spliterator;
    import java.util.Spliterators;
    import java.util.function.Consumer;
    
        /**
         *实现这个接口的的类允许使用"for-each loop"语句来遍历。
         */
    public interface Iterable<T> {
    
        /**
         *返回一个元素类型为T的迭代器
         */
        Iterator<T> iterator();
    
        /**
         * jdk1.8新增的遍历方式
         */
        default void forEach(Consumer<? super T> action) {
            Objects.requireNonNull(action);
            for (T t : this) {
                action.accept(t);
            }
        }
    
        /**
         * 暂不研究
         */
        default Spliterator<T> spliterator() {
            return Spliterators.spliteratorUnknownSize(iterator(), 0);
        }
    }

    Iterable接口有一个Iterator iterator();方法,而Collection继承自Iterable接口,所以我们说Collection因爱与Iterator。

    二、Collection 接口

    Collection是一个高度封装的集合接口,它提供了所有集合要实现的默认方法接口。

    我们看一下接口源码,了解它有哪些接口和默认实现。

    package java.util;
    
    import java.util.function.Predicate;
    import java.util.stream.Stream;
    import java.util.stream.StreamSupport;
    
    /**
     *这是一个集合分层的根接口。集合代表了一组包含元素的对象。有些集合允许有重复的元素,有些不允许。
     *有些集合是有序的有些无序的。jdk不对这个接口提供任何直接的实现,但是再一些直接子接口例如Set和List有实现了某些接口方法。
     *所有继承Collection的类必须提供两个默认的构造函数,一个不带参数的、一个带Collection类型参数。
     *
     */
    
    public interface Collection<E> extends Iterable<E> {
        //查询操作
    
        /**
         *返回集合大小,也就是集合中元素的数量
         */
        int size();
    
        /**
         * 如果集合包含元素则返回true,即判断集合是否为空
         */
        boolean isEmpty();
    
        /**
         * 判断集合是否存在某个对象,注意这里参数是个Object,并没有限制为E或其子类
         */
        boolean contains(Object o);
    
        /**
         * 返回一个迭代器iterator。并没有说明元素的迭代顺序,除非特别的集合有这个要求。
         */
        Iterator<E> iterator();
    
        /**
         *将集合转为对象数组,注意这里不是元素数组而是一个Object数组。
         *如果集合保证是有序的,那么通过迭代器返回数组有相同顺序
         *返回的数组是安全的,也就是说集合有自己的引用,数组开辟新的堆内存,也有自己的引用。所以调
         *用者可以随意操作返回的数组。
         *这个方法是数组和列表之间的桥梁
         */
        Object[] toArray();
    
        /**
         * 返回一个集合元素类型的数组。如果集合满足指定的数组并且有足够的空间,则在其中返回此集合
         * 否则返回此集合大小的新数组。
         * 如果集合有序,那么返回此集合迭代器遍历顺序的数组
         * 如果数组大小比集合元素多,那么在数组满足集合元素后在末尾设置为null  
         *
         * 如果在这个集合中指定数组运行时类型不是运行时元素类型的超类,那么抛ArrayStoreException异常
         * 如果指定数组为空,则抛出NullPointerException
         */
        <T> T[] toArray(T[] a);
    
    
        //修改操作
    
        /**
         * 确保此集合包含特定的元素类型。
         * 如果此集合增加元素成功返回true。
         * 如果此集合不允许有重复元素并且已经包含所传参数,那么返回false
         * 
         * 支持此操作的集合可能会限制向该集合添加哪些元素。特别的,有些集合会拒绝null元素,有些
         * 会对要增加的元素强加一些限制。
         * Collection实现类应该在文档中明确指出所有的限制。
         *
         * 如果集合以除已经包含元素之外的任何原因拒绝添加特定元素,则必须抛出异常
         *(而不是返回false)。这保留了集合在此调用返回后始终包含指定元素的不变式。
         */
        boolean add(E e);
    
        /**
         * 如果此集合中存在此元素,那么移除一个特定元素类型的实例。更正式的说,如果集合中包含一个或多个这样的元素,
         * 那么删除这样的元素(o==null?e==null:o.equals(e))。如果集合包含指定的元素(或集合因调用而发生改变),那么返回true。
         *
         * 如果指定元素的类型和集合不相容,抛出ClassCastException异常(可选的限制条件)
         * 如果指定元素是null并且这个集合不允许null元素存在,那么抛出NullPointerException异常(可选的限制条件)
         * 如果此集合不支持remove操作那么抛出UnsupportedOperationException异常(可选的限制条件)
         */
        boolean remove(Object o);
    
    
        //容量操作
    
        /**
         * 如果this集合包含指定集合的所有元素,返回true
         * c集合必须要检查是否被包含在this集合
         * 如果指定元素的类型和集合不相容,抛出ClassCastException异常(可选的限制条件)
         * 如果指定元素是null并且这个集合不允许null元素存在,那么抛出NullPointerException异常(可选的限制条件)
         */
        boolean containsAll(Collection<?> c);
    
        /**
         * 将指定集合的所有元素到this集合中(可选的操作)。
         * 如果指定的集合在操作进行时被修改了,那么此操作行为未定义。
         * (这意味着如果指定的集合是这个集合,并且这个集合是非空的,那么这个调用的行为是未定义的。)
         * 
         * @参数:c集合包含了要被添加到这个集合的元素
         * @返回:如果调用结果改变了this集合返回true
         * @throws:如果 addAll操作不被此集合支持,那么抛出UnsupportedOpertaionException异常
         * @throws: 如果指定集合包含了空元素而this集合不允许有空元素,那么抛出NullPointerException异常
         * @throws:如果this集合阻止hiding集合元素类型添加,那么抛出ClassCastException异常
         * @throws:如果指定集合的元素的某些属性阻止将其添加到此集合,则抛出IllegalArgumentException
         * @throws:由于插入限制,如果不是所有元素都可以在此时添加,则抛出IllegalStateException异常
         */
        boolean addAll(Collection<? extends E> c);
    
        /**
         * 移除此集合中所有的包含在指定集合中的元素(可选的操作)。调用过此函数之后,那么此集合和指定集合将不再包含相同元素。
         *
         * @param:包含要从该集合中删除的元素的c集合
         * @return:如果此集合因调用而更改那么返回true
         * @throws:如果此集合不支持removeAll方法,则抛出UnsupportedOperationException
         * @throws:如果集合中一个或多个元素的类型与指定集合不兼容,则抛出ClassCastException(可选的操作)
         * @throws:如果该集合包含一个或多个空元素,且指定的集合不支持空元素(optional),或者指定的集合为空,
         * 则抛出NullPointerException异常
         */
        boolean removeAll(Collection<?> c);
    
        /**
         * 移除此集合中所有符合给定Predicate的元素。在迭代期间或由Predicate引发的错误或运行时异常将被转发给调用方
         * @implSpec
         * 默认实现使用其迭代器遍历集合的所有元素。每一个匹配的元素使用iterator.remove()来移除。
         * 如果集合的iterator不支持移除将会抛出UnsupportedOperationException异常在匹匹厄到
         * 第一个元素时。
         * @param 过滤一个predicate
         * @param 筛选要删除的元素返回true的Predicate
         * @return 如果任何一个元素被删除返回true
         * @throws 指定过滤器为空,抛出NullPointerException
         * @throws 如果元素没有被删除,或者移除操作不支持,
         *  则立即抛出UnsupportedOperationException异常
         * @since 1.8
         */
        default boolean removeIf(Predicate<? super E> filter) {
            //如果filter为null抛出NullPointerException
            Objects.requireNonNull(filter);
            boolean removed = false;
            final Iterator<E> each = iterator();
            //通过迭代器遍历删除,只要删除一个removed就为true
            while (each.hasNext()) {
                if (filter.test(each.next())) {
                    each.remove();
                    removed = true;
                }
            }
            return removed;
        }
    
        /**
         * 只保留此集合中包含在指定集合中的元素(可选的操作)。
         * 也就是说,此集合中不包含在指定集合中的所有元素。
         * @param:要保留的元素的集合c
         * @return:如果此集合改变了返回true
         * @throws:如果此集合不支持retainAll,则抛出UnsupportedOperationException异常
         * @throws:如果集合中一个或多个元素的类型与指定集合不兼容,则抛出ClassCastException(可选的操作)
         * @throws:如果该集合包含一个或多个空元素,且指定的集合不支持空元素(optional),或者指定的集合为空
         */
        boolean retainAll(Collection<?> c);
    
        /**
         * 移除此集合中所有元素(可选操作),调用此方法后集合里将为空。
         * @throws: 如果此集合clear操作不支持将会抛出UnsupportOperationException异常。
         */
        void clear();
    
    
    
        //比较和hash
    
        /**
         * 比较指定的对象与此集合是否相等
         * 
         */
        boolean equals(Object o);
    
        /**
         *返回这个集合的hashCode。当集合接口没有对Object.hashCode方法的一般协议做任何规定,编程
         *人员应该注意在重写equals方法时必须重写hashCode方法,以便满足一般协议对这个
         *Object.hashCode方法。特别的,c1.equals(c2)表明c1.hashCode()==c2.hashCode()。
         */
        int hashCode();
    
        /**
         *一下1.8新增的Spliterator,暂不研究
         */
        @Override
        default Spliterator<E> spliterator() {
            return Spliterators.spliterator(this, 0);
        }
        default Stream<E> stream() {
            return StreamSupport.stream(spliterator(), false);
        }
        default Stream<E> parallelStream() {
            return StreamSupport.stream(spliterator(), true);
        }
    }

    三、AbstractCollection类

    AbstractCollection是一个实现了Collection接口的抽象类,除了iterator()和size()接口,它提供了一些其他接口的默认实现,其他集合类可以继承此类来复用。

    AbstractCollection源码

    package java.util;
    
    public abstract class AbstractCollection<E> implements Collection<E> {
        /*唯一的构造函数*/
        protected AbstractCollection(){
    
        }
    
        //查询操作
    
        public abstract Iterator<E> iterator();
    
        public abstract int size();
    
        /*
         * 返回size() == 0
         */
        public boolean isEmpty(){
            return size() == 0;
        }
    
        /**
         * 实现的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;
        }
    
        /**
         * 此默认实现,考虑到数组在迭代器遍历过程中大小可能会改变,
         * 也就是可能会增加或减少元素怒
         */
        public Object[] toArray(){
            //估计数组大小,并做好变小或变大的准备
            Object[] r = new Object[size()];
            Iterator<E> it = iterator();
            for (int i = 0; i < r.length; i++){
                if (! it.hasNext())  //比期望的元素少,那么调用Arrays.copyOf()方法返回一个新的数组
                    return Arrays.copyOf(r, i);
                r[i] = it.next();
            }
            //判断集合有没有被增加(迭代器改变),如果没有返回数组,如果有调用finishToArray()方法返回数组
            return it.hasNext() ? finishToArray(r, it) : r;
        }
    
        /**
         * 
         */
        @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;
        }
    
        /**
         * 一些VM会在数组中保留头信息,所以要占用8字节空间,头信息大小不能超过8
         * 重新分配更大的长度给数组,如果要求的数组大小超过VM限制,会抛出OutOfMemoryError
         * 默认值 2147483647 - 8;
         */
        private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
    
        /**
         * 重新在toArray方法中,如果iterator返回了比期望中的大小更多的元素时,重新给数组分配空间来完成填充数组。
         * @param 之前的已经被填满的数组
         * @param 操作中集合的iterator
         * @return 除了给定的数组之外,增加了从迭代器中获取的元素,并修正数组长度
         */
        @SuppressWarnings("unchecked")
        private static <T> T[] finishToArray(T[] r, Iterator<?> it) {
            int i = r.length; //被填充满的数组长度(原始集合大小)
            while (it.hasNext()) {
                int cap = r.length;
                if (i == cap) {  //第一次(刚进来的时候)一定为true,那么分配新的数组大小
                    int newCap = cap + (cap >> 1) + 1; //右移一位+1再加上原大小
                    if (newCap - MAX_ARRAY_SIZE > 0)  
                        //新数组大小大于集合默认最大值,调用hugeCapacity()方法重新分配,值为Integer.MAX_VALUE
                        newCap = hugeCapacity(cap + 1);
                    r = Arrays.copyOf(r, newCap);
                }
                r[i++] = (T)it.next();
            }
            // 修正数组多余的空间,如果正好直接返回,否则调用Arrays.copyOf()方法
            return (i == r.length) ? r : Arrays.copyOf(r, i);
        }
    
        private static int hugeCapacity(int minCapacity) {
            if (minCapacity < 0) // 内存溢出
                throw new OutOfMemoryError
                    ("Required array size too large");
            return (minCapacity > MAX_ARRAY_SIZE) ?
                Integer.MAX_VALUE :
                MAX_ARRAY_SIZE;
        }
    
    
    
        //修改操作
        /**
         * 此操作总是抛出 UnsupportedOperationException
         * @throws UnsupportedOperationException {@inheritDoc}
         * @throws ClassCastException            {@inheritDoc}
         * @throws NullPointerException          {@inheritDoc}
         * @throws IllegalArgumentException      {@inheritDoc}
         * @throws IllegalStateException         {@inheritDoc}
         */
        public boolean add(E e) {
            throw new UnsupportedOperationException();
        }
    
        /**
         * 通过集合迭代器查找元素,如果找到调用iterator.remove()方法删除元素。
         * 删除一个就返回true
         */
        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;
        }
    
        // Bulk Operations
        /**
         * 判断此集合是否包含指定集合所有元素,有一个没有返回false
         */
        public boolean containsAll(Collection<?> c) {
            for (Object e : c)
                if (!contains(e))
                    return false;
            return true;
        }
    
        /**
         * 调用add(E e)方法添加指定集合到此集合中
         *
         * @see #add(Object)
         */
        public boolean addAll(Collection<? extends E> c) {
            boolean modified = false;
            for (E e : c)
                if (add(e))
                    modified = true;
            return modified;
        }
    
        /**
         * 这个方法将从此集合中删除指定集合的所有元素,通过迭代器删除。
         * @throws UnsupportedOperationException {@inheritDoc}
         * @throws ClassCastException            {@inheritDoc}
         * @throws NullPointerException          {@inheritDoc}
         *
         * @see #remove(Object)
         * @see #contains(Object)
         */
        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;
        }
    
        /**
         * 此集合中保留指定集合的所有元素,也就是说调用此方法之后,此集合中删除了不存在指定集合中
         *的元素
         * 
         */
        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;
        }
    
        /**
         * 清空集合中所有元素
         * @throws UnsupportedOperationException {@inheritDoc}
         */
        public void clear() {
            Iterator<E> it = iterator();
            while (it.hasNext()) {
                it.next();
                it.remove();
            }
        }
    
    
        //  String conversion
    
        /**
         * 集合的toString方法,所有继承AbstractCollection的类都有此方法
         */
        public String toString() {
            Iterator<E> it = iterator();
            if (! it.hasNext())
                return "[]";
    
            StringBuilder sb = new StringBuilder();
            sb.append('[');
            for (;;) {
                E e = it.next();
                //如果将自己这个集合添加到自己,就会打印(this Collection)
                sb.append(e == this ? "(this Collection)" : e);
                if (! it.hasNext())
                    return sb.append(']').toString();
                sb.append(',').append(' ');
            }
        }
    
    }
    }

    AbstractCollection类默认实现的方法,在上面源代码中我都已经讲解过了,很多常用的集合都会使用 默认实现,比如常用的toString方法,我们在输出ArrayList时调用的就是此方法。

    引自:http://www.manongjc.com/article/66616.html

    很想高飞,但我不能;不想天空,剩我一人。
  • 相关阅读:
    linux驱动开发学习一:创建一个字符设备
    如何高效的对有序数组去重
    找到缺失的第一个正整数
    .NET不可变集合已经正式发布
    中国人唯一不认可的成功——就是家庭的和睦,人生的平淡【转】
    自己动手搭建 MongoDB 环境,并建立一个 .NET HelloWorld 程序测试
    ASP.NET MVC 中如何用自定义 Handler 来处理来自 AJAX 请求的 HttpRequestValidationException 错误
    自己动手搭建 Redis 环境,并建立一个 .NET HelloWorld 程序测试
    ServiceStack 介绍
    一步一步实战扩展 ASP.NET Route,实现小写 URL、个性化 URL
  • 原文地址:https://www.cnblogs.com/lixiansheng/p/11348270.html
Copyright © 2011-2022 走看看