讲解
数组长度固定、功能简陋,实际开发里装一组对象几乎都用集合框架。List 是最常用的集合:有序(元素按插入顺序排)、允许重复、支持下标访问,可以看作「会自动扩容的数组」。最常用的实现是 ArrayList——底层就是数组,按下标访问极快,尾部追加也快,中间插入删除较慢;另一个实现 LinkedList 基于链表,两端增删快,但随机访问慢,日常九成场景选 ArrayList 就够了。
声明集合要指明元素类型(泛型,后面有专章):List names = new ArrayList<>();,变量用接口类型 List,实例用实现类 ArrayList,这就是上一章说的面向接口编程。常用操作:add 追加、get(i) 取下标、set(i, 值) 替换、remove 删除、size() 长度(是方法!)、contains 判断是否包含、isEmpty 判空。遍历用增强 for 或普通 for。注意集合只能装对象不能装基本类型,List 是语法错误,要用对应的包装类 Integer、Double 等——装拆箱(基本类型和包装类自动互转)编译器会代劳,但 List 的 remove(1) 删的是「下标 1」,要删「值 1」得写 remove(Integer.valueOf(1)),这个歧义很经典。
排序用 list.sort(比较器) 或 Collections.sort(list);元素是数字、字符串时按自然顺序排。想在遍历的同时删除元素,直接 remove 会抛 ConcurrentModificationException——正确姿势是 removeIf(条件) 或迭代器的 remove 方法。这一章的示例都会演示。
示例
ArrayList 的增删改查与遍历:
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<String> names = new ArrayList<>();
names.add("李明");
names.add("王芳");
names.add("张伟");
System.out.println("初始:" + names + ",人数:" + names.size());
names.add(1, "陈静");
System.out.println("插入后:" + names);
names.set(0, "李明(班长)");
System.out.println("修改后第一个:" + names.get(0));
names.remove("张伟");
System.out.println("删除后:" + names);
System.out.println("包含王芳?" + names.contains("王芳"));
for (String name : names) {
System.out.println("学生:" + name);
}
}
}
包装类、排序,以及用 removeIf 安全地在遍历语义下删除:
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<Integer> scores = new ArrayList<>();
scores.add(88);
scores.add(59);
scores.add(72);
scores.add(45);
scores.add(91);
scores.sort(null);
System.out.println("升序:" + scores);
scores.removeIf(s -> s < 60);
System.out.println("去掉不及格:" + scores);
int sum = 0;
for (int s : scores) {
sum += s;
}
System.out.println("平均分:" + (double) sum / scores.size());
}
}
常见坑
- 边遍历边 remove:for (String s : list) { list.remove(s); } 抛 ConcurrentModificationException。删除元素用 removeIf、迭代器,或者先收集待删项再统一 removeAll。
- List 的 remove 歧义:remove(1) 按下标删,remove(Integer.valueOf(1)) 按值删,传 int 永远走下标版本。想清楚再写。
- 把 size() 写成 length 或 length():数组用 length 属性、字符串用 length() 方法、集合用 size() 方法,三个一起记,混用编译报错。
- Arrays.asList 返回的「假」List:它返回定长视图,add/remove 直接抛 UnsupportedOperationException。要可变就 new ArrayList<>(Arrays.asList(...)) 包一层,或干脆 List.of(...) 创建不可变列表。
小结
List 有序可重复,首选 ArrayList;增删改查遍历排序一套 API,遍历中删除用 removeIf,基本类型用包装类。下一节学习按键查找和自动去重:Map 与 Set。