美文网首页数据
使用ArrayList.subList()和Arrays.asL

使用ArrayList.subList()和Arrays.asL

作者: 元亨利贞o | 来源:发表于2017-02-24 17:19 被阅读960次

    一. ArrayList.subList()方法

    1. ArrayList.subList(int fromIndex, int toIndex)方法返回一个List: 此List的值包含fromIndex所在的值, 但不包含toIndex所在的值. 如果fromIndex等于toIndex, 那么会返回一个没有任何元素的空List. 返回的List支持java.util.List接口的所有操作.

    2. **ArrayList.subList() 方法返回的List不能强转为ArrayList. **
      ArrayList.subList() 方法返回的List实际类型是ArrayList的一个内部类SubList, 即java.util.ArrayList$SubList

    3. ArrayList.subList() 方法返回的List是ArrayList中某段数据的一个视图. 因此, 在操作此方法返回的List时, 同样会改变ArrayList的数据. 我们来看看ArrayList.SubList这个类的几个方法就知道了:

    public E set(int index, E e) {
        rangeCheck(index);
        checkForComodification();
        E oldValue = ArrayList.this.elementData(offset + index);
        ArrayList.this.elementData[offset + index] = e;
        return oldValue;
    }
    public E get(int index) {
        rangeCheck(index);
        checkForComodification();
        return ArrayList.this.elementData(offset + index);
    }
    

    我们知道ArrayList的内部是用对象数组(成员: elementData)存储数据的, 可以看到ArrayList的内部类SubList的add和get方法操作的就是ArrayList内部的对象数组. 因此对ArrayList.subList()方法的返回值的任何操作都会反映到ArrayList对象本身.

    1. 如果原ArrayList对象有改动, 那么ArrayList.subList()方法返回的视图将会无效. 也就是说在操作ArrayList.subList()方法的返回值前不能对原ArrayList做任何修改, 否则你将得到一个java.util.ConcurrentModificationException异常.

    2. ArrayList的subList方法定义如下:

    /**
         * Returns a view of the portion of this list between the specified
         * {@code fromIndex}, inclusive, and {@code toIndex}, exclusive.  (If
         * {@code fromIndex} and {@code toIndex} are equal, the returned list is
         * empty.)  The returned list is backed by this list, so non-structural
         * changes in the returned list are reflected in this list, and vice-versa.
         * The returned list supports all of the optional list operations.
         *
         * <p>This method eliminates the need for explicit range operations (of
         * the sort that commonly exist for arrays).  Any operation that expects
         * a list can be used as a range operation by passing a subList view
         * instead of a whole list.  For example, the following idiom
         * removes a range of elements from a list:
         * <pre>
         *      list.subList(from, to).clear();
         * </pre>
         * Similar idioms may be constructed for {@link #indexOf(Object)} and
         * {@link #lastIndexOf(Object)}, and all of the algorithms in the
         * {@link Collections} class can be applied to a subList.
         *
         * <p>The semantics of the list returned by this method become undefined if
         * the backing list (i.e., this list) is <i>structurally modified</i> in
         * any way other than via the returned list.  (Structural modifications are
         * those that change the size of this list, or otherwise perturb it in such
         * a fashion that iterations in progress may yield incorrect results.)
         *
         * @throws IndexOutOfBoundsException {@inheritDoc}
         * @throws IllegalArgumentException {@inheritDoc}
         */
        public List<E> subList(int fromIndex, int toIndex) {
            subListRangeCheck(fromIndex, toIndex, size);
            return new SubList(this, 0, fromIndex, toIndex);
        }
    

    更多细节可参考JDK中java.util.ArrayList类的源码

    二. Arrays.asList()方法

    1. Arrays.asList(T ... args)方法将一个数组转换成一个List. Arrays.asList()方法返回的对象是Arrays类的一个内部类, 并没有实现修改集合的相关方法 (看源码可以知道java.util.Arrasy$ArrayList类支持set()方法, 所以还是可以修改的). Arrays.asList()体现的是适配器模式, 只是转换接口, 后台数据仍是被转换的数组. 因此: 对原数组的改动会影响返回的List, 反之亦然!!
    2. 看源码可以知道Arrays.asList()的返回值是ArrayList, 但是请注意, 此ArrayList是Arrays类的一个内部类(java.util.Arrays$ArrayList), 而不是java.util.ArrayList. 因此不要把返回值强转成java.util.ArrayList
    3. Arrays.asList()方法的返回值不支持add/remove/clear方法 (返回的List没有实现修改操作), 如果调用, 你会得到一个UnsupportedOperationException异常.
    4. Arrays.asList()方法定义如下:
    /**
     * Returns a fixed-size list backed by the specified array.  (Changes to
     * the returned list "write through" to the array.)  This method acts
     * as bridge between array-based and collection-based APIs, in
     * combination with {@link Collection#toArray}.  The returned list is
     * serializable and implements {@link RandomAccess}.
     *
     * <p>This method also provides a convenient way to create a fixed-size
     * list initialized to contain several elements:
     * <pre>
     *     List<String> stooges = Arrays.asList("Larry", "Moe", "Curly");
     * </pre>
     *
     * @param <T> the class of the objects in the array
     * @param a the array by which the list will be backed
     * @return a list view of the specified array
     */
    @SafeVarargs
    @SuppressWarnings("varargs")
    public static <T> List<T> asList(T... a) {
        return new ArrayList<>(a);
    }
    

    此方法主要作用是: 用已存在的数组初始化一个固定大小的List.

    三. 总结

    1. 对API使用有疑问的话, 最好是去看源码(如果有源码) 或 API文档.
    2. 定期阅读JDK源码 (把其中常用的API吃透, 也就不会出现由于对API理解有误而导致的错误!!)

    相关文章

      网友评论

        本文标题:使用ArrayList.subList()和Arrays.asL

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