Java中初始化List的5种方法 /List的2种去重方式

前言

List是java重要的数据结构之一,我们经常接触到的有ArrayList、Vector和LinkedList三种,他们都继承来自java.util.Collection接口,类图如下:
在这里插入图片描述

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

		//方式1-1
        List<String> linkedList = new LinkedList<>();
        linkedList.add("a");
        linkedList.add("b");
        linkedList.add("c");
        for (String s : linkedList){
            System.out.print(s+" ");
        }
        System.out.println();
        //方式1-3
        List<String> linkedList3 = new ArrayList<>();
        linkedList3.add("a");
        linkedList3.add("b");
        linkedList3.add("c");
        for (String s : linkedList3){
            System.out.print(s+" ");
        }

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

	  //方式2
        List<String> linkedList4 = new LinkedList<String>(){{
            add("1");
            add("3");
            add("2");
        }};
        for (String s : linkedList4){
            System.out.print(s+" ");
        }

外层的{}定义了一个 LinkedList 的匿名内部类。内层的{}的定义了一个实例初始化代码块。 这个代码块在初始化内部类时执行。所以这里相当于定义了一个匿名内部类,并使用add添加元素来初始化。

这种方式有几个缺点:

使用匿名内部类,会有效率上的损失。当然在大多数情况下,这点效率都是可接受的。

静态内部类持有所在外部类的引用。如果需要将 List 返回给到其他地方使用,可能造成内存泄漏。

3.使用 Arrays.asList

        //方式3
        List<String> ArraysasList = Arrays.asList("a","b","c");
        for (String s : ArraysasList){
            System.out.print(s+" ");
        }

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

但也有几点需要注意:

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

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

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

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

  1. 使用 Lists (JDK9)
        //方式5
        List<String> list1 = Lists.newArrayList("a","b","c");

List的2种去重方式

我们大家都知道,set集合的特点就是没有重复的元素。如果集合中的数据类型是基本数据类型,可以直接将list集合转换成set,就会自动去除重复的元素,这个就相对比较简单。
在这里插入图片描述

当list集合中存储的类型是对象类型的时候,我们就不能简单的只把list集合转换成set集合。
当list集合中存储的是对象时,我们需要在对象的实体类中去重写equals()方法和hashCode()方法,如下:

 @Override
    public boolean equals(Object arg0) {
        People p = (People) arg0;
        return name.equals(p.name) && phoneNumber.equals(p.phoneNumber);
    }

    @Override
    public int hashCode() {
        String str = name + phoneNumber;
        return str.hashCode();
    }

equals()
比较两个对象时,首先先去判断两个对象是否具有相同的地址,如果是同一个对象的引用,则直接放回true;如果地址不一样,则证明不是引用同一个对象,接下来就是挨个去比较两个字符串对象的内容是否一致,完全相等返回true,否则false。
hashCode()官方定义:
hashcode方法返回该对象的哈希码值。支持该方法是为哈希表提供一些优点,例如,java.util.Hashtable 提供的哈希表。

hashCode 的常规协定是:
在 Java 应用程序执行期间,在同一对象上多次调用 hashCode 方法时,必须一致地返回相同的整数,前提是对象上 equals 比较中所用的信息没有被修改。从某一应用程序的一次执行到同一应用程序的另一次执行,该整数无需保持一致。

如果根据 equals(Object) 方法,两个对象是相等的,那么在两个对象中的每个对象上调用 hashCode 方法都必须生成相同的整数结果。

以下情况不是必需的:如果根据 equals(java.lang.Object) 方法,两个对象不相等,那么在两个对象中的任一对象上调用 hashCode 方法必定会生成不同的整数结果。但是,程序员应该知道,为不相等的对象生成不同整数结果可以提高哈希表的性能。

实际上,由 Object 类定义的 hashCode 方法确实会针对不同的对象返回不同的整数。(这一般是通过将该对象的内部地址转换成一个整数来实现的,但是 JavaTM 编程语言不需要这种实现技巧。)

当equals方法被重写时,通常有必要重写 hashCode 方法,以维护 hashCode 方法的常规协定,该协定声明相等对象必须具有相等的哈希码。

List去重的方法很多,可以用for循环或者使用java8新特性stream

参考:https://mp.weixin.qq.com/s/w8BiefeVL8nOIm0llDb3Og

猜你喜欢

转载自blog.csdn.net/liuge36/article/details/84998640