Java集合面试题下
大约 4 分钟
Java集合面试题下
1. HashMap 和 Hashtable 的区别:
线程安全性:
Hashtable是线程安全的,它的所有方法都被synchronized修饰。由于对整个数据结构加锁,性能会有一定的影响,尤其在多线程环境下竞争较激烈时,可能导致较低的效率。HashMap是非线程安全的,但性能较高。为了保证线程安全,可以使用ConcurrentHashMap代替。
对
null值的支持:Hashtable不允许null键和值。若尝试插入null,会抛出NullPointerException。HashMap允许一个null键和多个null值。
初始化容量和扩容规则:
Hashtable默认初始容量为 11,负载因子为 0.75,扩容时将容量变为原来的 2n + 1。HashMap默认初始容量为 16,负载因子为 0.75,扩容时将容量翻倍。HashMap使用 2 的幂次方来扩展容量,这是为了提高性能,避免哈希冲突。
继承体系:
Hashtable继承自Dictionary类,Dictionary是 JDK 1.0 引入的,已被弃用。HashMap继承自AbstractMap,并实现了Map接口。
迭代器:
Hashtable使用Enumeration进行迭代,而Enumeration并不支持 fail-fast 机制,即修改集合时不会抛出异常。HashMap使用Iterator,它是 fail-fast 的,如果在迭代过程中修改集合,将抛出ConcurrentModificationException。
底层实现:
Hashtable底层使用的是数组加链表来存储数据,但没有进行链表转红黑树的优化。HashMap在 JDK 1.8 以后对哈希冲突的处理做了优化,当链表长度超过阈值时(默认为 8),会将链表转换为红黑树以提高查询性能。
2. HashMap 和 HashSet 的区别:
数据结构:
HashSet是一个基于HashMap实现的 Set 接口,底层是使用HashMap来存储数据。它不允许重复的元素,因此底层会利用HashMap来判断元素是否已存在。HashMap是一个基于键值对的映射,存储数据时会关联一个key和一个value。
重复元素:
HashSet不允许存储重复的元素。如果插入一个已经存在的元素,它会忽略该元素。HashMap允许key的重复,但不允许key和value配对的重复(即相同的key不会存在多个相同的value)。
接口和功能:
HashSet只实现了Set接口,提供元素的无序存储,不保证插入顺序。HashMap实现了Map接口,提供键值对存储,支持对键的查找和访问。
3. HashMap 和 TreeMap 的区别:
排序:
TreeMap是有序的,它根据键的自然顺序或构造时提供的比较器对元素进行排序。HashMap是无序的,它的元素没有特定的顺序。
性能:
TreeMap的查找、插入和删除操作的时间复杂度为 O(log n),这是因为它底层使用红黑树实现。HashMap的查找、插入和删除操作的时间复杂度为 O(1),但在极端情况下(如大量哈希冲突)可能会退化为 O(n)。
适用场景:
- 如果需要按照键的排序存储数据,可以使用
TreeMap。 - 如果不关心排序,只需要快速存储和查找数据,可以使用
HashMap。
- 如果需要按照键的排序存储数据,可以使用
4. HashSet 如何检查重复元素:
HashSet通过调用其底层HashMap的containsKey方法来检查元素是否已存在。如果已经存在,则不插入新元素。底层通过hashCode()和equals()方法来比较元素。
5. HashMap 的底层实现:
HashMap底层使用数组和链表(或红黑树)来实现存储。每个数组元素是一个链表(或树的根节点),哈希冲突发生时,元素将以链表形式存储。链表过长时(超过阈值),会转换为红黑树来提高查找效率。
6. HashMap 线程不安全的原因:
HashMap不是线程安全的,因为它没有同步机制来保证并发访问时的正确性。当多个线程同时对HashMap进行读写操作时,可能会出现数据不一致或死循环等问题。因此,在多线程环境中,应使用ConcurrentHashMap或手动同步访问HashMap。
