美文网首页Java 杂谈
使用Arrays.asList()方法时的注意事项

使用Arrays.asList()方法时的注意事项

作者: LittleMagic | 来源:发表于2019-05-03 10:27 被阅读181次

最近休五一假期,不是很想写长篇大论,因此最近三篇文章都是信手拈来的小总结。等假期结束开工之后自然会恢复正常。

java.util.Arrays.asList()方法是我们在日常工作中极其常用的方法之一,它可以方便地将数组类型转化为列表类型。例如:

String[] teamsArray = { "Liverpool", "Man Utd", "Man City", "Arsenal", "Chelsea" };
List<String> teamsList = Arrays.asList(teamsArray);
System.out.println(teamsList.size());
teamsList.forEach(s -> System.out.println(s));

输出一切正常。


但是,如果这样呢?

int[] intArray = { 11, 22, 33, 44, 55 };
List intList = Arrays.asList(intArray);
System.out.println(intList.size());
intList.forEach(i -> System.out.println(i));

输出就会变成只有一个元素:


来看一下asList()方法的实现就明白了。

    @SafeVarargs
    @SuppressWarnings("varargs")
    public static <T> List<T> asList(T... a) {
        return new ArrayList<>(a);
    }

很显然,T必须是对象才能有对应的class,从而支持泛型。当传入int[]这样的基本类型的数组时,就会将数组本身当作一个对象传入,因此返回的List长度为1,且包含有该int数组。要避免这种情况,声明数组时需要用装箱类,即Integer[]。

另外,如果对asList()方法返回的列表进行增删操作,通通都会抛出UnsupportedOperationException异常。例如:

String[] teamsArray = { "Liverpool", "Man Utd", "Man City", "Arsenal", "Chelsea" };
List<String> teamsList = Arrays.asList(teamsArray);
teamsList.add("Tottenham");
teamsList.remove("Man City");

结果:


其原因是,在asList()方法中返回的ArrayList并不是我们常见的java.util.ArrayList,而是在Arrays类中定义的一个静态内部类的实例。

    private static class ArrayList<E> extends AbstractList<E>
        implements RandomAccess, java.io.Serializable
    {
        private static final long serialVersionUID = -2764017481108945198L;
        private final E[] a;

        ArrayList(E[] array) { a = Objects.requireNonNull(array); }

        @Override
        public int size() { return a.length; }

        @Override
        public Object[] toArray() { return a.clone(); }

        @Override
        @SuppressWarnings("unchecked")
        public <T> T[] toArray(T[] a) {
            int size = size();
            if (a.length < size)
                return Arrays.copyOf(this.a, size,
                                     (Class<? extends T[]>) a.getClass());
            System.arraycopy(this.a, 0, a, 0, size);
            if (a.length > size)
                a[size] = null;
            return a;
        }

        @Override
        public E get(int index) { return a[index]; }

        @Override
        public E set(int index, E element) {
            E oldValue = a[index];
            a[index] = element;
            return oldValue;
        }

        @Override
        public int indexOf(Object o) {
            E[] a = this.a;
            if (o == null) {
                for (int i = 0; i < a.length; i++)
                    if (a[i] == null)
                        return i;
            } else {
                for (int i = 0; i < a.length; i++)
                    if (o.equals(a[i]))
                        return i;
            }
            return -1;
        }

        @Override
        public boolean contains(Object o) { return indexOf(o) != -1; }

        @Override
        public Spliterator<E> spliterator() { return Spliterators.spliterator(a, Spliterator.ORDERED); }

        @Override
        public void forEach(Consumer<? super E> action) {
            Objects.requireNonNull(action);
            for (E e : a) {
                action.accept(e);
            }
        }

        @Override
        public void replaceAll(UnaryOperator<E> operator) {
            Objects.requireNonNull(operator);
            E[] a = this.a;
            for (int i = 0; i < a.length; i++) {
                a[i] = operator.apply(a[i]);
            }
        }

        @Override
        public void sort(Comparator<? super E> c) { Arrays.sort(a, c); }
    }

可见,它虽然继承了AbstractList抽象类,但并没有实现add()/remove()/clear()等方法,并且它内部存储元素的数组a用了final关键字修饰,说明它确实不支持使其长度发生改变的修改操作。要想添加或删除元素,就只能用它构造一个真正的java.util.ArrayList再进行操作了。

相关文章

网友评论

    本文标题:使用Arrays.asList()方法时的注意事项

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