JAVA集合知识点
- 集合判空
- 集合转Map
- 集合遍历
- 集合去重
- 集合转数组
- 数组转集合
- 正确将数组转为ArrayList的方法
- 手动实现工具类
- new List
- Java8 推荐的Stream
- Guava
- 使用 Apache Commons Collections
- 使用 Java9 的 List.of()方法
集合判空
判断所有集合内部的元素是否为空,使用 isEmpty() 方法,而不是 size()==0 的方式。
这是因为 isEmpty() 方法的可读性更好,并且时间复杂度为 O(1)。
集合转Map
在使用 java.util.stream.Collectors 类的 toMap() 方法转为 Map 集合时,一定要注意当 value 为 null 时会抛 NPE 异常。
原因:
toMap()方法内部调用了Map接口的merge()方法。而merge()方法会先调用Objects.requireNonNUll()方法判断value是否为空,如果为空,则抛出:NullPointerException。
集合遍历
不要在 foreach 循环里进行元素的 remove/add 操作。remove 元素请使用 Iterator 方式,如果并发操作,需要对 Iterator 对象加锁。
通过反编译可以看到foreach的底层依赖Iterator。但是,remove/add操作直接调用的是集合自己的方法,而不是Iterator的remove/add方法。
这样会令Iterator发现有元素多,或少了。会抛出ConcurrentModificationException异常。这是单线程状态下产生的fail-fast机制。
fail-fast机制:(fail-fast是一种错误检测机制,一旦检测到可能发生错误,就立马抛出异常,程序不继续往下执行。)
多个线程对fail-fast集合进行修改时,会抛出ConcurrentModificationException。单线程也会出现这个情况。
Java8 开始,可以使用 Collection#removeIf()方法删除满足特定条件的元素:
List<Integer> list = new ArrayList<>();
for (int i = 1; i <= 10; ++i) {
list.add(i);
}
list.removeIf(filter -> filter % 2 == 0);
/* 删除list中的所有偶数 */
System.out.println(list); /* [1, 3, 5, 7, 9] */
集合去重
可以利用 Set 元素唯一的特性,可以快速对一个集合进行去重操作,避免使用 List 的 contains() 进行遍历去重或者判断包含操作。
集合转数组
使用集合转数组的方法,必须使用集合的 toArray(T[] array),传入的是类型完全一致、长度为 0 的空数组。
toArray(T[] array) 方法的参数是一个泛型数组,如果 toArray 方法中没有传递任何参数的话返回的是 Object类 型数组。
String [] s= new String[]{
"dog", "lazy", "a", "over", "jumps", "fox",
};
List<String> list = Arrays.asList(s);
Collections.reverse(list);
//没有指定类型的话会报错
s=list.toArray(new String[0]);
由于 JVM 优化,new String[0]作为Collection.toArray()方法的参数现在使用更好,new String[0]就是起一个模板的作用,指定了返回数组的类型,0 是为了节省空间,因为它只是为了说明返回的类型。
数组转集合
使用工具类 Arrays.asList() 把数组转换成集合时,不能使用其修改集合相关的方法, 它的 add/remove/clear 方法会抛出 UnsupportedOperationException 异常。
举例使用如下:
String[] myArray = {"Apple", "Banana"};
List<String> myList = Arrays.asList(myArray);
//上面两个语句等价于下面一条语句
List<String> myList = Arrays.asList("Apple","Banana");
JDK中该方法源码如下:
/**
*返回由指定数组支持的固定大小的列表。
* 此方法作为基于数组和基于集合的API之间的桥梁,
* 与 Collection.toArray()结合使用。返回的List是可序列化
* 并实现RandomAccess接口。
*/
public static <T> List<T> asList(T... a) {
return new ArrayList<>(a);
}
注意:
- Arrays.asList()是泛型方法,传递的数组必须是对象数组,而不是基本类型。
int[] myArray = {1, 2, 3};
List myList = Arrays.asList(myArray);
System.out.println(myList.size());//1
System.out.println(myList.get(0));//数组地址值
System.out.println(myList.get(1));
//报错:ArrayIndexOutOfBoundsException
//出现了数组下标超出了其取值范围
int[] array = (int[]) myList.get(0);
System.out.println(array[0]);//1
当传入一个原生数据类型数组时,Arrays.asList() 的真正得到的参数就不是数组中的元素,而是数组对象本身!此时 List 的唯一元素就是这个数组。
可以使用包装类来解决上述问题:
Integer[] myArray = {1, 2, 3};
- 使用集合的修改方法会抛出异常
List myList = Arrays.asList(1, 2, 3);
myList.add(4);//运行时报错:UnsupportedOperationException
myList.remove(1);//运行时报错:UnsupportedOperationException
myList.clear();//运行时报错:UnsupportedOperationException
Arrays.asList() 方法返回的并不是 java.util.ArrayList ,而是 java.util.Arrays 的一个内部类,这个内部类并没有实现集合的修改方法或者说并没有重写这些方法。
List myList = Arrays.asList(1, 2, 3);
System.out.println(myList.getClass());
//class java.util.Arrays$ArrayList
正确将数组转为ArrayList的方法
手动实现工具类
//JDK1.5+
static <T> List<T> arrayToList(final T[] array) {
final List<T> l = new ArrayList<T>(array.length);
for (final T s : array) {
l.add(s);
}
return l;
}
Integer [] myArray = { 1, 2, 3 };
System.out.println(arrayToList(myArray).getClass());
//class java.util.ArrayList
new List
List list = new ArrayList<>(Arrays.asList("a", "b", "c"))
Java8 推荐的Stream
Integer [] myArray = { 1, 2, 3 };
List myList = Arrays.stream(myArray).
collect(Collectors.toList());
//基本类型也可以实现转换(依赖boxed的装箱操作)
int [] myArray2 = { 1, 2, 3 };
List myList = Arrays.stream(myArray2).boxed().
collect(Collectors.toList());
Guava
对于不可变集合,可以使用ImmutableList类和of(),copyOf()工厂方法:(参数不能为空)
List<String> il = ImmutableList.of("string", "elements");
// from varargs
List<String> il = ImmutableList.copyOf(aStringArray);
// from array
对于可变集合,可以使用Lists类和newArrayList()工厂方法:
List<String> l1 = Lists.newArrayList(anotherListOrCollection);
// from collection
List<String> l2 = Lists.newArrayList(aStringArray);
// from array
List<String> l3 = Lists.newArrayList("or", "string");
// from varargs
使用 Apache Commons Collections
List<String> list = new ArrayList<String>();
CollectionUtils.addAll(list, str);
使用 Java9 的 List.of()方法
Integer[] array = {1, 2, 3};
List<Integer> list = List.of(array);