List
大约 2 分钟languagejava
不使用Arrays.asList
出错演示
看下面的代码,说明正常声明的 ArrayList 是可以无限 add 元素的,但是通过 Arrays.asList 创建 List 对象后再次 add 元素会报错。 
原理
Arrays.asList 创建的 List 并不是 java.util.ArrayList 而是 java.util.Arrays.ArrayList。后者拥有前者的大部分属性、方法,但是没有 add、remove 方法。
基本数据类型数组
public static void main(String[] args) {
asList01();
asList02();
}
public static void asList01(){
int[] iarr = {1,2,3};
List<int[]> ints = Arrays.asList(iarr);
// 预期 list 的元素个数应该是3个
// 元素数量:1,打印结果:[[I@26a1ab54]
System.out.println("元素数量:" + ints.size() + ",打印结果:" + ints.toString());
}
public static void asList02(){
Integer[] iarr = {1,2,3};
List<Integer> integers = Arrays.asList(iarr);
// 如果使用包装类型就没有问题
// 元素数量:3,打印结果:[1, 2, 3]
System.out.println("元素数量:" + integers.size() + ",打印结果:" + integers.toString());
}
// 还有种解决方法是将基本数据类型转换为包装类型 - 下面是用 boxed
public static void asList03(){
int[] iarr = {1,2,3};
List<Integer> collect = Arrays.stream(iarr).boxed().collect(Collectors.toList());
// 元素数量:3,打印结果:[1, 2, 3]
System.out.println("元素数量:" + collect.size() + ",打印结果:" + collect.toString());
}
迭代器删除元素
list 中要删除 null 不可 list.remove(null),要采用迭代器删除
public <T> List<T> removeNull(List<T> list){
if(list == null) return list;
if(list.size() == 0) return list;
Iterator<T> it = list.iterator();
while(it.hasNext()){
T obj = it.next();
if(obj == null) it.remove();
}
return list;
}
List 和 Set
List
有序可重复,允许多个 null
可使用 Iterator 获取元素,也可以使用 get 传入索引
Set
无序,不可重复,只允许一个 null
只能通过迭代器 Iterator 进行遍历
转换 Map
public static void main(String[] args) {
List<BillCode> list = new ArrayList<>();
BillCode b1 = new BillCode();
b1.setIid(100);
b1.setSid("采购入库");
BillCode b2 = new BillCode();
b2.setIid(100);
b2.setSid("采购退货");
BillCode b3 = new BillCode();
b3.setIid(101);
b3.setSid("车间领料单");
list.add(b1);list.add(b2);list.add(b3);
// (k1,k2)->k1 表示保留重复key中第一次出现的对象,这里是保留“采购入库”
// 相反 (k1,k2)->k2 则表示保留重复 key 中第二次出现的对象
Map<Integer,BillCode> ret = list.stream().collect(Collectors.toMap(a->a.getIid(),a->a,(k1,k2)->k1));
System.out.println(ret);
}
ArrayList 和 LinkedList
ArrayList
- 基于动态数组、连续内存、适合下标访问
- 扩容机制 超出初始容量会产生数组复制,如果在中间插入会出现元素移动
- 在初始容量范围内,使用尾插法性能好,甚至超过 LinkedList
LinkedList
- 基于链表,分散在内存中,适合做插入、删除操作,不适合查询
- 不要使用 for 循环,而要使用迭代器 Iterator。前者的每次循环中都会通过 get(i) 对 list 重新遍历,性能消耗大。
- 不要使用 indexOf 返回元素索引,会对 list 遍历,当结果为空时会导致遍历整个表
