美文网首页
Java 8 ArrayList新特性

Java 8 ArrayList新特性

作者: 但时间也偷换概念 | 来源:发表于2019-11-20 17:29 被阅读0次

    引言:

    今天主要分析一下Java 8版本中java.util.ArrayList集合类有何变化。

    变化:

    1.上层collection接口变化

            //1.8新增方法:提供了接口默认实现,返回分片迭代器
            @Override
            default Spliterator<E> spliterator() {
                return Spliterators.spliterator(this, 0);
            }
            //1.8新增方法:提供了接口默认实现,返回串行流对象
            default Stream<E> stream() {
                return StreamSupport.stream(spliterator(), false);
            }
            //1.8新增方法:提供了接口默认实现,返回并行流对象
            default Stream<E> parallelStream() {
                return StreamSupport.stream(spliterator(), true);
            }
            /**
             * Removes all of the elements of this collection that satisfy the given
             * predicate.  Errors or runtime exceptions thrown during iteration or by
             * the predicate are relayed to the caller.
             * 1.8新增方法:提供了接口默认实现,移除集合内所有匹配规则的元素,支持Lambda表达式
             */
            default boolean removeIf(Predicate<? super E> filter) {
                //空指针校验
                Objects.requireNonNull(filter);
                //注意:JDK官方推荐的遍历方式还是Iterator,虽然forEach是直接用for循环
                boolean removed = false;
                final Iterator<E> each = iterator();
                while (each.hasNext()) {
                    if (filter.test(each.next())) {
                        each.remove();//移除元素必须选用Iterator.remove()方法
                        removed = true;//一旦有一个移除成功,就返回true
                    }
                }
                //这里补充一下:由于一旦出现移除失败将抛出异常,因此返回false指的仅仅是没有匹配到任何元素而不是运行异常
                return removed;
            }
        }
        public interface Iterable<T>{
        .....
            //1.8新增方法:提供了接口默认实现,用于遍历集合
            default void forEach(Consumer<? super T> action) {
                Objects.requireNonNull(action);
                for (T t : this) {
                    action.accept(t);
                }
            }
            //1.8新增方法:提供了接口默认实现,返回分片迭代器
            default Spliterator<T> spliterator() {
                return Spliterators.spliteratorUnknownSize(iterator(), 0);
            }
        }
        public interface List<E> extends Collection<E> {
            //1.8新增方法:提供了接口默认实现,用于对集合进行排序,主要是方便Lambda表达式
            default void sort(Comparator<? super E> c) {
                Object[] a = this.toArray();
                Arrays.sort(a, (Comparator) c);
                ListIterator<E> i = this.listIterator();
                for (Object e : a) {
                    i.next();
                    i.set((E) e);
                }
            }
            //1.8新增方法:提供了接口默认实现,支持批量删除,主要是方便Lambda表达式
            default void replaceAll(UnaryOperator<E> operator) {
                Objects.requireNonNull(operator);
                final ListIterator<E> li = this.listIterator();
                while (li.hasNext()) {
                    li.set(operator.apply(li.next()));
                }
            }
            /**
             * 1.8新增方法:返回ListIterator实例对象 
             * 1.8专门为List提供了专门的ListIterator,相比于Iterator主要有以下增强:
             *     1.ListIterator新增hasPrevious()和previous()方法,从而可以实现逆向遍历
             *     2.ListIterator新增nextIndex()和previousIndex()方法,增强了其索引定位的能力
             *     3.ListIterator新增set()方法,可以实现对象的修改
             *     4.ListIterator新增add()方法,可以向List中添加对象
             */
            ListIterator<E> listIterator();
        }
    

    2.构造方法变化

    /**
      * Constructs an empty list with an initial capacity of ten.
      * 1.8版的默认构造器,只会初始化一个空数组
      */
    public ArrayList() {
        super();
        this.elementData = EMPTY_ELEMENTDATA;//初始化一个空数组
    }
    /**
      * Constructs an empty list with an initial capacity of ten.
      * 1.7版的默认构造器,会直接初始化一个10容量的数组
      */
    public ArrayList() {
        this(10);
    }
    

    构造方法最大的改变就是变成懒加载了,当你调用add方法的时候才会真正分配数组的内存。

    3.增加foreach

    /**
      * Performs the given action for each element of the {@code Iterable}
      * until all elements have been processed or the action throws an
      * exception.  Unless otherwise specified by the implementing class,
      * actions are performed in the order of iteration (if an iteration order
      * is specified).  Exceptions thrown by the action are relayed to the
      * caller.
      * 1.8新增方法,重写Iterable接口的forEach方法
      * 提供对数组的遍历操作,由于支持Consumer因此在遍历时将执行传入的方法
      */
    @Override
    public void forEach(Consumer<? super E> action) {
        Objects.requireNonNull(action);
        final int expectedModCount = modCount;
        @SuppressWarnings("unchecked")
        final E[] elementData = (E[]) this.elementData;
        final int size = this.size;
        for (int i=0; modCount == expectedModCount && i < size; i++) {
            action.accept(elementData[i]);//执行传入的自定义方法
        }
        if (modCount != expectedModCount) {
            throw new ConcurrentModificationException();
        }
    }
    

    4.增加removeIf

    /**
      * Removes all of the elements of this collection that satisfy the given
      * predicate.  Errors or runtime exceptions thrown during iteration or by
      * the predicate are relayed to the caller.
      * 1.8新增方法,重写Collection接口的removeIf方法
      * 移除集合内所有复合匹配条件的元素,迭代时报错会抛出异常 或 把断言传递给调用者(即断言中断)
      * 该方法主要干了两件事情:
      *     1.根据匹配规则找到所有符合要求的元素
      *     2.移除元素并转移剩余元素位置
      * 补充:为了安全和快速,removeIf分成两步走,而不是直接找到就执行删除和转移操作,写法值得借鉴
      */
    @Override
    public boolean removeIf(Predicate<? super E> filter) {
        Objects.requireNonNull(filter);
        // figure out which elements are to be removed any exception thrown from
        // the filter predicate at this stage will leave the collection unmodified
        int removeCount = 0;
        //BitSet用于按位存储,这里用作存储待移除元素(即符合匹配规则的元素)
        //BitSet能够通过位图算法大幅减少数据占用存储空间和内存,尤其适合在海量数据方面,这里是个很明显的优化
        //有机会会在基础番中解析一下BitSet的奇妙之处
        final BitSet removeSet = new BitSet(size);
        final int expectedModCount = modCount;
        final int size = this.size;
        //每次循环都要判断modCount == expectedModCount!
        for (int i=0; modCount == expectedModCount && i < size; i++) {
            @SuppressWarnings("unchecked")
            final E element = (E) elementData[i];
            if (filter.test(element)) {
                removeSet.set(i);
                removeCount++;
            }
        }
        if (modCount != expectedModCount) {
            throw new ConcurrentModificationException();
        }
        // shift surviving elements left over the spaces left by removed elements
        // 当有元素被移除,需要对剩余元素进行位移
        final boolean anyToRemove = removeCount > 0;
        if (anyToRemove) {
            final int newSize = size - removeCount;
            for (int i=0, j=0; (i < size) && (j < newSize); i++, j++) {
                i = removeSet.nextClearBit(i);
                elementData[j] = elementData[i];
            }
            for (int k=newSize; k < size; k++) {
                elementData[k] = null;  // Let gc do its work
            }
            this.size = newSize;
            if (modCount != expectedModCount) {
                throw new ConcurrentModificationException();
            }
            modCount++;
        }
        //正常情况下,一旦匹配到元素,应该删除成功,否则将抛出异常,当没有匹配到任何元素时,返回false
        return anyToRemove;
    }
    

    5.增加removeAll

    /**
      * Replaces each element of this list with the result of applying the operator to that element.
      * Errors or runtime exceptions thrown by the operator are relayed to the caller.
      * 1.8新增方法,重写List接口的replaceAll方法
      * 提供支持一元操作的批量替换功能
      */
    @Override
    @SuppressWarnings("unchecked")
    public void replaceAll(UnaryOperator<E> operator) {
        Objects.requireNonNull(operator);
        final int expectedModCount = modCount;
        final int size = this.size;
        for (int i=0; modCount == expectedModCount && i < size; i++) {
            elementData[i] = operator.apply((E) elementData[i]);
        }
        if (modCount != expectedModCount) {
            throw new ConcurrentModificationException();
        }
        modCount++;
    }
    

    6.增加sort

    /**
      * Sorts this list according to the order induced by the specified
      * 1.8新增方法,重写List接口的sort方法
      * 支持对数组进行排序,主要方便于Lambda表达式
      */
    @Override
    @SuppressWarnings("unchecked")
    public void sort(Comparator<? super E> c) {
        final int expectedModCount = modCount;
        //Arrays.sort底层是结合归并排序和插入排序的混合排序算法,有不错的性能
        //有机会在基础番对Timsort(1.8版)和ComparableTimSort(1.7版)进行解析
        Arrays.sort((E[]) elementData, 0, size, c);
        if (modCount != expectedModCount) {
            throw new ConcurrentModificationException();
        }
        modCount++;
    }
    

    参考地址
    集合番@ArrayList一文通(1.8版)

    相关文章

      网友评论

          本文标题:Java 8 ArrayList新特性

          本文链接:https://www.haomeiwen.com/subject/yytaictx.html