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 有点大材小用了。
- 使用 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