Java集合面试

Java集合常见面试

Java集合概览

主要实现两个接口

  • Collection
  • Map

说说 List, Set, Queue, Map 四者的区别?

  • List 顺序,可重复
  • Set 独一无二
  • Queue 实现排队
  • Map 用键值对(key-value)存储,可用key搜索

ArrayList 和 Vector 的区别?

  • 是List的主要实现类,线程不安全
  • 是List的古老实现类,一般不用,但线程安全

ArrayList 与 LinkedList 区别?

  • 线程不保证安全
  • 底层数据结构实现不一样:一个用数组,另一个用双向链表
  • arrayList插入移动元素比较多,LinkedList插入方便(但也不是特别方便)
  • arrayList支持快速随机访问而另一个不支持
  • 内存空间占用:LinkedList会更大,因为要存储指针

我们在项目中一般是不会使用到 LinkedList 的,需要用到 LinkedList 的场景几乎都可以使用 ArrayList 来代替,并且,性能通常会更好!就连 LinkedList 的作者约书亚 · 布洛克(Josh Bloch)自己都说从来不会使用 LinkedList

说一说 ArrayList 的扩容机制吧

  • 在插入元素前会调用ensureCapacityInternal()确保容量
  • 容量不足的时候会调用grow方法,新容量为旧容量的1.5倍
  • 把旧的数据复制到新的

comparable 和 Comparator 的区别

  • comparable 接口实际上是出自java.lang包 它有一个 compareTo(Object obj)方法用来排序
  • comparator接口实际上是出自 java.util 包它有一个compare(Object obj1, Object obj2)方法用来排序

无序性和不可重复性的含义是什么

  • 无序就是底层存储没有顺序,而是根据数据的哈希值决定顺序
  • 不可重复性指的是添加元素时会进行equals判断

比较 HashSet、LinkedHashSet 和 TreeSet 三者的异同

  • 都是Set的实现类,不是线程安全的
  • HashSet基于hash表,LinkedHashSet 的底层数据结构是链表和哈希表,TreeSet 底层数据结构是红黑树,
  • 应用场景不同,看对顺序的要求,HashSet 用于不需要保证元素插入和取出顺序的场景,LinkedHashSet 用于保证元素的插入和取出顺序满足 FIFO 的场景,TreeSet 用于支持对元素自定义排序规则的场景

Queue 与 Deque 的区别

  • Queue 是单端队列,只能从一端插入元素,另一端删除元素,实现上一般遵循 先进先出(FIFO) 规则。
  • Deque 是双端队列,在队列的两端均可以插入或删除元素。

HashMap 和 Hashtable 的区别

  • HashMap线程不安全,Hashtable线程安全(用了synchronized修饰内部方法)
  • 因为线程安全的问题,HashMap效率更高
  • HashMap 可以存储 null 的 key 和 value
  • HashMap中,当链表长度大于阈值(默认为 8)时,将链表转化为红黑树(将链表转换成红黑树前会判断,如果当前数组的长度小于 64,那么会选择先进行数组扩容,而不是转换为红黑树),HashTable不存在这样的机制

HashMap 和 HashSet 区别

HashMapHashSet
实现了 Map 接口实现 Set 接口
存储键值对仅存储对象
调用 put()向 map 中添加元素调用 add()方法向 Set 中添加元素
HashMap 使用键(Key)计算 hashcodeHashSet 使用成员对象来计算 hashcode 值,对于两个对象来说 hashcode 可能相同,所以equals()方法用来判断对象的相等性

HashSet 如何检查重复?

HashSetadd()方法只是简单的调用了HashMapput()方法,并且判断了一下返回值以确保是否有重复元素。

HashMap 的底层实现

解决hash冲突的方式变了

JDK1.8之前

JDK1.8之后

ConcurrentHashMap 和 Hashtable 的区别

ConcurrentHashMapHashtable 的区别主要体现在实现线程安全的方式上不同。

  • 数据结构不同:一个是数组加树或者链表,一个还是数据加链表
  • 线程安全实现不同:
    • ConcurrentHashMap是分段锁的
    • Hashtable 就一把锁

ConcurrentHashMapHashtable 的区别主要体现在实现线程安全的方式上不同。

  • 底层数据结构: JDK1.7 的 ConcurrentHashMap 底层采用 分段的数组+链表 实现,JDK1.8 采用的数据结构跟 HashMap1.8 的结构一样,数组+链表/红黑二叉树。Hashtable 和 JDK1.8 之前的 HashMap 的底层数据结构类似都是采用 数组+链表 的形式,数组是 HashMap 的主体,链表则是主要为了解决哈希冲突而存在的;
  • 实现线程安全的方式(重要):
    • 在 JDK1.7 的时候,ConcurrentHashMap 对整个桶数组进行了分割分段(Segment,分段锁),每一把锁只锁容器其中一部分数据(下面有示意图),多线程访问容器里不同数据段的数据,就不会存在锁竞争,提高并发访问率。
    • 到了 JDK1.8 的时候,ConcurrentHashMap 已经摒弃了 Segment 的概念,而是直接用 Node 数组+链表+红黑树的数据结构来实现,并发控制使用 synchronized 和 CAS 来操作。(JDK1.6 以后 synchronized 锁做了很多优化) 整个看起来就像是优化过且线程安全的 HashMap,虽然在 JDK1.8 中还能看到 Segment 的数据结构,但是已经简化了属性,只是为了兼容旧版本;
    • Hashtable(同一把锁) :使用 synchronized 来保证线程安全,效率非常低下。当一个线程访问同步方法时,其他线程也访问同步方法,可能会进入阻塞或轮询状态,如使用 put 添加元素,另一个线程不能使用 put 添加元素,也不能使用 get,竞争会越来越激烈效率越低。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值