Java集合相关面试题

目录

目录

一,Java集合框架体系

 二,List相关面试题

1,数组的定义

 面试题:为什么数组索引从0开始呢?假如从1开始不行吗?​编辑

操作数组的时间复杂度

 总结

 2,ArrayList源码分析

 1,成员变量

 2,构造方法

3,添加操作 

 面试题1:ArrayList底层的实现原理是什么?

面试题2:ArrayLisst list = new ArrayList(10)中list扩容几次了?

 面试题3:如何实现数组和List之间的转换?(注意是否存在影响)

 3,LinkedList

1,单向链表

 2,双向链表

面试题:ArrayList和LinkedList有什么不同?

 三,HashMap相关面试题

 1,相关数据结构

1,二叉搜索树

 2,红黑树

 3,散列表(哈希表Hash Table)

 2,Hash相关面试题

面试题:请你说说HashMap的实现原理?

 面试题:HashMap的jdk1.7和jdk1.8有什么区别?

面试题:HashMap的put方法的具体执行流程?

 面试题:HashMap的扩容机制原理

 面试题:HashMap的寻址算法​编辑

面试题:为何HashMap的数组长度一定是2的次幂? 

 面试题:HashMap在1.7情况下的多线程死循环问题是什么?

四,ConcurrentHashMap相关面试题

1,ConcurrentHashMap 线程安全的具体实现方式/底层具体实现

1,JDK1.8之前

2,JDK1.8之后

2,JDK 1.7 和 JDK 1.8 的 ConcurrentHashMap 实现有什么不同?

五,HashTable相关面试题

1,HashTable有什么特点?

2,HashMap和HashTable有什么区别?

3,HashTable和ConcurrentHashMap有什么区别


一,Java集合框架体系

 二,List相关面试题

1,数组的定义

 面试题:为什么数组索引从0开始呢?假如从1开始不行吗?

操作数组的时间复杂度

1,查找

随机查询(根据索引查询): O(1)

未知索引查询:

        顺序查询:O(n)

        二分查找(有序数组):O(log n)

2,删改

因为数据是一段连续的内存空间,因此为了保准数组的连续性会使得数据的插入和删除效率变得很低(需要移动元素)

 

 总结

 2,ArrayList源码分析

 1,成员变量

 2,构造方法

3,添加操作 

1,第1添加,初始化(第一次添加数据-扩容情况)

 2,第2-10次添加数据(无扩容)

 3,第11次添加(扩容操作)

//Array.copyof()是一种数组复制拷贝方法,不同的数据类型
//使用了不同的实现,但是算法思路一样,且都用到了System.arraycopy
//下面以Int类型为例
public static int[] copyOf(int[] original, int newLength) {
    int[] copy = new int[newLength];
    System.arraycopy(original, 0, copy, 0,
            Math.min(original.length, newLength));
    return copy;
}

 面试题1:ArrayList底层的实现原理是什么?

面试题2:ArrayLisst list = new ArrayList(10)中list扩容几次了?

 面试题3:如何实现数组和List之间的转换?(注意是否存在影响)

 3,LinkedList

1,单向链表

 

 2,双向链表

 

 

面试题:ArrayList和LinkedList有什么不同?

一共四个点回答:

  1. 底层数据结构
  2. 操作效率
  3. 内存空间利用率
  4. 线程安全

 三,HashMap相关面试题

 1,相关数据结构

1,二叉搜索树

 

 

 2,红黑树

 3,散列表(哈希表Hash Table)

 

1,数据+链表 实现散列表存在的问题 

 2,数据+链表+红黑树 解决退化问题

 

 总结:

 2,Hash相关面试题

面试题:请你说说HashMap的实现原理?

 面试题:HashMap的jdk1.7和jdk1.8有什么区别?

  1. 底层数据结构:1.7中是数组+链表,1.8中是数组+链表+红黑树
  2. 链表插入方式:1.7是头插法,而1.8是尾插法
  3. 哈希算法复杂度:1.7更为复杂且耗性能(因为1.8采用了红黑树,散列性要求较低) 

 

