面试||java集合系列

在这里插入图片描述
在这里插入图片描述

List

http://cmsblogs.com/?p=4727
(1)ArrayList?
ArrayList以数组实现,具有动态扩展的能力,动态数组。
ArrayList实现了List,提供了基础的添加、删除、遍历等操作;实现了RandomAccess,提供了随机访问的能力;实现了Cloneable,可以被克隆;实现了Serializable,可以被序列化。
(2)ArrayList是怎么扩容的?
默认容量10,1.5倍扩容;计算出新的扩容数组的size后实例化,并将原有数组内容复制到新数组中去。
(3)LinkedList是单链表还是双链表实现的?
双向链表实现;实现了List,Queue和Deque接口,能作为List,双端队列,栈使用。
不支持随机访问
(4)CopyOnWriteArrayList是怎么保证并发安全的?
用ReentrantLock重入锁加锁,保证线程安全;是ArrayList的线程安全版本,通过数组实现,对数组的修改都完全拷贝一份新的数组来修改,修改完了再替换掉老数组,这样保证了只阻塞写操作,不阻塞读操作,实现读写分离。
(5)CopyOnWriteArrayList的实现采用了什么思想?
读写分离的思想,适用于读多写少的场合。实现了List, RandomAccess, Cloneable, Serializable等接口。
(6)CopyOnWriteArrayList是不是强一致性的?
只保证最终一致性,不保证实时一致性;
(7)CopyOnWriteArrayList为什么没有size属性?
每次修改都是拷贝一份正好可以存储目标个数元素的数组,所以不需要size属性了,数组的长度就是集合的大小,而不像ArrayList数组的长度实际是要大于集合的大小的。
(8)如何对Object的list排序?
对objects数组进行排序,我们可以用Arrays.sort()方法
对objects的集合进行排序,需要使用Collections.sort()方法
(9)如何求ArrayList集合的交集 并集 差集 去重复并集

// 并集
list1.addAll(list2);
 // 交集
list1.retainAll(list2);
 // 差集
list1.removeAll(list2);
 // 无重复并集
list2.removeAll(list1);
list1.addAll(list2);

(10)什么是迭代器(Iterator)?
Iterator 接口,提供了很多对集合元素进行迭代的方法。每一个集合类都包含了可以返回迭代器实例的迭代方法。迭代器可以在迭代的过程中删除底层集合的元素,但是不可以直接调用集合的 #remove(Object Obj) 方法删除,可以通过迭代器的 #remove() 方法删除。
(11)Iterator 和 ListIterator 的区别是什么?
Iterator 可用来遍历 Set 和 List 集合,但是 ListIterator 只能用来遍历 List。
Iterator 对集合只能是前向遍历,ListIterator 既可以前向也可以后向。
ListIterator 实现了 Iterator 接口,并包含其他的功能。比如:增加元素,替换元素,获取前一个和后一个元素的索引等等。
(12)快速失败(fail-fast)和安全失败(fail-safe)的区别是什么?
差别在于 ConcurrentModification 异常:
**快速失败:**当你在迭代一个集合的时候,如果有另一个线程正在修改你正在访问的那个集合时,就会抛出一个 ConcurrentModification 异常。 在 java.util 包下的都是快速失败。
**安全失败:**你在迭代的时候会去底层集合做一个拷贝,所以你在修改上层集合的时候是不会受影响的,不会抛出 ConcurrentModification 异常。在 java.util.concurrent 包下的全是安全失败的。
(13)如何删除 List 中的某个元素?
有两种方式,分别如下:
方式一,使用 Iterator ,顺序向下,如果找到元素,则使用 remove()方法进行移除。
方式二,倒序遍历 List ,如果找到元素,则使用 remove() 方法进行移除。
(14)Enumeration 和 Iterator 接口有什么不同?
Enumeration 跟 Iterator 相比较快两倍,而且占用更少的内存。
但是,Iterator 相对于 Enumeration 更安全,因为其他线程不能修改当前迭代器遍历的集合对象。同时,Iterators 允许调用者从底层集合中移除元素,这些 Enumerations 都没法完成。
《Java Enumeration 接口》
(15)为何 Iterator 接口没有具体的实现?
Iterator 接口,定义了遍历集合的方法,但它的实现则是集合实现类的责任。每个能够返回用于遍历的 Iterator 的集合类都有它自己的 Iterator 实现内部类。
这就允许集合类去选择迭代器是 fail-fast 还是 fail-safe 的。比如,ArrayList 迭代器是 fail-fast 的,而 CopyOnWriteArrayList 迭代器是 fail-safe 的。
(16)Comparable 和 Comparator 的区别?
Comparable 接口,在 java.lang 包下,用于当前对象和其它对象的比较,所以它有一个 compareTo(Object obj) 方法用来排序,该方法只有一个参数。
Comparator 接口,在 java.util 包下,用于传入的两个对象的比较,所以它有一个 compare(Object obj1, Object obj2) 方法用来排序,该方法有两个参数。
详细的,可以看看 《Java 自定义比较器》

