马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
x
问题1:说说 List,Set,Map 三者的区别?
在 Java 中,List、Set 和 Map 是最常用的集合框架(Collection Framework)接口,它们的重要区别如下:
1. List(列表)
- 特点:
- 允许存储 重复元素。
- 保持插入次序,即元素的存储次序与遍历次序同等。
- 允许null值(可存多个)。
- 提供索引访问,可以使用索引(get(int index))获取元素。
- 常见实现类:
- ArrayList(基于数组,查询快,增删慢)
- LinkedList(基于双向链表,查询慢,增删快)
- Vector(线程安全的 ArrayList,但性能较低)
- 使用场景:
- 需要有序存储元素,而且可能有重复值,例如存储一系列日志纪录、待服务项等。
2. Set(集合)
- 特点:
- 不允许存储重复元素。
- 无法通过索引访问元素(没有 get(int index) 方法)。
- 默认情况下不包管元素的存储次序(TreeSet 除外)。
- 允许最多一个 null 值(HashSet 允许,TreeSet 不允许)。
- 常见实现类:
- HashSet(基于哈希表,存取快,但无序)
- LinkedHashSet(有序的 HashSet,按插入次序存储)
- TreeSet(基于红黑树,自动排序,不允许 null)
- 使用场景:
- 需要存储唯一的元素集合,例如存储用户ID、标签等。
3. Map(映射)
- 特点:
- 以 键值对 (key-value) 形式存储数据。
- Key 不可重复,但 Value 可以重复。
- 允许最多一个 null 键,多值 null 值(TreeMap 不允许 null 键)。
- 常见实现类:
- HashMap(无序,基于哈希表,存取快,线程不安全)
- LinkedHashMap(有序的 HashMap,按插入次序存储)
- TreeMap(排序的 Map,基于红黑树,按 Key 排序)
- 使用场景:
- 需要存储键值映射,如学生学号-姓名、配置项键值对等。
总结对比
特性ListSetMap是否允许重复元素允许不允许Key 不允许重复,Value 允许是否包管次序包管插入次序HashSet 无序,LinkedHashSet 包管插入次序,TreeSet 排序HashMap 无序,LinkedHashMap 保持插入次序,TreeMap 按 key 排序是否可存 null允许多个仅 HashSet 允许一个HashMap 允许一个 null Key,多 null Value,TreeMap 不允许 null Key访问方式通过索引 (get(int index))迭代器 (Iterator)通过 Key (get(K key))实用场景需要有序存储并允许重复,如购物车、使命列表需要唯一元素,如用户ID需要键值映射,如用户信息 简单影象:
- List 适合 有序、可重复 场景。
- Set 适合 唯一、无序(或排序) 场景。
- Map 适合 键值映射 场景。
问题2: List,Set,Map 在 Java 中分别由哪些对应的实现类?底层的数据结构?
在 Java 中,List、Set 和 Map 各自有多个常见的实现类,它们的底层数据结构不同,实用于不同的场景。下面详细分析各自的实现类及其底层结构。
1. List(列表)
List 重要有以下几个实现类:
(1)ArrayList
- 底层数据结构:动态数组
- 特点:
- 查询速度快(基于数组,通过索引访问,O(1))。
- 插入和删除慢(涉及数据移动,O(n))。
- 允许 null 元素,允许重复元素。
- 线程不安全。
- 实用场景:
- 读操纵多,写操纵少的场景,如缓存数据、搜索结果等。
(2)LinkedList
- 底层数据结构:双向链表
- 特点:
- 查询速度慢(链表遍历,O(n))。
- 插入、删除速度快(O(1),不涉及数据移动)。
- 允许 null 元素,允许重复元素。
- 线程不安全。
- 实用场景:
(3)Vector
- 底层数据结构:动态数组
- 特点:
- 与 ArrayList 类似,但线程安全(方法加了 synchronized)。
- 查询快,插入删除慢。
- 允许 null 元素,允许重复元素。
- 实用场景:
2. Set(集合)
Set 重要有以下几个实现类:
(1)HashSet
- 底层数据结构:哈希表(基于 HashMap 实现,值存 HashMap 的 key)
- 特点:
- 无序存储元素(元素次序可能变革)。
- 不允许重复元素。
- 允许 null 值(但只能有一个)。
- 查询、插入、删除速度快(平均 O(1))。
- 实用场景:
(2)LinkedHashSet
- 底层数据结构:哈希表 + 双向链表
- 特点:
- 有序(按照插入次序存储)。
- 不允许重复元素。
- 查询、插入、删除速度比 HashSet 略慢(受链表影响)。
- 实用场景:
- 既需要去重,又要保持插入次序的场景,如LRU缓存。
(3)TreeSet
- 底层数据结构:红黑树(自平衡二叉搜索树)
- 特点:
- 自动排序(默认按升序排序,可自定义 Comparator)。
- 不允许重复元素。
- 不允许 null。
- 查询、插入、删除速度 O(log n)(比 HashSet 慢)。
- 实用场景:
3. Map(映射)
Map 重要有以下几个实现类:
(1)HashMap
- 底层数据结构:数组 + 单链表 + 红黑树(JDK 1.8 之后)
- 特点:
- Key 无序存储,不允许重复,允许 null(最多一个)。
- Value 允许重复,允许 null。
- 查询、插入、删除快(O(1),最坏 O(log n))。
- 线程不安全。
- 实用场景:
- 需要快速查找 key-value 数据,如缓存、配置项存储。
(2)LinkedHashMap
- 底层数据结构:哈希表 + 双向链表
- 特点:
- 按插入次序存储(可以用 accessOrder=true 变成 LRU 访问次序)。
- 查询、插入、删除速度略低于 HashMap(受链表影响)。
- 实用场景:
(3)TreeMap
- 底层数据结构:红黑树
- 特点:
- Key 自动排序(默认升序,可自定义 Comparator)。
- Key 不允许 null(Value 允许)。
- 查询、插入、删除 O(log n)。
- 实用场景:
- 需要按 key 排序的 Map,如时间戳排序的日志数据。
(4)Hashtable
- 底层数据结构:哈希表
- 特点:
- 线程安全(方法加 synchronized)。
- 不允许 null key 和 null value。
- 查询、插入、删除 O(1)。
- 效率较低(同步开销大)。
- 实用场景:
- 需要线程安全的 Map(但通常用 ConcurrentHashMap 替换)。
(5)ConcurrentHashMap
- 底层数据结构:分段锁 + 哈希表(JDK 1.7),CAS + 哈希表 + 红黑树(JDK 1.8)
- 特点:
- 线程安全,高效(分段锁 / CAS 机制)。
- 不允许 null key 和 null value。
- 查询、插入、删除比 Hashtable 快(O(1))。
- 实用场景:
总结
类型
实现类
底层数据结构
重要特点
实用场景
List
ArrayList
动态数组
查询快,增删慢
读多写少
LinkedList
双向链表
插入/删除快,查询慢
频繁增删
Vector
动态数组
线程安全
多线程
Set
HashSet
哈希表
无序,不重复
唯一集合
LinkedHashSet
哈希表 + 双向链表
插入次序
唯一且有序
TreeSet
红黑树
自动排序
唯一且排序
Map
HashMap
数组 + 链表 + 红黑树
无序,查询快
快速查找
LinkedHashMap
哈希表 + 双向链表
按插入次序
LRU缓存
TreeMap
红黑树
Key 自动排序
需要排序
Hashtable
哈希表
线程安全,低效
线程安全(少用)
ConcurrentHashMap
哈希表 + CAS
高并发
并发情况
问题3:有哪些集合是线程不安全的?怎么办理呢?
1. 线程不安全的集合
(1)ArrayList(线程不安全)
- 底层数据结构:动态数组
- 问题:多线程情况下,多个线程同时 add() 可能导致 数据覆盖、数组扩容时的数据丢失。
- 办理方案:
- 使用 Vector(线程安全,但性能较低)
- 使用 Collections.synchronizedList(new ArrayList<>())
- 使用 CopyOnWriteArrayList(实用于读多写少的场景)
(2)HashMap(线程不安全)
- 底层数据结构:数组 + 链表(JDK 1.7),数组 + 链表 + 红黑树(JDK 1.8)
- 问题:
- JDK 1.7 多线程 put() 时可能引发死循环(rehash 过程中链表反转)。
- JDK 1.8 仍然是线程不安全的,多线程 put() 可能会丢数据。
- 办理方案:
- 使用 ConcurrentHashMap(高性能并发 Map,推荐)
- 使用 Collections.synchronizedMap(new HashMap<>())(性能较低)
- 使用 Hashtable(线程安全但性能差,较少使用)
2. ArrayList vs. Vector(高频对比)
对比项
ArrayList
Vector
线程安全
❌ 非线程安全
✅ 线程安全(synchronized)
底层数据结构
动态数组
动态数组
扩容方式
1.5x 扩容
2x 扩容
性能
高(无锁)
低(同步开销大)
实用场景
单线程
多线程(但 CopyOnWriteArrayList 更推荐)
|