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 区别

HashMap HashSet
实现了 Map 接口 实现 Set 接口
存储键值对 仅存储对象
调用 put()向 map 中添加元素 调用 add()方法向 Set 中添加元素
HashMap 使用键(Key)计算 hashcode HashSet 使用成员对象来计算 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,竞争会越来越激烈效率越低。

猜你喜欢

转载自blog.csdn.net/weixin_51209821/article/details/129124329
今日推荐