Map相关问题***

Map的实现主要有HashMap、LinkedHashMap、WeakHashMap、TreeMap、ConcurrentHashMap、ConcurrentSkipListMap
(1)什么是散列表?
hash表 ,根据关键码值而进行直接进行访问的数据结构。通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射也叫散列函数,存放记录的数组叫散列表。
(2)怎么实现一个散列表?
用hash函数将查找的键转换成数组索引
(3)java中HashMap
实现了Cloneable,可以被克隆,HashMap实现了Serializable,可以被序列化。
Java中,HashMap的实现采用了(数组 + 链表 + 红黑树)的复杂结构,数组的一个元素又称作桶。
初始容量16,最大为2的30次方,2倍扩容;当容量达到64时才可以树化,默认装载因子0.75,桶中元素>=8转化红黑树,<=6树转链表;
(4)HashMap在多线程环境中什么时候会出现问题?
并发环境下的rehash过程可能会带来循环链表,导致死循环致使线程挂掉。
(5)红黑树知多少?
红黑树具有以下5种性质:
(1)节点是红色或黑色。(2)根节点是黑色。(3)每个叶节点(NIL节点,空节点)是黑色的。
(4)每个红色节点的两个子节点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色节点)
(5)从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点。
红黑树的时间复杂度为O(log n),与树的高度成正比。
红黑树每次的插入、删除操作都需要做平衡,平衡时有可能会改变根节点的位置,颜色转换,左旋,右旋等。
(6)LinkedHashMap
LinkedHashMap 源码详细分析
双向链表,能保证元素按插入的顺序访问,也能以访问顺序访问,可以用来实现LRU缓存策略(Least Recently Used,最近最少使用,也就是优先淘汰最近最少使用的元素。)。
可以看成是 LinkedList + HashMap。

(7)TreeMap
红黑树存储元素,实现了Map、SortedMap、NavigableMap、Cloneable、Serializable等接口。

** (8)ConcurrentHashMap **
ConcurrentHashMap对整个桶数组进行了分割分段(Segment),然后在每一个分段上都用lock锁进行保护,相对于HashTable的syn关键字锁的粒度更精细了一些,并发性能更好
使用(数组 + 链表 + 红黑树)的结构。
(9)ConcurrentHashMap是怎么保证并发安全的?
分段锁,细化了锁的粒度
添加元素操作中使用的锁主要有(自旋锁 + CAS + synchronized + 分段锁)
(10)ConcurrentHashMap是怎么扩容的?
新桶数组大小是旧桶数组的两倍,扩容过程都是通过CAS控制sizeCtl这个字段来进行的。
(11)ConcurrentHashMap的size()方法的实现知多少?
单线程:首先遍历segments将每个segment的count加起来作为整个concurrenthashMap的size。
并发环境下:引入了modCount和两次比较来实现size的确认。1.进行第一遍遍历segments数组,将每个segemnt的count加起来作为总数,期间把每个segment的modCount(修改次数,只增不减)加起来sum作为结果是否被修改的判断依据。2.size操作就是遍历了两次所有的Segments,每次记录Segment的modCount值,然后将两次的modCount进行比较,相同返回结果,不同锁住所有segements,全部遍历。
(12)ConcurrentHashMap是强一致性的吗?
ConcurrentHashMap弱一致性体现在clear、迭代器和get方法,原因在于没有加锁。
如迭代器在遍历数据的时候是一个Segment一个Segment去遍历的,如果在遍历完一个Segment时正好有一个线程在刚遍历完的Segment上插入数据,就会体现出不一致性。
(13)什么是伪共享?怎么避免伪共享?
(14)什么是跳表?