面试题:HashMap的put方法的具体执行流程?

 

 

  

 面试题:HashMap的扩容机制原理

流程图:

 总结:

链表拆分演示:

 面试题:HashMap的寻址算法

面试题:为何HashMap的数组长度一定是2的次幂? 

 面试题:HashMap在1.7情况下的多线程死循环问题是什么?

 

四,ConcurrentHashMap相关面试题

1,ConcurrentHashMap 线程安全的具体实现方式/底层具体实现

1,JDK1.8之前

首先将数据分为一段一段(这个“段”就是 Segment)的存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数据时,其他段的数据也能被其他线程访问。

ConcurrentHashMap 是由 Segment 数组结构和 HashEntry 数组结构组成

Segment 继承了 ReentrantLock,所以 Segment 是一种可重入锁,扮演锁的角色。HashEntry 用于存储键值对数据。

一个 ConcurrentHashMap 里包含一个 Segment 数组,Segment 的个数一旦初始化就不能改变Segment 数组的大小默认是 16,也就是说默认可以同时支持 16 个线程并发写

Segment 的结构和 HashMap 类似,是一种数组和链表结构,一个 Segment 包含一个 HashEntry 数组,每个 HashEntry 是一个链表结构的元素,每个 Segment 守护着一个 HashEntry 数组里的元素,当对 HashEntry 数组的数据进行修改时,必须首先获得对应的 Segment 的锁。也就是说,对同一 Segment 的并发写入会被阻塞,不同 Segment 的写入是可以并发执行的。

2,JDK1.8之后

Java 8 几乎完全重写了 ConcurrentHashMap,代码量从原来 Java 7 中的 1000 多行,变成了现在的 6000 多行。

ConcurrentHashMap 取消了 Segment 分段锁,采用 Node + CAS + synchronized 来保证并发安全。数据结构跟 HashMap 1.8 的结构类似,数组+链表/红黑二叉树。Java 8 在链表长度超过一定阈值(8)时将链表(寻址时间复杂度为 O(N))转换为红黑树(寻址时间复杂度为 O(log(N)))。

Java 8 中,锁粒度更细synchronized锁定当前链表或红黑二叉树的首节点,这样只要 hash 不冲突,就不会产生并发,就不会影响其他 Node 的读写,效率大幅提升。

