zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    阿里云 k8s 部署 Spring Cloud Alibaba 微服务实践 (四) 自动化部署
    阿里云 k8s 部署 Spring Cloud Alibaba 微服务实践 (三) 服务观测
    阿里云 k8s 部署 Spring Cloud Alibaba 微服务实践 (二) 部署微服务程序
    阿里云 k8s 部署 Spring Cloud Alibaba 微服务实践 (一) 部署 Nacos
    C++知识点
    libmkl 学习笔记
    基于tesseract-OCR进行中文识别
    poco编译与运行
    Linux下的I/O复用与epoll详解(转载)
    高并发网络编程之epoll详解(转载)
  • 原文地址:https://www.cnblogs.com/DiZhang/p/12545011.html
Copyright © 2011-2022 走看看