Java List 入门指南:从零开始掌握列表操作
本文面向 Java 初学者,用通俗易懂的方式讲解
List的核心概念和常用操作。
一、什么是 List?
想象你去超市购物,手里拿着一张购物清单:
1. 牛奶 2. 面包 3. 鸡蛋 4. 苹果这张清单有几个特点:
- 有序:第一项是牛奶,第二项是面包,顺序是固定的
- 可重复:你可以写两瓶牛奶
- 可随时增减:走到半路可以加一项"酸奶",也可以划掉"鸡蛋"
Java 中的List就是这样一种数据结构——有序、可重复、可动态增减的集合。
二、List 是一个接口
在 Java 中,List是一个接口(Interface),它定义了"列表应该有哪些能力",但本身不能直接new。我们常用的实现类有两个:
| 实现类 | 特点 | 适用场景 |
|---|---|---|
ArrayList | 底层数组实现,查询快,增删慢 | 绝大多数场景的首选 |
LinkedList | 底层链表实现,增删快,查询少 | 频繁在头部插入/删除时使用 |
初学者记住:不确定用什么的时候,选
ArrayList就对了。
三、创建一个 List
importjava.util.ArrayList;importjava.util.List;publicclassListDemo{publicstaticvoidmain(String[]args){// 创建一个存放字符串的 ArrayListList<String>fruits=newArrayList<>();System.out.println(fruits);// 输出: []}}几个关键点:
List<String>中的<String>叫泛型,表示这个列表只能放String类型的数据new ArrayList<>()右边的<>可以留空(菱形语法),编译器会自动推断类型- 创建后默认是空列表
[]
四、List 的常用操作(CRUD)
4.1 添加元素 —add()
List<String>fruits=newArrayList<>();fruits.add("苹果");// 添加到末尾fruits.add("香蕉");fruits.add("橘子");fruits.add(1,"葡萄");// 在索引 1 的位置插入System.out.println(fruits);// 输出: [苹果, 葡萄, 香蕉, 橘子]⚠️注意索引从 0 开始!第一个元素的索引是
0,第二个是1,以此类推。
4.2 访问元素 —get()
Stringfirst=fruits.get(0);// 获取第一个元素Stringsecond=fruits.get(1);// 获取第二个元素System.out.println("第一个: "+first);// 第一个: 苹果System.out.println("第二个: "+second);// 第二个: 葡萄4.3 获取大小 —size()
System.out.println("列表里有 "+fruits.size()+" 种水果");// 输出: 列表里有 4 种水果💡 是
size()而不是length!数组用.length,List 用.size(),别搞混了。
4.4 修改元素 —set()
fruits.set(0,"西瓜");// 把索引 0 的元素改为"西瓜"System.out.println(fruits);// 输出: [西瓜, 葡萄, 香蕉, 橘子]4.5 删除元素 —remove()
fruits.remove("葡萄");// 按内容删除(删除第一个匹配项)fruits.remove(0);// 按索引删除System.out.println(fruits);// 输出: [香蕉, 橘子]⚠️小心歧义!
remove(1)会被当作"删除索引 1 的元素",而不是"删除值为 1 的元素"。如果要删除整数,用remove(Integer.valueOf(1))。
4.6 查找元素 —contains()和indexOf()
List<String>fruits=newArrayList<>();fruits.add("苹果");fruits.add("香蕉");fruits.add("橘子");// 判断是否包含某个元素booleanhasApple=fruits.contains("苹果");System.out.println("有苹果吗?"+hasApple);// 有苹果吗?true// 查找元素的索引位置intindex=fruits.indexOf("香蕉");System.out.println("香蕉在索引: "+index);// 香蕉在索引: 1// 不存在时返回 -1intnotFound=fruits.indexOf("芒果");System.out.println("芒果在索引: "+notFound);// 芒果在索引: -1五、遍历 List(三种方式)
这是最常用的操作之一——逐个访问列表中的元素。
方式一:for 循环(经典写法)
for(inti=0;i<fruits.size();i++){System.out.println("第"+(i+1)+"个: "+fruits.get(i));}适合需要用到索引的场景。
方式二:增强 for 循环(for-each)⭐ 推荐
for(Stringfruit:fruits){System.out.println(fruit);}写法简洁,适合只需要读取元素的场景。
方式三:forEach + Lambda(Java 8+)
fruits.forEach(fruit->System.out.println(fruit));更简洁,也支持方法引用:
fruits.forEach(System.out::println);六、List 与数组的转换
实际开发中经常需要在 List 和数组之间互相转换。
List → 数组
String[]arr=fruits.toArray(newString[0]);数组 → List
String[]colors={"红","绿","蓝"};List<String>colorList=newArrayList<>(Arrays.asList(colors));// 或者更简洁(Java 9+)List<String>colorList2=List.of("红","绿","蓝");⚠️
Arrays.asList()返回的是一个固定大小的列表,不能add和remove。如果需要增删,请用new ArrayList<>(Arrays.asList(...))包一层。
七、List 的排序
importjava.util.Collections;List<Integer>numbers=newArrayList<>();numbers.add(3);numbers.add(1);numbers.add(4);numbers.add(1);numbers.add(5);// 升序排序Collections.sort(numbers);System.out.println(numbers);// [1, 1, 3, 4, 5]// 降序排序Collections.sort(numbers,Collections.reverseOrder());System.out.println(numbers);// [5, 4, 3, 1, 1]// 字符串列表排序List<String>names=newArrayList<>();names.add("Charlie");names.add("Alice");names.add("Bob");Collections.sort(names);System.out.println(names);// [Alice, Bob, Charlie]八、常用方法速查表
| 方法 | 作用 | 示例 |
|---|---|---|
add(e) | 添加元素到末尾 | list.add("A") |
add(i, e) | 在指定位置插入 | list.add(0, "B") |
get(i) | 获取指定位置的元素 | list.get(0) |
set(i, e) | 修改指定位置的元素 | list.set(0, "C") |
remove(i) | 删除指定位置的元素 | list.remove(0) |
remove(e) | 删除第一个匹配的元素 | list.remove("A") |
size() | 获取元素个数 | list.size() |
contains(e) | 是否包含某元素 | list.contains("A") |
indexOf(e) | 查找元素索引 | list.indexOf("A") |
isEmpty() | 列表是否为空 | list.isEmpty() |
clear() | 清空所有元素 | list.clear() |
addAll(c) | 批量添加 | list.addAll(otherList) |
subList(from, to) | 截取子列表 | list.subList(0, 2) |
九、容易踩的坑
坑 1:遍历时删除元素
// ❌ 错误写法:会抛出 ConcurrentModificationExceptionfor(Stringfruit:fruits){if(fruit.equals("苹果")){fruits.remove(fruit);}}// ✅ 正确写法:使用 IteratorIterator<String>it=fruits.iterator();while(it.hasNext()){if(it.next().equals("苹果")){it.remove();}}// ✅ 正确写法:使用 removeIf(Java 8+)fruits.removeIf(fruit->fruit.equals("苹果"));坑 2:List 存的是引用
List<List<String>>matrix=newArrayList<>();List<String>row=newArrayList<>();row.add("A");matrix.add(row);row.set(0,"B");System.out.println(matrix.get(0).get(0));// 输出: B(也被改了!)因为matrix和row指向同一个对象。如果不想互相影响,需要深拷贝。
坑 3:泛型不支持基本类型
// ❌ 编译错误List<int>nums=newArrayList<>();// ✅ 使用包装类List<Integer>nums=newArrayList<>();nums.add(1);// 自动装箱:int → Integerintn=nums.get(0);// 自动拆箱:Integer → int十、ArrayList vs LinkedList 怎么选?
ArrayList LinkedList 随机访问 ⭐⭐⭐ ⭐ 头部插入 ⭐ ⭐⭐⭐ 尾部插入 ⭐⭐⭐ ⭐⭐⭐ 内存占用 较少 较多(额外指针)结论:99% 的场景用ArrayList即可。只有当你需要频繁在列表头部插入/删除时,才考虑LinkedList。
十一、小结
List是 Java 中最常用的集合之一,特点是有序、可重复、可动态增删- 日常开发优先使用
ArrayList - 核心操作:
add、get、set、remove、size、contains - 遍历推荐用 for-each 或
forEach - 注意遍历时不要直接
remove,用Iterator或removeIf - 泛型用包装类(
Integer而不是int)
💡练习建议:打开你的 IDE,照着上面的代码敲一遍,亲手运行看看结果。学编程最有效的方法就是——动手写代码!