2,JDK 1.7 和 JDK 1.8 的 ConcurrentHashMap 实现有什么不同?

  • 线程安全实现方式:JDK 1.7 采用 Segment 分段锁来保证安全, Segment 是继承自 ReentrantLock。JDK1.8 放弃了 Segment 分段锁的设计,采用 Node + CAS + synchronized 保证线程安全,锁粒度更细,synchronized 只锁定当前链表或红黑二叉树的首节点。
  • Hash 碰撞解决方法 : JDK 1.7 采用拉链法,JDK1.8 采用拉链法结合红黑树(链表长度超过一定阈值时,将链表转换为红黑树【 O(N) -> O(log(N) 】)。
  • 并发度:JDK 1.7 最大并发度是 Segment 的个数,默认是 16。JDK 1.8 最大并发度是 Node 数组的大小,并发度更大。 

五,HashTable相关面试题

1,HashTable有什么特点?

在Java中,HashTable是一个线程安全的哈希表实现,它是Dictionary类的子类。HashTable使用键值对的方式存储数据,其中键和值都不能为null。它使用哈希算法来计算键的哈希值,并将键值对存储在哈希表的桶中。

HashTable的主要用途是在多线程环境下存储和访问数据,因为它的方法都是同步的,可以保证线程安全性。它可以用于存储缓存、共享数据、配置信息等。

推荐在以下场景下使用HashTable:

1. 多线程环境:当需要在多个线程中安全地存储和访问数据时,可以使用HashTable来保证线程安全性。

2. 简单的键值存储:如果只需要简单地存储键值对,而不需要复杂的功能,HashTable可以是一个简单且可靠的选择。

HashTable的优点:

  1.         1. 线程安全:HashTable的方法都是同步的,可以在多线程环境下使用。
    1.         2. 简单易用:HashTable提供了简单的键值存储功能,使用起来比较方便。

HashTable的缺点:

1. 性能较差:由于所有方法都是同步的,HashTable的性能相对较差,特别是在高并发环境下。

2. 不支持null值:HashTable不允许键或值为null,如果出现null值,会抛出NullPointerException。

常用操作方法:

  1.         1. put(key, value):将键值对存储到HashTable中。
    1.         2. get(key):根据键获取对应的值。
      1.         3. remove(key):根据键移除对应的键值对。
        1.         4. containsKey(key):判断HashTable中是否包含指定的键。
          1.         5. containsValue(value):判断HashTable中是否包含指定的值。
            1.         6. size():返回HashTable中键值对的数量。
              1.         7. clear():清空HashTable中的所有键值对。

需要注意的是,由于HashTable是线程安全的,使用时需要考虑同步的开销和性能问题。如果不需要线程安全性,推荐使用HashMap或ConcurrentHashMap来获得更好的性能。

2,HashMap和HashTable有什么区别?

1. 线程安全性:HashTable是线程安全的,而HashMap不是。HashTable的方法都是同步的,可以在多线程环境下使用,但由于同步操作的开销,性能较差。HashMap在多线程环境下需要通过其他手段来保证线程安全性,如使用ConcurrentHashMap。

2. Null:HashMap允许键和值都为null,而HashTable不允许。在HashMap中,可以使用null作为键或值,但在HashTable中,如果键或值为null,会抛出NullPointerException。

3. 继承关系:HashMap是HashTable的轻量级替代品,它实现了Map接口,而HashTable是Dictionary类的子类。

4. 初始容量和扩容机制:HashMap的初始容量为16,而HashTable的初始容量为11。HashMap在扩容时,容量会翻倍,而HashTable的容量会增加约一倍加一。

5. 迭代器:HashMap的迭代器是fail-fast的,即在迭代过程中,如果其他线程对HashMap进行修改,会抛出ConcurrentModificationException异常。而HashTable的迭代器不是fail-fast的。

总的来说,HashMap更常用,因为它的性能更好,但在多线程环境下需要注意线程安全性。而HashTable由于线程安全的特性,适合在多线程环境下使用,但性能较差。

3,HashTable和ConcurrentHashMap有什么区别?

ConcurrentHashMap和HashTable都是Java中用于存储键值对的数据结构,但它们在实现和用法上有一些异同。

相同点:

  1. 都是线程安全的:ConcurrentHashMap和HashTable都是线程安全的,可以在多线程环境下使用而无需额外的同步措施。
  2. 都实现了Map接口:ConcurrentHashMap和HashTable都实现了Map接口,提供了类似于HashMap的键值对存储和检索功能。

不同点:
        1. 同步机制:ConcurrentHashMap使用了锁分段技术(lock striping),将整个数据结构分成多个段(Segment)【jdk1.8之前使用Segment 数组 + HashEntry 数组 + 链表,而jdk1.8后,采用了Node数组+链表+红黑树实现,其实现锁的方式也改成了采用Node + CAS + synchronized】,每个段都有自己的锁。这样可以提高并发性能,多个线程可以同时访问不同的段,从而减少了线程之间的竞争。而HashTable则使用了全局同步锁(synchronize),即每次只能有一个线程访问整个数据结构,这可能会导致性能瓶颈。
        2. 迭代器:ConcurrentHashMap的迭代器是弱一致性的(weakly consistent),即在迭代过程中,如果有其他线程修改了数据结构,迭代器可能会抛出ConcurrentModificationException异常。而HashTable的迭代器是强一致性的(fail-fast),即在迭代过程中,如果有其他线程修改了数据结构,迭代器会立即抛出ConcurrentModificationException异常。
        3. null值和null键:ConcurrentHashMap允许null值和null键,而HashTable不允许null值和null键。

综上所述,ConcurrentHashMap在并发性能上优于HashTable,特别是在多线程环境下。因此,如果需要在多线程环境中使用键值对存储结构,推荐使用ConcurrentHashMap

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值