Java集合(二): List 源码剖析

x33g5p2x  于2021-09-25 转载在 Java  
字(3.6k)|赞(0)|评价(0)|浏览(409)

Java 中经常需要使用到 List,下面简单介绍几种常见的初始化方式。

1.构造 List 后使用 List.add 初始化

List<String> stringList = new LinkedList<>();
1.
stringList.add("a");
1.
stringList.add("b");
1.
stringList.add("c");

这是最常规的做法,用起来不太方便。

2.使用 {{}} 双括号语法

List<String> stringList = new LinkedList<String>(){{
1.
add("a");
1.
add("b");
1.
add("c");
1.
}};

这种方式相对方便了一些。

外层的 {} 定义了一个 LinkedList 的匿名内部类。内层的 {} 的定义了一个实例初始化代码块。 这个代码块在初始化内部类时执行。

所以这里相当于定义了一个匿名内部类,并使用 add 添加元素来初始化。

这种方式有几个缺点:

  • 使用匿名内部类,会有效率上的损失。当然在大多数情况下,这点效率都是可接受的。
  • 静态内部类持有所在外部类的引用。如果需要将 List 返回给到其他地方使用,可能造成内存泄漏。

3.使用 Arrays.asList

List<String> stringList = Arrays.asList("a", "b", "c");

这种方式使用了 java.util.Arrays 的静态方法。写法上比之前的两种都更简洁,也没有构造匿名内部类的效率问题。

但也有几点需要注意:

  • Arrays.asList 返回的是 Arrays 的静态内部类(静态内部类不持有所在外部类的引用)。

这个内部类继承自 AbstractList,实现了 RandomAccess,内部使用了一个数组来存储元素。但是不支持增删元素。这点需要注意。如果只是使用 Arrays.asList 来初始化常量,那么这点就不算什么问题了。

  • Arrays.asList 的参数如果是基本类型的数组时,需要留意返回值可能和你预期的不同。

int[] intArray = new int[]{1, 2, 3};
1.
Integer[] integerArray = new Integer[]{1, 2, 3};
1.
1.
**List<int[]> intArrayList** = Arrays.asList(intArray);
1.
**List<Integer> integerList** = Arrays.asList(integerArray);
1.
List<Integer> integerList2 = Arrays.asList(1, 2, 3);

这里 Arrays.asList(intArray) 的返回值是 List<int[]> 而不是 List<Integer>。这一点也算不上问题,只是使用时需要留意。

如果能在 Java 中做到尽量使用 List 和 Integer,尽量避免使用 int 等基本类型和 [] 这种较为底层的数据结构即可避免。

虽然本文是在讲初始化 List,但这里的 {{}} 双括号语法同样可用于初始化 Map 等其他众多类型。

相对而言,Arrays.asList 就只能用于初始化 List 类型了。

  1. 使用 Stream (JDK8)
List<String> list = Stream.of("a", "b", "c").collect(Collectors.toList());

使用了 JDK8 的 Stream 来初始化。 单纯初始化 List,使用 Stream 有点大材小用了。

  1. 使用 Lists (JDK9)
List<String> list = Lists.newArrayList("a", "b", "c");

这个和 Arrays.asList 一样简洁清晰。

1、8种初始化方式

public class Test111 {

    private static final Boolean TRUE = true;
    public static void main(String[] args) {
        //初始化--1、常规方法
        final List<String> list = Lists.newArrayList();
        list.add("a");
        list.add("b");
        //取值--1、直接输出
        System.out.println(list);//[a,b]
        //取值--2、增强for
        for(String str:list){
            System.out.print(str);
        }
        //取值--3、迭代器
        for(Iterator iterator = list.iterator();iterator.hasNext();){
            String s = (String)iterator.next();
            System.out.print(s);
        }
        //取值--4、for
        for(int i = 0;i<list.size();i++){
            System.out.print(list.get(i));
        }

        //初始化--2、Arrays.asList(),// 生成的list不可变
//        private final E[] a;
//        ArrayList(E[] array) {
//            a = Objects.requireNonNull(array);
//        }
        List<String> list1 = Arrays.asList("1","2", "3");
        System.out.print(list1);
//        list1.add("4");//java.lang.UnsupportedOperationException
        System.out.print(list1);
         如果要可变需要用ArrayList包装一下
        List<String> list2 = Lists.newArrayList(list1);
        System.out.println(list2);

        //初始化--3、Collections.nCopies(),// 生成的list不可变
        List<String> list3 = Collections.nCopies(3,"1");
        // 如果要可变需要用ArrayList包装一下
        List<String> dogs = new ArrayList<>(Collections.nCopies(3, "dog"));
        dogs.add("dog");
        System.out.println("dogs: " + dogs);

        //初始化--4、Lists.newArrayList
        List<String> list4 = Lists.newArrayList("1", "2", "3");
        System.out.println("getList4: " + list4);

        //初始化--5、匿名内部类
        List<String> list5 = new ArrayList<String>(){{
            add("1");
            add("2");
        }};
        System.out.println(list5);

        //初始化--6、ImmutableList.of
        List<String> list6 = ImmutableList.of("1","2");
        System.out.println(list6);

        //初始化--7、Stream
        List<String> list7 = Stream.of("1","2").collect(Collectors.toList());
        System.out.println(list7);

        //初始化--8、List--java9
//        List<String> list8 = List.of("1");
//        System.out.println(list8);
    }
}

相关文章