Java 集合 + 泛型 超全精讲(零基础易懂)
一、整体概念
1. 集合是什么
集合(Collection):Java 用来存储、操作一组对象的容器,替代数组。
- 数组:长度固定、只能存同类型、功能少
- 集合:长度可变、提供增删改查、遍历、排序等丰富方法,只存对象(基本类型自动装箱)
2. 泛型是什么
泛型(Generic): <E> 语法,限定集合中元素类型,解决两大问题:
1. 编译期类型检查,避免类型转换异常
2. 遍历/取值时不用强转,代码更安全简洁
规范写法:所有集合一律配合泛型使用,不写泛型属于 raw 原始类型,不推荐。
二、集合整体架构(两大根接口)
Java 集合分为 单列集合 和 双列集合 两大派系:
plaintext
集合框架
├─ 单列集合:Collection 接口(单个元素)
│ ├─ List 接口:有序、可重复、有索引
│ │ ├─ ArrayList
│ │ ├─ LinkedList
│ │ └─ Vector(过时)
│ ├─ Set 接口:无序、不可重复、无索引
│ │ ├─ HashSet
│ │ ├─ LinkedHashSet
│ │ └─ TreeSet
│ └─ Queue 队列(了解)
│
└─ 双列集合:Map 接口(键值对 key=value)
├─ HashMap
├─ LinkedHashMap
├─ TreeMap
└─ HashTable(过时)
三、单列集合:Collection
1. 通用常用方法(所有子集合都能用)
java
boolean add(E e) // 添加元素
boolean remove(Object o)// 删除元素
void clear() // 清空集合
boolean contains(Object o) // 判断是否包含
boolean isEmpty() // 是否为空
int size() // 获取元素个数
2. List 系列(有序、可重复、带索引)
(1)ArrayList(最常用)
- 底层:动态数组
- 特点:查询快、增删慢、线程不安全、效率高
- 使用 + 泛型示例:
java
// 泛型<String>:规定只能存字符串
ArrayList<String> list = new ArrayList<>();
list.add("Java");
list.add("集合");
list.add("泛型");
// 遍历1:普通for(有索引可用)
for (int i = 0; i < list.size(); i++) {
String s = list.get(i); // 无需强转
System.out.println(s);
}
// 遍历2:增强for(推荐)
for (String s : list) {
System.out.println(s);
}
(2)LinkedList
- 底层:双向链表
- 特点:查询慢、首尾增删极快
- 特有方法(操作首尾):
java
LinkedList<String> link = new LinkedList<>();
link.addFirst("头");
link.addLast("尾");
link.getFirst();
link.removeFirst();
3. Set 系列(无序、元素唯一、无索引)
(1)HashSet
- 底层:哈希表
- 特点:去重、无序、查询快
- 去重原理:依赖 hashCode() + equals()
java
HashSet<String> set = new HashSet<>();
set.add("A");
set.add("A"); // 重复元素,添加失败
System.out.println(set.size()); // 结果:1
(2)LinkedHashSet
有序 + 去重,底层哈希表+链表,存取顺序一致。
(3)TreeSet
自然排序/自定义排序,元素自动升序。
四、双列集合:Map(键值对 key-value)
- 格式: key=value ,key 唯一,value 可重复
- 无继承自 Collection,独立接口
1. Map 常用方法
java
V put(K key, V value) // 添加/修改键值对
V get(Object key) // 根据key取value
V remove(Object key) // 根据key删除
boolean containsKey() // 判断是否包含键
Set<K> keySet() // 获取所有键
Collection<V> values() // 获取所有值
2. HashMap(工作最常用)
- 底层:哈希表
- 特点:查询极快、键唯一、无序、线程不安全
- 泛型使用: Map<键类型, 值类型>
Map 两种遍历方式
java
// 泛型:键Integer,值String
HashMap<Integer, String> map = new HashMap<>();
map.put(1, "张三");
map.put(2, "李四");
// 方式1:键找值 keySet()
Set<Integer> keys = map.keySet();
for (Integer k : keys) {
String v = map.get(k);
System.out.println(k + "=" + v);
}
// 方式2:键值对对象 entrySet()(推荐,效率高)
Set<Map.Entry<Integer, String>> entries = map.entrySet();
for (Map.Entry<Integer, String> entry : entries) {
System.out.println(entry.getKey() + "=" + entry.getValue());
}
其他 Map
- LinkedHashMap:存取有序的 HashMap
- TreeMap:key 自动排序
五、泛型 详解(重点)
1. 为什么要用泛型?
不使用泛型(原始集合)
java
ArrayList list = new ArrayList();
list.add("字符串");
list.add(123); // 可以存任意对象
// 取值必须强转,极易报错
String s = (String) list.get(1); // 运行异常:ClassCastException
使用泛型(安全)
java
// 规定只能存 String
ArrayList<String> list = new ArrayList<>();
list.add("Hello");
// list.add(123); 编译直接报错,提前拦截问题
String s = list.get(0); // 无需强转
2. 泛型基本语法
(1)定义泛型类
java
// <T> 代表泛型占位符,T、E、K、V 都是约定符号
public class Box<T> {
private T data;
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
// 使用
Box<String> box = new Box<>();
box.setData("测试");
(2)泛型方法
java
public static <E> void print(E e){
System.out.println(e);
}
print(100);
print("Java");
(3)泛型通配符 ?
- <?> :任意类型
- <? extends 类> :上限,只能是该类/子类
- <? super 类> :下限,只能是该类/父类
示例:
java
// 只能接收 Number 及子类(Integer、Double)
public void show(ArrayList<? extends Number> list){}
3. 泛型特点
1. 只在编译期生效,运行时会擦除(泛型擦除)
2. 不能用基本类型,必须用包装类: ArrayList<Integer> 而非 ArrayList<int>
3. 泛型不支持多继承、不能实例化泛型对象
六、集合选择口诀(面试/开发必记)
1. 查多增删少 → 用 ArrayList
2. 首尾频繁增删 → 用 LinkedList
3. 需要去重 → 用 HashSet
4. 去重且要有序 → 用 LinkedHashSet
5. 存键值对、查询快 → 用 HashMap
6. 键值对且有序 → 用 LinkedHashMap
七、高频面试考点精简
1. ArrayList 和 LinkedList 区别
- ArrayList:数组,查询快、增删慢
- LinkedList:链表,查询慢、首尾增删快
2. HashSet 怎么去重
先判断 hashCode() ,再判断 equals() ,都相同才判定重复。
3. 泛型作用
类型安全、编译检查、避免强转、代码复用。
4. Map 遍历两种方式
keySet、entrySet(entrySet 效率更高)。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)