JAVA面试题

1个回答

旧巷情书 2025-07-23 23:57:14
JAVA面试题解答1. HashMap 和 Hashtable 有什么区别?

答案

  • 线程安全性:HashMap 是线程不安全的,而 Hashtable 是线程安全的。这意味着在多线程环境下,Hashtable 能够保证数据的一致性,但性能相对较低;HashMap 则没有这种保证,但性能较高。
  • null 值支持:HashMap 允许使用 null 作为 key 或 value,而 Hashtable 不允许。如果尝试在 Hashtable 中插入 null key 或 value,将抛出 NullPointerException。
  • 遍历方式:Hashtable 使用 Enumeration 进行遍历,而 HashMap 没有专门的迭代器,但可以通过遍历 key 的集合或者 entry 对,也可以使用 Java 8 的函数接口(如 Stream API)进行遍历。

图片展示:(由于 markdown 格式限制,无法直接展示图片,但以下链接为图片地址,可在浏览器中查看)

2. 如何决定使用 HashMap 还是 TreeMap?

答案

  • 有序性:HashMap 是无序集合,而 TreeMap 是有序集合。TreeMap 中的元素按照 key 的自然顺序或指定的 Comparator 进行排序。
  • 底层存储结构:HashMap 的底层存储结构是数组,而 TreeMap 的底层存储结构是红黑树。这决定了 TreeMap 在插入、删除和查找操作时能够保持有序性,但性能相对较低。
  • 使用场景:当数据量大且需要按照 key 排序时,使用 TreeMap;当数据量小且对顺序无要求时,使用 HashMap。若查找操作占大部分时,使用 HashMap;插入删除大部分时使用 TreeMap。
3. 说一下 HashMap 的实现原理?

答案

  • 底层结构:HashMap 底层封装了一个 Entry 数组,元素位置基于 Object 类的 hashCode 函数计算。
  • 哈希冲突解决:当出现哈希冲突时,HashMap 采用拉链法(链表法)解决冲突,即每个数组元素都是一个链表,存储具有相同哈希值的 Entry 对象。
  • 扩容机制:当当前数组达到阈值(loadFactor * capacity)时,触发扩容。在 JDK 1.8 及以后版本中,如果节点的链表元素个数大于 8 时,还会将链表转换成红黑树以提高查找效率。
  • 相关成员属性

    capacity:默认值为 16,表示数组的容量。

    loadFactor:默认值为 0.75,表示负载因子。

    size:默认值为 0,表示当前 HashMap 中存储的键值对的数量。

4. 说一下 HashSet 的实现原理?

答案

  • 底层实现:HashSet 底层为 HashMap,其方法几乎都是调用 HashMap 的相关方法实现。HashSet 中的元素作为 HashMap 的 key 存储,而 value 则使用一个固定对象(如常量对象)表示。
5. ArrayList 和 LinkedList 的区别是什么?

答案

  • 底层实现:ArrayList 底层实现为数组,当数组元素个数达到数组长度时,数组将进行动态扩容;LinkedList 底层实现为链表,原则上不存在元素个数饱和的情况。
  • 随机访问性能:ArrayList 常用于随机访问场景,因为数组可以通过索引直接访问元素;而 LinkedList 在随机访问时需要从头节点开始遍历。
  • 添加删除性能:在添加删除场景中,ArrayList 主要耗时为 System.arraycopy(数组复制),而 LinkedList 则是通过 for 循环寻找插入位置。当数据量小于 30 时,两者没有明显差别;当数据量大于容量 1/10 时,LinkedList 的效率没有 ArrayList 高。
  • 遍历性能:在元素个数大致相等的情况下,两者遍历的性能差不多。
6. 如何实现数组和 List 之间的转换?

答案

  • List 转 Array

    调用 List 成员方法 toArray。

    使用 for 循环生成 Array。

  • Array 转 List

    调用 Arrays 类方法 asList。

    使用 for 循环生成 List(如 ArrayList)。

7. ArrayList 和 Vector 的区别是什么?

答案

  • 历史背景:Vector 是 JDK 1.0 的集合类,内部通过数组实现,支持 Enumeration 遍历;ArrayList 是 JDK 1.2 的集合类,内部同样通过数组实现,但支持 Iterator 遍历。
  • 线程安全性:Vector 是线程同步的,而 ArrayList 是线程不同步的。因此,在多线程环境下,Vector 能够保证数据的一致性,但性能相对较低;ArrayList 则没有这种保证,但性能较高。
  • 扩容机制:内存不足时,Vector 默认扩展 1 倍,而 ArrayList 默认扩展 1.5 倍。
8. Array 和 ArrayList 有何区别?

答案

  • 数据类型:Array 可以含有基本数据类型和引用类型,而 ArrayList 只能包括引用类型(通过对象封装基本数据类型)。
  • 大小变化:Array 的大小是固定的,一旦创建就不能改变;而 ArrayList 的大小可以动态增加。
  • 功能丰富性:ArrayList 对数据的处理方法比 Array 多,提供了更多便捷的操作方法,可以看作是 Array 的加强版。
  • 元素类型一致性:Array 的元素数据类型必须一致;而 ArrayList 在未指定泛型的前提下,可以存储不同类型的对象(但通常不推荐这样做)。在实际开发中,Array 不常用,主要用于确定元素个数的场景中;而 ArrayList 则更为常用。