【从零开始java学习|第二十二篇】集合进阶之collection
目录
概述
1、根接口:Collection
2、两大家族
3、记忆口诀
一、单列集合顶层接口 ——Collection
核心方法
定义Collectioncoll= new ArrayList<>(); 怎么理解?
二、Collection 的遍历方式
1. 迭代器遍历(Iterator)
编辑
2. 增强 for 遍历(for-each)
3. Lambda 表达式遍历
三、List 中常见的方法和五种遍历方式
常见方法
五种遍历方式
1. 迭代器遍历(同 Collection)
2. 增强 for 遍历(同 Collection)
3. Lambda 表达式遍历(同 Collection)
4. 普通 for 循环(利用索引)
5. ListIterator 遍历(可双向遍历)
概述
这张图是 Java 集合框架(Java Collections Framework)的“家谱”速览,用一句话就能背下来:
Collection 是根;List 和 Set 是两大家族;每个家族下面再分“谁有序、谁重复、谁带索引”。
1、根接口:Collection
-
所有单列集合(一次只装一个元素)的共同祖先。
-
定义了最通用的方法:
add
/remove
/contains
/size
…
2、两大家族
家族 | 特点(图中红字) | 常见实现类 | 底层结构与使用场景 |
---|---|---|---|
List | 有序、可重复、有索引 | ArrayList | 数组,查询快、增删慢 |
LinkedList | 双向链表,增删快、查询慢 | ||
Vector | 老式线程安全数组(已过时) | ||
Set | 无序、不重复、无索引 | HashSet | 哈希表,去重首选,最快 |
LinkedHashSet | 哈希表+链表,保留插入顺序 | ||
TreeSet | 红黑树,自动排序(升序/自定义) |
3、记忆口诀
List 系列:“有序可重复,带索引,像数组”
Set 系列:“无序不重复,无索引,像数学集合”
想保插入顺序 → 用LinkedHashSet
想自动排序 → 用TreeSet
只想去重最快 → 用HashSet
把图旋转 90° 就是一条线:
Collection → List|Set → 具体实现类
,先选家族(List/Set),再选特性(是否排序/是否线程安全/是否频繁增删),最后挑实现类即可。
一、单列集合顶层接口 ——Collection
java.util.Collection
是 Java 单列集合的顶层接口,它定义了所有单列集合(如 List
、Set
)通用的操作方法,是整个单列集合体系的基础。
核心方法
- 添加元素:
boolean add(E e)
,向集合中添加元素,成功返回true
。 - 删除元素:
boolean remove(Object o)
,删除集合中指定的元素,成功返回true
;void clear()
,清空集合中的所有元素。 - 判断元素:
boolean contains(Object o)
,判断集合中是否包含指定元素;boolean isEmpty()
,判断集合是否为空。 - 获取长度:
int size()
,获取集合中元素的个数。 - 转数组:
Object[] toArray()
,将集合转换为数组。
定义Collection<Student>coll= new ArrayList<>(); 怎么理解?
这行代码:
Collection<Student> coll = new ArrayList<>();
= 面向接口编程的“标准姿势”,一句话拆解:
-
左边
Collection<Student>
把变量声明成接口类型(而不是具体类),以后想换LinkedList
、HashSet
、TreeSet
…只需改右边,调用者代码不动。 -
右边
new ArrayList<>()
真正创建的是ArrayList 实现类对象,但向上转型为接口类型,只暴露 Collection 接口定义的功能(add/remove/contains/size…)。 -
泛型
<Student>
告诉编译器:这个集合里只能放 Student 对象,放错类型直接报错,取出时无需强转。 -
好处
-
解耦:调用代码只依赖接口,不依赖具体实现。
-
灵活:随时替换实现类,性能/特性需求变化零入侵。
-
可读:一眼看出“这是存 Student 的集合”,类型安全。
-
“左边接口,右边实现;接口变量,实现对象。”
更详细的说:
一、把变量声明成接口类型(而不是具体类)
-
先回忆两种写法
ArrayList<Student> list1 = new ArrayList<>(); // 左边是具体类 Collection<Student> list2 = new ArrayList<>(); // 左边是接口
-
区别就像“遥控器”
-
左边是遥控器外形(变量类型)。
-
右边是真实机器(真正 new 出来的对象)。
用
ArrayList
遥控器 → 上面 20 多个 ArrayList 特有按钮(如ensureCapacity
)都能按。
用Collection
遥控器 → 只有 10 个通用按钮(add/remove/contains/size…),看不到 ArrayList 特有按钮。 -
-
为什么要“少按钮”
以后你想把机器换成LinkedList
或HashSet
:Collection<Student> list2 = new LinkedList<>(); // 遥控器外形不变
后面所有代码(list2.add / list2.contains)一句不用改,因为它们只用到 Collection 那 10 个通用按钮。
这就叫“面向接口编程”——变量类型尽量用高层接口,代码更通用、更灵活。
二、向上转型为接口类型(只暴露 Collection 功能)
-
向上转型(Up-casting)
把子类对象当成父类型/接口类型来引用,不需要强制转换,Java 自动完成:ArrayList<> 子类对象 → Collection<> 父接口变量
-
暴露范围
转型后,编译器只让你调用 Collection 接口里有的方法,ArrayList 自己的特有方法(如ensureCapacity
)被“隐藏”了,防止误用,也降低耦合。
三、泛型是什么意思
-
没有泛型时(Java 5 以前)
List list = new ArrayList(); // 任何 Object 都能放 list.add("abc"); list.add(123); // 编译通过 String s = (String) list.get(1); // 运行期 ClassCastException!
-
加入泛型后
Collection<Student> coll = new ArrayList<>();
在编译阶段就告诉编译器:“这个集合里只能放 Student 对象”。
coll.add("abc"); // 直接红线报错,连运行机会都不给
四、取出时无需强转
继续上面的例子:
-
有泛型
Collection<Student> coll = new ArrayList<>(); coll.add(new Student("张三", 23)); Student stu = coll.iterator().next(); // 直接拿到 Student 类型
-
没有泛型
Collection coll = new ArrayList(); coll.add(new Student("张三", 23)); Student stu = (Student) coll.iterator().next(); // 必须强转,否则编译错误
泛型在编译期自动插入隐式强转,所以你写代码时省掉了 (Student)
,既简洁又安全。
二、Collection 的遍历方式
1. 迭代器遍历(Iterator)
迭代器是专门用于遍历集合的工具,通过 Collection
的 iterator()
方法获取迭代器对象。
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;public class IteratorDemo {public static void main(String[] args) {Collection<String> collection = new ArrayList<>();collection.add("Java");collection.add("Python");collection.add("C++");Iterator<String> iterator = collection.iterator();while (iterator.hasNext()) { // 判断是否有下一个元素String element = iterator.next(); // 获取下一个元素System.out.println(element);}}
}
2. 增强 for 遍历(for-each)
增强 for 循环是一种简化的遍历方式,内部基于迭代器实现,适用于遍历集合或数组。
import java.util.ArrayList;
import java.util.Collection;public class ForEachDemo {public static void main(String[] args) {Collection<String> collection = new ArrayList<>();collection.add("Java");collection.add("Python");collection.add("C++");for (String element : collection) {System.out.println(element);}}
}
3. Lambda 表达式遍历
Java 8 及以上版本支持通过 Lambda 表达式结合 forEach()
方法遍历集合,代码更加简洁。
import java.util.ArrayList;
import java.util.Collection;public class LambdaDemo {public static void main(String[] args) {Collection<String> collection = new ArrayList<>();collection.add("Java");collection.add("Python");collection.add("C++");collection.forEach(element -> System.out.println(element));}
}
三、List 中常见的方法和五种遍历方式
List
是 Collection
的子接口,它的元素有序、可重复、有索引,除了继承 Collection
的方法外,还新增了许多基于索引操作的方法。
常见方法
- 添加元素:
void add(int index, E element)
,在指定索引处添加元素;boolean addAll(int index, Collection<? extends E> c)
,在指定索引处添加另一个集合中的所有元素。 - 获取元素:
E get(int index)
,获取指定索引处的元素。 - 修改元素:
E set(int index, E element)
,修改指定索引处的元素,返回被修改的旧元素。 - 删除元素:
E remove(int index)
,删除指定索引处的元素,返回被删除的元素。 - 查找索引:
int indexOf(Object o)
,返回指定元素在集合中第一次出现的索引;int lastIndexOf(Object o)
,返回指定元素在集合中最后一次出现的索引。 - 子列表:
List<E> subList(int fromIndex, int toIndex)
,获取从fromIndex
(包含)到toIndex
(不包含)的子列表。
五种遍历方式
1. 迭代器遍历(同 Collection)
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;public class ListIteratorDemo {public static void main(String[] args) {List<String> list = new ArrayList<>();list.add("Java");list.add("Python");list.add("C++");Iterator<String> iterator = list.iterator();while (iterator.hasNext()) {String element = iterator.next();System.out.println(element);}}
}
2. 增强 for 遍历(同 Collection)
import java.util.ArrayList;
import java.util.List;public class ListForEachDemo {public static void main(String[] args) {List<String> list = new ArrayList<>();list.add("Java");list.add("Python");list.add("C++");for (String element : list) {System.out.println(element);}}
}
3. Lambda 表达式遍历(同 Collection)
import java.util.ArrayList;
import java.util.List;public class ListLambdaDemo {public static void main(String[] args) {List<String> list = new ArrayList<>();list.add("Java");list.add("Python");list.add("C++");list.forEach(element -> System.out.println(element));}
}
4. 普通 for 循环(利用索引)
由于 List
有索引,可通过普通 for
循环结合 get(index)
方法遍历。
import java.util.ArrayList;
import java.util.List;public class ListForDemo {public static void main(String[] args) {List<String> list = new ArrayList<>();list.add("Java");list.add("Python");list.add("C++");for (int i = 0; i < list.size(); i++) {String element = list.get(i);System.out.println(element);}}
}
5. ListIterator 遍历(可双向遍历)
ListIterator
是 Iterator
的子接口,专门用于 List
,支持向前和向后遍历,还能在遍历过程中修改集合。
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;public class ListListIteratorDemo {public static void main(String[] args) {List<String> list = new ArrayList<>();list.add("Java");list.add("Python");list.add("C++");ListIterator<String> listIterator = list.listIterator();// 向前遍历while (listIterator.hasNext()) {String element = listIterator.next();System.out.println(element);}// 向后遍历while (listIterator.hasPrevious()) {String element = listIterator.previous();System.out.println(element);}}
}
通过对 Collection
及 List
的学习,能更灵活地操作和遍历集合,满足不同场景下的数据处理需求,为后续学习 Set
等其他集合类型打下基础。
如果我的内容对你有帮助,请点赞,评论,收藏。接下来我将继续更新相关内容!