Set

(1)HashSet
内部使用HashMap的key存储元素,无序的;
(2)HashSet如何检查重复
当你把对象加入HashSet时,HashSet会先计算对象的hashcode值来判断对象加入的位置,同时也会与其他加入的对象的hashcode值作比较,如果没有相符的hashcode,HashSet会假设对象没有重复出现。但是如果发现有相同hashcode值的对象,这时会调用equals()方法来检查hashcode相等的对象是否真的相同。如果两者相同,HashSet就不会让加入操作成功。
(2)LinkedHashSet
用默认容量16, 默认装载因子0.75
LinkedHashSet继承自HashSet,它的添加、删除、查询等方法都是直接用的HashSet的,唯一的不同就是它使用LinkedHashMap存储元素,按照插入的顺序排序的。
(3)TreeSet
采用TreeMap实现的一种Set,所以它是有序的,同样也是非线程安全的
(4)CopyOnWriteArraySet
底层使用CopyOnWriteArrayList存储元素的,所以它并不是使用Map来存储元素的

Queue

BlockingQueue是什么

ArrayBlockingQueue
LinkedBlockingQueue

简述 ConcurrentLinkedQueue LinkedBlockingQueue 的用处和不同之处。

Deque

(1)hashCode()与equals()的相关规定:

  1. 如果两个对象相等,则hashcode一定也是相同的
  2. 两个对象相等,对两个equals方法返回true
  3. 两个对象有相同的hashcode值,它们也不一定是相等的
  4. 综上,equals方法被覆盖过,则hashCode方法也必须被覆盖
  5. hashCode()的默认行为是对堆上的对象产生独特值。如果没有重写hashCode(),则该class的两个对象无论如何都不会相等(即使这两个对象指向相同的数据)。

(2)==与equals的区别
1.==是判断两个变量或实例是不是指向同一个内存空间 ,equals是判断两个变量或实例所指向的内存空间的值是不是相同
2.==是指对内存地址进行比较 equals()是对字符串的内容进行比较
3.==指引用是否相同 equals()指的是是否相同

(3)List 和 Set 区别?
List,Set 都是继承自 Collection 接口
List 特点:元素有放入顺序,元素可重复。
Set 特点:元素无放入顺序,元素不可重复,重复元素会覆盖掉。

注意:元素虽然无放入顺序,但是元素在 Set 中的位置是有该元素的 hashcode 决定的,其位置其实是固定的。
另外 List 支持 for 循环,也就是通过下标来遍历,也可以用迭代器,但是 Set 只能用迭代,因为他无序,无法用下标来取得想要的值。

Hash算法

Hashcode 的作用

简述一致性 Hash 算法

Collections

介绍Java中的Collection FrameWork。集合类框架的基本接口有哪些

Collections类是什么?Collection 和 Collections的区别?Collection、Map的实现

集合类框架的最佳实践有哪些

在这里插入图片描述
为什么 Collection 不从 Cloneable 和 Serializable 接口继承

说出几点 Java 中使用 Collections 的最佳实践?

Collections 中 遗留类 (HashTable、Vector) 和 现有类的区别

Comparator 与 Comparable 接口是干什么的

Comparable: 内部比较器,一个类如果想要使用 Collections.sort(list) 方法进行排序,则需要实现该接口
Comparator: 外部比较器用于对那些没有实现Comparable接口或者对已经实现的Comparable中的排序规则不满意进行排序.无需改变类的结构,更加灵活。(策略模式)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值