java基础面试题六集合框架
目录
1. List,Set,Map是否继承自collection接口?
3. 写出list、map、set接口的实现类,并说出其特点
9. ArrayList与Vector区别呢?为什么要用ArrayList取代Vector呢?
10. Java.util.ArrayList常用的方法有哪些?
14. Set里的元素是不能重复的,那么用什么方法来区分重复与否呢? 是用==还是equals()? 它们有何区别?
26. HashMap的key存储在哪里?和value存储在一起吗?那么value存储在哪里?说具体点?
29. Collection 和 Collections的区别?
31. HashMap是否线程安全,怎样解决HashMap的线程不安全
1. List,Set,Map是否继承自collection接口?
Map不是。
2. 说说List,Set,Map三者的区别
1. List
- 特性:
List
是一个有序集合,允许元素重复。 - 实现类:常见的实现类有
ArrayList
、LinkedList
和Vector
。 - 索引:
List
支持通过索引来访问元素,索引从 0 开始。 - 适用场景:适用于需要维护元素顺序和允许重复元素的场景,比如存储学生成绩列表、任务列表等。
2. Set
- 特性:
Set
是一个无序集合,不允许元素重复。 - 实现类:常见的实现类有
HashSet
、LinkedHashSet
(保持插入顺序)和TreeSet
(按自然排序或自定义排序)。 - 适用场景:适用于需要确保元素唯一性、不允许重复元素的场景,比如存储用户ID、电话号码等。
3. Map
- 特性:
Map
是一个键值对(key-value)集合,每个键唯一,值可以重复。 - 实现类:常见的实现类有
HashMap
、LinkedHashMap
(按插入顺序)和TreeMap
(按键排序)。 - 适用场景:适用于根据键快速查找值的场景,比如存储用户ID和对应的用户信息、单词和解释等。
3. 写出list、map、set接口的实现类,并说出其特点
1. List 接口的实现类
ArrayList
:查询快,增删慢,不线程安全。LinkedList
:增删快,查询慢,不线程安全。Vector
:查询快,增删慢,线程安全。Stack
:后进先出结构,线程安全。
2. Set 接口的实现类
HashSet
:无序,允许快速操作,不允许重复元素。LinkedHashSet
:有序(按插入顺序),不允许重复元素。TreeSet
:按顺序存储,支持排序,不允许重复元素。EnumSet
:专用于枚举类型的集合,高效。
3. Map 接口的实现类
HashMap
:无序,允许null
键和值,线程不安全。LinkedHashMap
:按插入顺序存储,允许null
键和值。TreeMap
:按键排序存储,不允许null
键。Hashtable
:无序,线程安全,不允许null
键和值。EnumMap
:适合枚举类型键的高效存储。ConcurrentHashMap
:线程安全,高效并发访问。
4. 常见集合类的区别和适用场景
1. List 集合类
ArrayList | 基于数组实现,有序、随机访问效率高,增删元素性能一般,线程不安全。 | 适用于频繁读取数据、元素增删较少的场景,比如商品列表、学生名单等。 |
LinkedList | 基于双向链表实现,有序,增删效率高,但随机访问性能差,线程不安全。 | 适用于频繁增删元素的场景,如队列、栈、任务调度等。 |
Vector | 类似 ArrayList ,但线程安全,方法加锁,性能稍差。 | 适用于多线程环境下的顺序列表存储,线程安全要求不高时推荐使用 ArrayList 。 |
Stack | 继承自 Vector ,实现了后进先出(LIFO)结构。 | 适用于后进先出(LIFO)需求的场景,如撤销操作、浏览历史记录等。 |
2. Set 集合类
HashSet | 基于哈希表实现,无序,不允许重复元素,查询和插入效率高,线程不安全。 | 适用于需要快速查找和去重的场景,如用户名、ID、电话簿等。 |
LinkedHashSet | 继承自 HashSet ,按插入顺序存储,不允许重复元素。 | 适用于需要顺序且无重复的集合场景,比如历史记录、用户输入记录等。 |
TreeSet | 基于红黑树实现,按元素自然顺序或自定义顺序存储,不允许重复元素,查询效率高。 | 适用于需要排序和去重的场景,比如学生成绩排名、字母顺序列表等。 |
EnumSet | 专门用于存储枚举类型,效率高。 | 适用于枚举类型的集合,且枚举类型固定的场景,如表示状态、方向等固定集合。 |
3. Map 集合类
HashMap | 基于哈希表实现,无序存储,允许 null 键和 null 值,线程不安全,查询和插入效率高。 | 适用于快速查找键值对的场景,如缓存、配置参数、数据映射等。 |
LinkedHashMap | 继承自 HashMap ,按插入顺序存储,允许 null 键和 null 值。 | 适用于既要保持插入顺序又需要键值对映射的场景,如按访问顺序排序的数据缓存。 |
TreeMap | 基于红黑树实现,按键排序,不允许 null 键,查询效率高。 | 适用于需要按键排序的场景,比如字典、电话号码簿等。 |
Hashtable | 类似 HashMap ,线程安全,不允许 null 键和 null 值,效率较低。 | 适用于多线程环境下的键值对存储,要求严格的线程安全,如早期的 Java 应用。 |
EnumMap | 专门用于枚举类型的键,效率高,顺序为枚举常量的自然顺序。 | 适用于键为枚举类型的场景,且不允许 null 键,如状态机、固定类别的数据映射。 |
ConcurrentHashMap | 线程安全,分段锁设计并发性能高,适合高并发场景,不允许 null 键和 null 值。 | 适用于多线程环境下高效的键值对存储,比如在线用户状态、并发访问的数据缓存等。 |
4. Queue 接口类
LinkedList | 可作为 Queue 使用,支持队列的 FIFO 操作,增删效率高。 | 适用于普通队列操作,如任务队列、消息队列等。 |
PriorityQueue | 基于堆实现的优先级队列,按元素的自然顺序或自定义排序器排序。 | 适用于优先级调度场景,如事件调度、任务优先级处理等。 |
ArrayDeque | 基于数组实现的双端队列,支持双向操作(两端插入和删除),性能高。 | 适用于双端队列场景,如双向数据流、栈和队列的混合需求。 |
5. 集合的父类是谁?哪些安全的?
在 Java 中,集合类的父接口是 Collection
和 Map
。
集合接口的继承关系
-
Collection
Collection
是所有单一数据集合(如List
和Set
)的父接口。Collection
本身不能直接用于创建集合对象,但它定义了一些集合的基本操作(如添加、删除、遍历等)。- 主要子接口:
List
:有序、允许重复元素。Set
:无序、不允许重复元素。Queue
:有序,通常按照 FIFO(先进先出)规则进行元素操作。
- 主要子接口:
-
Map
Map
是键值对集合的父接口,表示一种将唯一键映射到特定值的数据结构。Map
本身也不能直接用于创建对象,但它定义了键值对的基本操作。- 主要子接口和实现类:
HashMap
:无序存储,允许null
键和null
值,线程不安全。LinkedHashMap
:按插入顺序存储,允许null
键和null
值。TreeMap
:按键排序,不允许null
键。Hashtable
:线程安全,不允许null
键和null
值。ConcurrentHashMap
:线程安全,高效并发。
- 主要子接口和实现类:
线程安全的集合类
在 Java 中,并非所有集合类都是线程安全的,只有部分实现类提供了线程安全的操作。
-
线程安全的集合类:
Vector
和Stack
:这两者都是线程安全的List
实现,Vector
的所有方法都加了同步锁,而Stack
继承自Vector
。Hashtable
:线程安全的Map
实现,不允许null
键和null
值,所有方法都加了同步锁。ConcurrentHashMap
:线程安全的高效Map
实现,分段锁设计保证了更好的并发性,适合高并发场景。CopyOnWriteArrayList
和CopyOnWriteArraySet
:线程安全的List
和Set
实现,适合多读少写的场景,因为每次写操作都会复制整个集合。
-
非线程安全的集合类:
ArrayList
、LinkedList
、HashSet
、HashMap
等标准集合类都是非线程安全的。如果在多线程环境下使用这些集合,需手动同步(如通过Collections.synchronizedList
包装)或使用并发集合。
6. 遍历集合的方式有哪些?
1. 使用 for-each
循环(增强型 for 循环)
适用于所有实现了 Iterable
接口的集合,如 List
、Set
、Queue
等。使用简单、代码简洁。
List<String> list = Arrays.asList("A", "B", "C");
for (String item : list) {
System.out.println(item);
}
2. 使用迭代器(Iterator
)
Iterator
是一种通用遍历方法,适用于所有集合,包括 List
、Set
和 Map
。Iterator
支持在遍历过程中删除元素,确保在多线程环境下的安全性。
List<String> list = Arrays.asList("A", "B", "C");
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
String item = iterator.next();
System.out.println(item);
}
对于 List
类型,还可以使用 ListIterator
,它支持双向遍历和修改元素:
List<String> list = Arrays.asList("A", "B", "C");
ListIterator<String> listIterator = list.listIterator();
while (listIterator.hasNext()) {
String item = listIterator.next();
System.out.println(item);
}
7. List下面有哪些实现
实现类 | 特点 | 适用场景 |
---|---|---|
ArrayList | 基于数组实现,查询快,增删慢,线程不安全。 | 适合频繁查询和顺序存储的场景。 |
LinkedList | 基于双向链表,增删快,查询慢,线程不安全。 | 适合频繁增删操作的场景。 |
Vector | 基于数组实现,线程安全,性能较低。 | 适合多线程环境的顺序列表,但一般不推荐使用。 |
Stack | 继承自 Vector ,实现 LIFO 的栈结构。 | 适合后进先出的场景,如回退功能。 |
CopyOnWriteArrayList | 基于写时复制实现,线程安全,适合读多写少。 | 适合多线程环境下读多写少的场景。 |
8. ArrayList与LinkedList区别?
底层实现 | 动态数组 | 双向链表 |
随机访问效率 | 高(O(1)) | 低(O(n)) |
插入/删除效率 | 末尾高效,中间位置低效 | 首尾高效,中间位置高效(调整引用指针) |
内存占用 | 较小,存储元素本身 | 较大,每个元素需额外存储前后引用指针 |
线程安全性 | 线程不安全 | 线程不安全 |
适用场景 | 频繁读取、少量增删 | 频繁插入、删除(如队列、栈实现) |
9. ArrayList与Vector区别呢?为什么要用ArrayList取代Vector呢?
1. 线程安全性
-
ArrayList:非线程安全,没有同步机制,因此在多线程环境下需要手动同步。
-
Vector:线程安全,内部方法使用
synchronized
进行同步。每次访问或修改数据时都会加锁,保证线程安全性。为什么使用
ArrayList
替代Vector
?
在现代 Java 开发中,通常采用外部同步或使用CopyOnWriteArrayList
或Collections.synchronizedList()
来确保线程安全,而不需要依赖Vector
的同步机制。Vector
的同步是强制的,会影响性能,因此在不需要线程安全的场景下,ArrayList
是更好的选择。
2. 性能
- ArrayList:因为没有同步,性能比
Vector
高,适合单线程环境或手动控制同步的多线程环境。 - Vector:由于同步机制的存在,性能比
ArrayList
低,尤其是在频繁操作的情况下,过多的同步操作会导致性能损耗。
3. 扩容机制
-
ArrayList:默认情况下,容量不足时会扩容为原来的 1.5 倍(即 50%)。
-
Vector:默认情况下,容量不足时会扩容为原来的 2 倍。虽然这种扩容机制减少了扩容次数,但会增加内存消耗。
为什么使用
ArrayList
替代Vector
?ArrayList
的扩容机制相比Vector
更加节约内存,并减少不必要的扩容操作,更加灵活。
10. Java.util.ArrayList常用的方法有哪些?
1. 添加元素
add(E e)
: 将元素e
添加到ArrayList
的末尾。add(int index, E element)
: 在指定的索引位置插入元素element
。
2. 获取元素
get(int index)
: 获取指定索引位置的元素。
3. 修改元素
set(int index, E element)
: 用新的元素element
替换指定索引位置的元素。
4. 删除元素
remove(int index)
: 移除指定索引位置的元素。remove(Object o)
: 移除首次出现的指定元素o
。clear()
: 清空ArrayList
中的所有元素。
5. 查询元素
contains(Object o)
: 检查ArrayList
中是否包含指定元素o
。indexOf(Object o)
: 返回指定元素o
首次出现的索引位置,如果不存在则返回 -1。lastIndexOf(Object o)
: 返回指定元素o
最后一次出现的索引位置。
6. 获取大小
size()
: 返回ArrayList
中的元素个数。
7. 判断是否为空
isEmpty()
: 检查ArrayList
是否为空。
11. Arraylist 是有序还是无序?为什么?
ArrayList
是有序的,因为它会按照元素插入的顺序来存储和访问数据。
原因
-
顺序存储:
ArrayList
基于动态数组实现,每个元素都有一个固定的索引位置。插入时,元素会按顺序依次存储。 -
索引访问:
ArrayList
提供按索引访问元素的方法(如get(int index)
),这意味着我们可以通过索引确定每个元素的顺序。 -
插入顺序:在不排序的情况下,
ArrayList
中的元素会保持插入时的顺序,不会因为插入或删除而打乱已有元素的顺序。
因此,ArrayList
是有序的集合类,其元素按插入顺序排列,适合需要顺序访问或按索引快速访问的场景。
12. Set集合有哪些实现类,分别有什么特点?
1. HashSet
- 特点:基于哈希表实现的集合,不保证元素的顺序。
- 存储顺序:无序(插入顺序不被保证),但可以实现快速存取。
- 速度:插入、删除、查找的时间复杂度为 O(1),性能通常比其他 Set 实现更高。
- 注意事项:由于使用哈希算法,
HashSet
中存储的元素需要正确实现hashCode()
和equals()
方法。
2. LinkedHashSet
- 特点:
HashSet
的子类,基于链表和哈希表的组合实现,保留了元素的插入顺序。 - 存储顺序:有序(按元素的插入顺序存储)。
- 速度:在保证插入顺序的前提下,插入、删除、查找的时间复杂度仍然为 O(1),但略慢于
HashSet
。 - 适用场景:适合需要按插入顺序遍历元素的场景。
3. TreeSet
- 特点:基于红黑树(自平衡的二叉查找树)实现,元素会按自然顺序或自定义比较器排序。
- 存储顺序:有序(按元素的自然顺序或自定义排序规则存储)。
- 速度:插入、删除、查找的时间复杂度为 O(log n),由于排序,性能一般低于
HashSet
和LinkedHashSet
。 - 适用场景:适合需要排序的场景,或者需要按顺序遍历元素的情况。
13. List集合和Set集合的区别?
1. 是否允许重复元素
- List:允许存储重复的元素。例如,一个
List
中可以有多个相同的元素。 - Set:不允许存储重复的元素,每个元素在
Set
中都是唯一的。
2. 元素的存储顺序
- List:有序集合,按照元素的插入顺序进行存储和访问。可以通过索引访问元素。
- Set:一般是无序的(如
HashSet
),但有的实现类(如LinkedHashSet
)会按插入顺序存储,TreeSet
则按自然顺序或自定义比较器排序。
3. 索引支持
- List:支持按索引访问元素,提供了
get(int index)
、indexOf(Object o)
等方法,可以直接访问或查找特定索引位置的元素。 - Set:不支持索引访问,没有按位置访问的功能。
Set
中的元素只能通过迭代器或增强型for
循环来遍历。
4. 常见实现类
- List:
ArrayList
:基于动态数组实现,访问速度快,增删元素效率略低。LinkedList
:基于双向链表实现,增删元素效率较高,但随机访问速度较慢。Vector
:线程安全的List
实现,已较少使用。
- Set:
HashSet
:基于哈希表实现,不保证顺序,查找速度快。LinkedHashSet
:基于哈希表和链表,按插入顺序存储。TreeSet
:基于红黑树实现,按自然顺序或自定义顺序存储,支持排序。
14. Set里的元素是不能重复的,那么用什么方法来区分重复与否呢? 是用==还是equals()? 它们有何区别?
Set
使用equals()
和hashCode()
方法来区分重复元素。==
比较的是内存地址,而equals()
比较的是内容。
15. TreeSet两种排序方式在使用的时候怎么起作用?
- 自然排序:依赖
Comparable
接口中的compareTo()
方法,适用于需要默认排序的情况。 - 定制排序:依赖
Comparator
接口,可以在创建TreeSet
时定义自定义排序规则,用于特定排序需求。
16. TreeSet的数据结构
TreeSet
的底层数据结构是红黑树(Red-Black Tree),它是一种自平衡的二叉搜索树。由于 TreeSet
使用红黑树实现,因此它可以保证集合中元素的有序性和高效的插入、删除、查找操作。
17. 说一下Java的集合Map有哪些Map?
1. HashMap
- 特点:基于哈希表实现,存储无序。键和值都允许为
null
(键只能有一个null
)。 - 线程安全性:非线程安全,如果需要线程安全,可以使用
Collections.synchronizedMap(new HashMap<>())
。 - 时间复杂度:平均情况下,插入、删除、查找的时间复杂度为 O(1)。
- 适用场景:适用于不要求顺序、需要快速查找的场景。
2. LinkedHashMap
- 特点:
HashMap
的子类,保留了键值对的插入顺序(也可以按访问顺序)。 - 线程安全性:非线程安全。
- 时间复杂度:与
HashMap
类似,平均时间复杂度为 O(1)。 - 适用场景:适用于需要维护元素插入顺序或按访问顺序迭代的场景。
3. TreeMap
- 特点:基于红黑树实现,键值对按键的自然顺序或自定义比较器的顺序排序。
- 线程安全性:非线程安全。
- 时间复杂度:查找、插入、删除操作的时间复杂度为 O(log n)。
- 适用场景:适用于需要按顺序遍历键值对的场景。
4. Hashtable
- 特点:基于哈希表实现,早期的
Map
实现类,不允许键或值为null
。 - 线程安全性:线程安全,通过同步方法实现线程安全。
- 时间复杂度:查找、插入、删除的时间复杂度为 O(1)。
- 适用场景:适用于多线程环境下不允许键或值为
null
的情况(不过由于性能问题,现已较少使用)。
18. final怎么用,修饰Map可以继续添加数据吗?
final
修饰Map
后,Map
的引用地址不能改变,即不能重新指向其他Map
对象。final
并不影响Map
的内容,因此可以在Map
中继续添加、删除或修改元素。
19. Set和Map的比较
HashSet底层就是HashMap
LinkedHashSet底层就是LinkedHashMap
TreeSet底层就是TreeMap
20. HashMap说一下,线程安全吗?
为什么 HashMap
不是线程安全的?
-
无同步机制:
HashMap
的方法没有进行同步(synchronized)处理,因此多个线程可以同时操作HashMap
,这可能导致竞态条件(Race Condition),如覆盖或丢失数据。 -
扩容时的并发问题:
HashMap
在需要扩容时,会重新分配内部的哈希桶数组并将数据重新分配到新的桶中。如果多个线程同时触发了扩容,可能会出现环形链表、数据丢失等问题,导致死循环或性能问题。
线程安全的替代方案
-
ConcurrentHashMap:
ConcurrentHashMap
是HashMap
的线程安全替代品。它采用了分段锁(Segmented Lock)机制,在高并发下可以保证线程安全,同时性能也优于使用同步锁的Hashtable
。 -
Collections.synchronizedMap():可以使用
Collections.synchronizedMap()
方法来包装HashMap
,得到一个线程安全的Map
。这种方式会对HashMap
的所有访问方法进行同步处理,但性能较差,因为所有操作都在同一个锁上进行串行化。
21. HashMap和Hashbable的区别?
线程安全性 | 不安全,需手动同步 | 线程安全,自动同步 |
是否允许 null 键/值 | 允许 null 键和 null 值 | 不允许 null 键和值 |
性能 | 更高效(无同步机制) | 性能较差(由于同步机制) |
迭代器 | fail-fast 迭代器(检测并发修改) | 传统的迭代器(没有 fail-fast ) |
继承关系 | 继承自 AbstractMap | 继承自 Dictionary (已废弃) |
使用推荐 | 推荐使用,特别是在现代应用中 | 不推荐使用,已经被淘汰 |
22. Hashtable是怎么实现的,为什么线程安全?
1. Hashtable
的实现结构
Hashtable
是基于哈希表实现的,这与 HashMap
类似。哈希表使用数组和链表(或其他数据结构)来存储数据,其核心思想是通过哈希函数将键(key)映射到数组中的索引位置,从而实现快速的查找、插入和删除。
- 哈希表数组:
Hashtable
底层使用一个数组来存储键值对。每个数组元素是一个链表或树(如果哈希冲突严重)。每个键值对通过哈希函数计算出键的哈希值,进而映射到数组中的一个索引位置。 - 链表解决冲突:当两个不同的键经过哈希函数计算后得到相同的索引时,会发生哈希冲突。
Hashtable
会使用链表来存储这些哈希冲突的键值对。即,多个键值对会被存储在同一个位置的链表中。
2. Hashtable
的线程安全性
Hashtable
的线程安全性主要来源于它对所有方法的同步(synchronization)。在多线程环境中,多个线程可能同时访问同一个 Hashtable
对象,Hashtable
会使用 synchronized
关键字来确保每次只有一个线程能够访问对象的内部状态,从而防止数据竞争和不一致的状态。
23. HashMap和LinkedHashMap的区别
存储顺序 | 无序 | 按插入顺序或访问顺序 |
实现结构 | 基于哈希表 | 基于哈希表 + 双向链表 |
性能 | 较高,操作较快 | 较低,因维护顺序而稍微慢一些 |
内存开销 | 较小 | 较大,额外维护链表指针 |
适用场景 | 不关心顺序的场景 | 需要维持顺序(如缓存、按顺序遍历) |
null 键/值 | 允许(最多一个 null 键) | 允许(最多一个 null 键) |
构造方法 | 简单构造方法 | 支持按顺序排序的构造方法 |
24. HashMap 和 TreeMap 的区别
HashMap
适合那些不关心顺序、需要快速查找、插入和删除的场景,通常性能更好,尤其是在大数据量的情况下。TreeMap
适合那些需要保证键的有序性,或者需要根据键的顺序进行遍历的场景,尤其适用于有序集合操作,如获取最大/最小键值对、按顺序遍历等。
25. HashMap里面实际装的是什么?
HashMap
内部实际存储的是Entry
对象,每个Entry
对象存储一个键值对(key-value)。- 元素是存储在一个数组中,如果发生哈希冲突,使用链表或红黑树来解决。
HashMap
采用哈希算法来确定元素存储的位置,元素的顺序是无序的。
26. HashMap的key存储在哪里?和value存储在一起吗?那么value存储在哪里?说具体点?
key
和value
是存储在Entry
对象中的。Entry
对象 存储在HashMap
的 数组 中。数组中的每个元素是一个链表或红黑树的头节点,用于处理哈希冲突。key
和value
存储在同一个Entry
对象内,而next
指针用于处理冲突时的链表连接。
因此,HashMap
的 key
和 value
会通过 Entry
对象一起存储在哈希表的数组中,而哈希表中的每个位置可能有多个 Entry
对象(在发生哈希冲突时)。
27. 自定义类型可以作为Key么?
- 自定义类型可以作为
HashMap
的key
,但必须确保自定义类正确实现了hashCode()
和equals()
方法,这样才能保证哈希值的正确性和键的唯一性。 - 键对象的
hashCode()
和equals()
方法应该根据对象的实际属性来实现,确保哈希表的效率和正确性。
28. 集合类的工具类是谁?用过工具类哪些方法?
在 Java 中,集合类的工具类是 java.util.Collections
类,它提供了许多静态方法来操作和处理集合(如 List
、Set
、Map
等)。这些方法大大简化了集合的操作,增强了集合类的功能。
常用的 Collections
类方法
1. 排序方法
-
sort(List<T> list)
: 用于对List
集合进行升序排序。排序的依据是元素的自然顺序(即元素实现了Comparable
接口)。 -
sort(List<T> list, Comparator<? super T> c)
: 用于按照指定的Comparator
对List
进行排序,可以自定义排序规则。
2. 反转方法
reverse(List<?> list)
: 用于反转List
中元素的顺序
3. 填充方法
fill(List<? super T> list, T obj)
: 用指定的元素替换List
中的所有元素
4. 查找方法
-
max(Collection<? extends T> coll)
: 返回集合中最大元素。要求元素实现了Comparable
接口。 -
min(Collection<? extends T> coll)
: 返回集合中最小的元素
29. Collection 和 Collections的区别?
Collection
是集合框架的根接口,定义了集合的基本操作方法,所有集合类(如List
、Set
等)都实现了Collection
接口。Collections
是一个工具类,提供了许多静态方法来操作和处理集合,如排序、查找、反转等。它不用于定义集合类型,而是用于执行常见的集合操作。
30. ArrayList 如何实现排序
1. 使用 Collections.sort()
对 ArrayList
进行排序
Collections.sort()
是 Java 提供的一个静态方法,用于对实现了 Comparable
接口的元素进行排序。它对 List
进行升序排序,并且修改原列表。如果要实现自定义的排序顺序,可以传入一个 Comparator
对象。
31. HashMap是否线程安全,怎样解决HashMap的线程不安全
HashMap
本身不是线程安全的,在多线程环境下使用时需要特别小心。- 如果需要线程安全的
Map
,最推荐使用ConcurrentHashMap
,它可以在多线程环境下高效地进行并发操作。 - 如果必须使用
HashMap
,可以通过Collections.synchronizedMap()
或显式加锁(如使用ReentrantLock
)来确保线程安全,但这些方法可能会影响性能。
原文地址:https://blog.csdn.net/m0_75210916/article/details/143656148
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!