• java中的Arrays.asList()浅析


    1.Arrays.asList(T..)使用的是静态内部类:ArrayList, (没有定义add和remove等一些方法),而不是java.util.ArrayList

    /**
         * 1.测试Arrays.asList()方法 
         * @author zhangdi
         * @description 
         * 使用的是静态内部类:ArrayList, (没有定义add和remove等一些方法),而不是java.util.ArrayList
         * 接受的参数被一个final修饰的成员变量 private final E[] a接受
         * 调用Arrays.asList()的add和remove方法 会抛异常:java.lang.UnsupportedOperationException
         */
        @Test
        public void testAsListOfArray() {
            List<String> list = Arrays.asList("1", "2", "3");
            list.add("4");
            for (String string : list) {
                System.out.println("string:" + string);
            }
        }
    
        @Test
        public void testAsListOfArray2() {
            List<String> list = new ArrayList<>();
            list.add("5");
            list.add("6");
            list.add("7");
            list.add("8");
            for (String string : list) {
                System.out.println("string:" + string);
            }
        }

    2.为什么List<int[]> asList2 = Arrays.asList(d);返回的是List<int[]>而不是List<int>呢?为什么testAsListOfArray3中的list.size():输出1而不是4呢?

    /**
         *  2.Array.asList()接收基本类型与单个元素
         *  @author zhangdi
         *  @see https://stackoverflow.com/questions/1467913/arrays-aslist-not-working-as-it-should
         */
        @Test
        public void testAsListOfArray3(){
            //1
            int[] f = {1,2,3,4};
            List list = Arrays.asList(f);
            System.out.println("list.size():"+list.size());  //output: list.size():1
    
            //2
            int[] a = {1,2,3,4,8,10,22,12,214,23};  
            String[] b = {"a","b","c"};  
            Integer[] c = {1,2,3,4,8,10,22,12,214,23};
            System.out.println(Arrays.asList(a));  
            System.out.println(Arrays.asList(b));  
            System.out.println(Arrays.asList(c)); 
    
            //3
            //There's no such thing as a List<int> in Java - generics don't support primitives.
            //Autoboxing only happens for a single element, not for arrays of primitives.
            //java arrays are objects and Arrays.asList() treats your int array as a single argument in the varargs list.
            int[] d = new int[]{1,2,3,4,8,10,22,12,214,23};  
            Integer[] e = new Integer[]{1,2,3,4,8,10,22,12,214,23}; //避免使用原始类型数组作为asList的输入参数
            List<int[]> asList2 = Arrays.asList(d);
            List<Integer> asList3 = Arrays.asList(e);
            System.out.println(asList2);  
            System.out.println(asList3);  
           // output:
            /*
            1
            [[I@232d49d1]    //会被当做一个参数接收
            [a, b, c]
            [1, 2, 3, 4, 8, 10, 22, 12, 214, 23]
            [[I@ef05133d]
            [1, 2, 3, 4, 8, 10, 22, 12, 214, 23]
            */
        }

    因为:Arrays.asList()方法接受一个可变参数T,一般可看做数组参数,但是因为int[] 本身就是一个类型,所以a变量作为参数传递时,编译器认为只传了一个变量,这个变量的类型是int数组,所以size为1,相当于是List中数组的个数。基本类型是不能作为泛型的参数,要想作为泛型化参数就必须使用其对应的包装类型。 按道理此处应该使用包装类型,但这里却没有报错,因为数组是可以泛型化的,所以转换后在list中就有一个类型为int的数组; 所以 ,以后要避免使用原始类型数组作为asList的输入参数.

    另外,java8的一些写法:学习一下

    //1
    Integer[] boxedInts = IntStream.of(ints).boxed().toArray(Integer[]::new);
    List<Integer> boxedInts = IntStream.of(ints).boxed().collect(Collectors.toList());
    //2
    Integer[] boxedIntArray = Arrays.stream(ints).boxed().toArray(Integer[]::new);
    List<Integer> boxedIntList = Arrays.stream(ints).boxed().collect(Collectors.toList());
    1. 自己实现一个asList方法,能够add和remove; (比较一下自己和源码的写法)
        /**
         * @author zhangdi
         * @param strings
         * @return  目的也是为了让返回的list是一个可操作的list
         * @description   jdk 中Arrays.asList()是一个静态方法: 
         */
        @SafeVarargs
        private static <T> List<T> asList(T... args) {
            List<T> list = new ArrayList<>();
            for (T a : args) {
                list.add(a);
            }
            return list;
        }

    Arrays.asList()的手写第二个版本(目的也是为了让返回的list是一个可操作的list):

        /**
         * @author zhangdi
         * @param a
         * @return
         * @description asList_v2 比用for更为简洁
         */
        @SafeVarargs
        public static <T> List<T> asList_v2(T... a) {  
            List<T> list = new ArrayList<T>();  
            Collections.addAll(list, a);  
            return list;  
        }  

    实际上,addAll底层用的也是for循环,还有一个 result |= c.add(element);操作,可以学习一下

        /**
         * jdk_source:
         * 把所有指定元素添加到集合c中, 有一个元素添加成功就返回true 
         */  
        public static <T> boolean addAll(Collection<? super T> c, T... elements) {  
            boolean result = false;  
            for (T element : elements)  
                result |= c.add(element);  
            return result;  
        } 

    jdk源码 – Arrays.asList(T… a) :
    从这个内部类ArrayList的实现可以看出,它继承了类AbstractList,但是没有重写add和remove方法,没有给出具体的实现。查看一下AbstractList类中对add和remove方法的定义,如果一个list不支持add和remove就会抛出UnsupportedOperationException。

        @SafeVarargs
        @SuppressWarnings("varargs")
        public static <T> List<T> asList(T... a) {
            return new ArrayList<>(a);
        }
    
        /**
         * @serial include
         */
        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);
            }
        }

    参考:
    https://stackoverflow.com/questions/1467913/arrays-aslist-not-working-as-it-should
    https://blog.csdn.net/bruce128/article/details/21640479

  • 相关阅读:
    【9408】数的计数
    【rlz03】十六进制转十进制
    【rlz02】二进制转十进制
    【rlz01】完全数
    【a101】高精度实数加法
    【9406】2的幂次方
    【42.86%】【Codeforces Round #380D】Sea Battle
    【26.83%】【Codeforces Round #380C】Road to Cinema
    【9932】饥饿的牛
    【9933】单词的划分
  • 原文地址:https://www.cnblogs.com/DiZhang/p/12545011.html
Copyright © 2020-2023  润新知