集合-探索
目录
- 1、集合在数学中的概念 VS 集合在编程中的概念
- 在数学中的概念:
- 在计算机科学中的概念:
- 2、Java中的集合框架(类图)
- 3、集合适用于什么场景?
- 4、集合有什么特点?
- Java中集合的特点
- 集合框架的通用特点
- 主要集合接口及其特点
- 1. Collection接口
- 2. List接口
- 3. Set接口
- 4. Queue接口
- 5. Map接口
- 集合的线程安全性
- Java 8+新增特性
- 5、用集合有什么好处?
- 使用Java集合的好处
- 1. 动态大小
- 2. 丰富的API
- 3. 类型安全(通过泛型)
- 4. 多种数据结构实现
- 5. 高性能优化
- 6. 线程安全选项
- 7. 与现代Java特性集成
- 8. 内存效率
- 9. 标准化接口
- 10. 迭代器支持
- 实际应用示例
- 6、代码示例
- Java 集合使用场景大全
- 一、List 接口实现类
- 1. ArrayList
- 2. LinkedList
- 二、Set 接口实现类
- 1. HashSet
- 2. TreeSet
- 三、Map 接口实现类
- 1. HashMap
- 2. LinkedHashMap
- 3. TreeMap
- 四、Queue/Deque 实现类
- 1. PriorityQueue
- 2. ArrayDeque
- 五、并发集合(Java.util.concurrent)
- 1. ConcurrentHashMap
- 2. CopyOnWriteArrayList
- 六、特殊场景集合
- 1. EnumSet/EnumMap
- 2. WeakHashMap
- 选择集合的原则
1、集合在数学中的概念 VS 集合在编程中的概念
在数学中的概念:
集合,简称集,是数学中一个基本概念,也是集合论的主要研究对象。集合论的基本理论创立于19世纪,关于集合的最简单的说法就是在朴素集合论(最原始的集合论)中的定义,即集合是“确定的一堆东西”,集合里的“东西”则称为元素。现代的集合一般被定义为:由一个或多个确定的元素所构成的整体。
在计算机科学中的概念:
计算机科学中,集合是一组可变数量的数据项(也可能是0个)的组合,这些数据项可能共享某些特征,需要以某种操作方式一起进行操作。一般来讲,这些数据项的类型是相同的,或基类相同(若使用的语言支持继承)。列表(或数组)通常不被认为是集合,因为其大小固定,但事实上它常常在实现中作为某些形式的集合使用。集合的种类包括列表,集,多重集,树和图。枚举类型可以是列表或集。
2、Java中的集合框架(类图)
来源:https://pdai.tech/md/java/collection/java-collection-all.html
3、集合适用于什么场景?
不同类型的集合实现适用于不同的场景。
需求 | 建议集合类型 |
---|---|
需要索引、有序、可重复 | List(ArrayList) |
无序、不重复元素集合 | Set(HashSet) |
键值映射结构 | Map(HashMap) |
FIFO 队列或优先级队列 | Queue(LinkedList, PriorityQueue) |
栈或双端队列结构 | Deque(ArrayDeque) |
4、集合有什么特点?
Java中集合的特点
Java集合框架(Java Collections Framework)提供了多种集合类型,每种集合都有其特定的特点和用途。以下是Java集合的主要特点:
集合框架的通用特点
- 动态大小:与数组不同,集合可以动态增长或缩小
- 类型安全:支持泛型,可以在编译时检查类型
- 高性能:针对不同操作进行了优化
- 丰富的API:提供了大量便捷的方法
主要集合接口及其特点
1. Collection接口
- 所有集合类的根接口
- 基本操作:add(), remove(), contains(), size()等
- 子接口:List, Set, Queue
2. List接口
- 有序集合:元素按插入顺序保存
- 允许重复元素
- 可通过索引访问:get(int index)
- 主要实现类:
- ArrayList:基于动态数组,随机访问快
- LinkedList:基于链表,插入删除快
- Vector:线程安全的ArrayList(已过时,推荐使用CopyOnWriteArrayList)
3. Set接口
- 不允许重复元素
- 无序(某些实现如LinkedHashSet保持插入顺序)
- 主要实现类:
- HashSet:基于哈希表,最快查找
- LinkedHashSet:保持插入顺序的HashSet
- TreeSet:基于红黑树,元素自动排序
4. Queue接口
- **先进先出(FIFO)**数据结构
- 主要实现类:
- LinkedList:也可用作Queue
- PriorityQueue:优先级队列
- ArrayDeque:双端队列
5. Map接口
- 键值对存储:不是Collection的子接口
- 键唯一,值可重复
- 主要实现类:
- HashMap:基于哈希表,最快查找
- LinkedHashMap:保持插入顺序
- TreeMap:基于红黑树,键自动排序
- Hashtable:线程安全的HashMap(已过时,推荐使用ConcurrentHashMap)
集合的线程安全性
- 大多数集合不是线程安全的(如ArrayList, HashMap)
- 线程安全替代方案:
- Collections.synchronizedXXX()方法包装
- java.util.concurrent包中的并发集合(如ConcurrentHashMap, CopyOnWriteArrayList)
Java 8+新增特性
- Stream API支持
- Lambda表达式支持
- 新增方法如removeIf(), forEach()等
选择集合类型时应根据具体需求考虑元素的唯一性、排序需求、访问方式和性能要求等因素。
5、用集合有什么好处?
使用Java集合的好处
Java集合框架相比传统数组提供了许多优势,以下是使用集合的主要好处:
1. 动态大小
- 自动扩容:集合可以动态增长或缩小,无需手动管理容量
- 无需预先确定大小:不像数组需要初始化时指定固定长度
- 示例:
ArrayList
会根据需要自动扩容
2. 丰富的API
- 内置操作方法:提供大量现成方法如
add()
,remove()
,contains()
等 - 算法支持:排序、搜索、过滤等操作都有现成实现
- 示例:
Collections.sort()
可以直接对集合排序
3. 类型安全(通过泛型)
- 编译时类型检查:可以指定集合存储的元素类型
- 避免类型转换错误:减少运行时
ClassCastException
- 示例:
List<String>
只能存储字符串
4. 多种数据结构实现
- 不同需求不同实现:
- 需要快速访问:
ArrayList
- 频繁插入删除:
LinkedList
- 去重需求:
HashSet
- 键值对存储:
HashMap
- 需要快速访问:
- 示例:
HashMap
提供O(1)时间复杂度的查找
5. 高性能优化
- 算法优化:各实现类针对不同操作进行了优化
- 自动扩容策略:如
ArrayList
按1.5倍增长平衡内存和性能 - 示例:
HashSet
基于哈希表实现快速查找
6. 线程安全选项
- 并发集合:
java.util.concurrent
包提供线程安全实现 - 同步包装器:
Collections.synchronizedList()
等 - 示例:
ConcurrentHashMap
高性能线程安全Map
7. 与现代Java特性集成
- Stream API支持:可直接转换为流进行操作
- Lambda表达式友好:支持函数式编程风格
- 示例:
list.stream().filter(...).map(...).collect(...)
8. 内存效率
- 自动收缩:某些集合在元素移除时会自动缩小容量
- 稀疏集合:如
EnumSet
对枚举类型有特别优化
9. 标准化接口
- 统一的操作方式:所有集合遵循相同的接口规范
- 易于替换实现:如从
ArrayList
改为LinkedList
只需修改构造函数
10. 迭代器支持
- 统一的遍历方式:通过
Iterator
或增强for循环 - 安全删除:迭代时可通过迭代器安全删除元素
- 示例:
for (String item : list) { ... } // 或 Iterator<String> it = list.iterator(); while(it.hasNext()) { ... }
实际应用示例
// 传统数组的局限性
String[] array = new String[10]; // 固定大小
array[0] = "A";
// array[10] = "B"; // 抛出ArrayIndexOutOfBoundsException// 使用ArrayList的优势
List<String> list = new ArrayList<>();
list.add("A"); // 自动扩容
list.add("B");
list.remove("A"); // 简单操作
Collections.sort(list); // 内置排序
集合框架的这些优势使得它成为Java开发中处理数据集合的首选工具,大大提高了开发效率和代码质量。
6、代码示例
Java 集合使用场景大全
Java集合框架提供了多种数据结构,每种都有其最适合的使用场景。以下是主要集合类及其典型应用场景:
一、List 接口实现类
1. ArrayList
- 场景:需要频繁随机访问元素
- 典型应用:
- 商品列表展示
- 分页查询结果存储
- 需要根据索引快速获取元素的场景
- 示例:
List<Product> productList = new ArrayList<>();
// 添加商品
productList.add(new Product("手机", 2999));
// 随机访问
Product p = productList.get(0);
2. LinkedList
- 场景:需要频繁在头部/中间插入删除元素
- 典型应用:
- 实现队列(Queue)或栈(Stack)
- 浏览器历史记录
- 撤销操作记录
- 示例:
LinkedList<String> history = new LinkedList<>();
// 添加浏览记录
history.addFirst("首页");
history.addFirst("商品页");
// 模拟后退按钮
String lastPage = history.removeFirst();
二、Set 接口实现类
1. HashSet
- 场景:需要快速判断元素是否存在
- 典型应用:
- 用户注册时用户名去重
- 黑名单过滤
- 标签系统
- 示例:
Set<String> usernames = new HashSet<>();
// 添加用户名
usernames.add("user1");
// 检查是否已存在
if(usernames.contains("user1")) {System.out.println("用户名已存在");
}
2. TreeSet
- 场景:需要元素自动排序
- 典型应用:
- 排行榜
- 有序的标签云
- 范围查询
- 示例:
TreeSet<Integer> scores = new TreeSet<>();
scores.add(90);
scores.add(85);
// 获取大于等于88的最小分数
Integer higher = scores.ceiling(88);
三、Map 接口实现类
1. HashMap
- 场景:需要键值对快速查找
- 典型应用:
- 用户会话管理(userId -> User对象)
- 缓存系统
- 词频统计
- 示例:
Map<String, User> sessionMap = new HashMap<>();
// 存储会话
sessionMap.put("sessionId123", currentUser);
// 查找用户
User user = sessionMap.get("sessionId123");
2. LinkedHashMap
- 场景:需要保持插入顺序的Map
- 典型应用:
- 最近访问记录(LRU缓存)
- 需要保持顺序的配置项
- 示例:
LinkedHashMap<String, String> settings = new LinkedHashMap<>();
settings.put("theme", "dark");
settings.put("font", "Arial");
// 遍历时保持插入顺序
3. TreeMap
- 场景:需要按键排序的Map
- 典型应用:
- 字典/词典应用
- 价格区间映射
- 带排序的配置
- 示例:
TreeMap<String, String> dictionary = new TreeMap<>();
dictionary.put("apple", "苹果");
dictionary.put("banana", "香蕉");
// 自动按键排序
四、Queue/Deque 实现类
1. PriorityQueue
- 场景:需要优先级处理的元素集合
- 典型应用:
- 任务调度系统
- 医院急诊分诊
- Dijkstra算法实现
- 示例:
PriorityQueue<Task> taskQueue = new PriorityQueue<>();
taskQueue.add(new Task("紧急任务", 1));
taskQueue.add(new Task("普通任务", 3));
// 总是先取出优先级高的
Task next = taskQueue.poll();
2. ArrayDeque
- 场景:需要高效的双端队列
- 典型应用:
- 滑动窗口算法
- 工作窃取算法
- 撤销/重做功能
- 示例:
Deque<Integer> window = new ArrayDeque<>();
// 滑动窗口操作
window.addLast(1);
window.removeFirst();
五、并发集合(Java.util.concurrent)
1. ConcurrentHashMap
- 场景:高并发环境下的键值存储
- 典型应用:
- 在线用户统计
- 共享缓存
- 计数器
- 示例:
ConcurrentHashMap<String, AtomicInteger> counters = new ConcurrentHashMap<>();
// 线程安全的计数
counters.computeIfAbsent("clicks", k -> new AtomicInteger()).incrementAndGet();
2. CopyOnWriteArrayList
- 场景:读多写少的并发列表
- 典型应用:
- 监听器列表
- 配置信息存储
- 白名单
- 示例:
CopyOnWriteArrayList<EventListener> listeners = new CopyOnWriteArrayList<>();
// 安全的遍历和修改
for(EventListener l : listeners) {l.onEvent();
}
六、特殊场景集合
1. EnumSet/EnumMap
- 场景:枚举类型的集合操作
- 典型应用:
- 权限系统
- 状态机实现
- 选项标志
- 示例:
EnumSet<DayOfWeek> weekend = EnumSet.of(DayOfWeek.SATURDAY, DayOfWeek.SUNDAY);
2. WeakHashMap
- 场景:需要自动清理无用键值对的Map
- 典型应用:
- 缓存实现
- 临时对象存储
- 示例:
WeakHashMap<Key, BigObject> cache = new WeakHashMap<>();
// 当Key不再被强引用时,条目会自动移除
选择集合的原则
-
是否需要键值对:
- 是 → 选择Map实现
- 否 → 选择Collection实现
-
是否需要排序:
- 是 → TreeSet/TreeMap
- 否 → HashSet/HashMap
-
是否需要保持插入顺序:
- 是 → LinkedHashSet/LinkedHashMap
- 否 → 其他实现
-
是否多线程环境:
- 是 → 并发集合
- 否 → 普通集合
-
性能考虑:
- 随机访问多 → ArrayList
- 插入删除多 → LinkedList
通过合理选择集合类型,可以大大提高程序的效率和可维护性。