有哪些Java集合面试题

发布时间:2021-10-23 15:55:21 作者:iii
来源:亿速云 阅读:121

本篇内容主要讲解“有哪些Java集合面试题”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“有哪些Java集合面试题”吧!

常用的集合类有哪些? ***

Map接口和Collection接口是所有集合框架的父接口。下图中的实线和虚线看着有些乱,其中接口与接口之间如果有联系为继承关系,类与类之间如果有联系为继承关系,类与接口之间则是类实现接口。重点掌握的抽象类有HashMapLinkedListHashTableArrayListHashSetStackTreeSetTreeMap。注意:Collection接口不是Map的父接口。

有哪些Java集合面试题

有哪些Java集合面试题

List,Set,Map三者的区别? ***

常用集合框架底层数据结构 ***

哪些集合类是线程安全的? ***

迭代器 Iterator 是什么 *

Iterator 是 Java 迭代器最简单的实现,它不是一个集合,它是一种用于访问集合的方法,Iterator接口提供遍历任何Collection的接口。

Java集合的快速失败机制 “fail-fast”和安全失败机制“fail-safe”是什么? ***

如何边遍历边移除 Collection 中的元素? ***

从上文**“快速失败机制”**可知在遍历集合时如果直接调用remove()方法会抛出ConcurrentModificationException异常,所以使用迭代器中调用remove()方法。

Array 和 ArrayList 有何区别? ***

comparable 和 comparator的区别? ** 

它们之间的区别:很多包装类都实现了comparable接口,像IntegerString等,所以直接调用Collections.sort()直接可以使用。如果对类里面自带的自然排序不满意,而又不能修改其源代码的情况下,使用Comparator就比较合适。此外使用Comparator可以避免添加额外的代码与我们的目标类耦合,同时可以定义多种排序规则,这一点是Comparable接口没法做到的,从灵活性和扩展性讲Comparator更优,故在面对自定义排序的需求时,可以优先考虑使用Comparator接口。

Collection 和 Collections 有什么区别? **

List集合

遍历一个 List 有哪些不同的方式? **

先说一下常见的元素在内存中的存储方式,主要有两种:

  1. 顺序存储(Random Access):相邻的数据元素在内存中的位置也是相邻的,可以根据元素的位置(如ArrayList中的下表)读取元素。

  2. 链式存储(Sequential Access):每个数据元素包含它下一个元素的内存地址,在内存中不要求相邻。例如LinkedList

主要的遍历方式主要有三种:

  1. for循环遍历:遍历者自己在集合外部维护一个计数器,依次读取每一个位置的元素。

  2. Iterator遍历:基于顺序存储集合的Iterator可以直接按位置访问数据。基于链式存储集合的Iterator,需要保存当前遍历的位置,然后根据当前位置来向前或者向后移动指针。

  3. foreach遍历:foreach 内部也是采用了Iterator 的方式实现,但使用时不需要显示地声明Iterator

那么对于以上三种遍历方式应该如何选取呢?

在Java集合框架中,提供了一个RandomAccess接口,该接口没有方法,只是一个标记。通常用来标记List的实现是否支持RandomAccess。所以在遍历时,可以先判断是否支持RandomAccesslist instanceof RandomAccess),如果支持可用 for 循环遍历,否则建议用Iteratorforeach 遍历。

ArrayList的扩容机制 ***

先说下结论,一般面试时需要记住,ArrayList的初始容量为10,扩容时对是旧的容量值加上旧的容量数值进行右移一位(位运算,相当于除以2,位运算的效率更高),所以每次扩容都是旧的容量的1.5倍。

具体的实现大家可查看下ArrayList的源码。

ArrayList 和 LinkedList 的区别是什么? ***
ArrayList 和 Vector 的区别是什么? ***
简述 ArrayList、Vector、LinkedList 的存储性能和特性? ***

Set集合

说一下 HashSet 的实现原理 ***

HashSet的底层是HashMap,默认构造函数是构建一个初始容量为16,负载因子为0.75 的HashMapHashSet的值存放于HashMapkey上,HashMapvalue统一为PRESENT

HashSet如何检查重复?(HashSet是如何保证数据不可重复的?) ***

这里面涉及到了HasCode()equals()两个方法。

介绍完equals()方法和hashCode()方法,继续说下HashSet是如何检查重复的。

HashSet的特点是存储元素时无序且唯一,在向HashSet中添加对象时,首相会计算对象的HashCode值来确定对象的存储位置,如果该位置没有其他对象,直接将该对象添加到该位置;如果该存储位置有存储其他对象(新添加的对象和该存储位置的对象的HashCode值相同),调用equals方法判断两个对象是否相同,如果相同,则添加对象失败,如果不相同,则会将该对象重新散列到其他位置。

HashSet与HashMap的区别 ***
HashMapHashSet
实现了Map接口实现了Set接口
存储键值对存储对象
key唯一,value不唯一存储对象唯一
HashMap使用键(Key)计算HashcodeHashSet使用成员对象来计算hashcode
速度相对较快速度相对较慢

Map集合

HashMap在JDK1.7和JDK1.8中有哪些不同?HashMap的底层实现 ***

有哪些Java集合面试题

有哪些Java集合面试题

HashMap在JDK1.7和JDK1.8中有哪些不同点:


JDK1.7JDK1.8JDK1.8的优势
底层结构数组+链表数组+链表/红黑树(链表大于8)避免单条链表过长而影响查询效率,提高查询效率
hash值计算方式9次扰动 = 4次位运算 + 5次异或运算2次扰动 = 1次位运算 + 1次异或运算可以均匀地把之前的冲突的节点分散到新的桶(具体细节见下面扩容部分)
插入数据方式头插法(先讲原位置的数据移到后1位,再插入数据到该位置)尾插法(直接插入到链表尾部/红黑树)解决多线程造成死循环地问题
扩容后存储位置的计算方式重新进行hash计算原位置或原位置+旧容量省去了重新计算hash值的时间
HashMap 的长度为什么是2的幂次方 ***

因为HashMap是通过key的hash值来确定存储的位置,但Hash值的范围是-2147483648到2147483647,不可能建立一个这么大的数组来覆盖所有hash值。所以在计算完hash值后会对数组的长度进行取余操作,如果数组的长度是2的幂次方,(length - 1)&hash等同于hash%length,可以用(length - 1)&hash这种位运算来代替%取余的操作进而提高性能。

HashMap的put方法的具体流程? **

HashMap的主要流程可以看下面这个流程图,逻辑非常清晰。

有哪些Java集合面试题

HashMap的扩容操作是怎么实现的? ***
HashMap默认加载因子为什么选择0.75?

这个主要是考虑空间利用率和查询成本的一个折中。如果加载因子过高,空间利用率提高,但是会使得哈希冲突的概率增加;如果加载因子过低,会频繁扩容,哈希冲突概率降低,但是会使得空间利用率变低。具体为什么是0.75,不是0.74或0.76,这是一个基于数学分析(泊松分布)和行业规定一起得到的一个结论。

为什么要将链表中转红黑树的阈值设为8?为什么不一开始直接使用红黑树?

可能有很多人会问,既然红黑树性能这么好,为什么不一开始直接使用红黑树,而是先用链表,链表长度大于8时,才转换为红红黑树。

HashMap是怎么解决哈希冲突的? ***

哈希冲突:hashMap在存储元素时会先计算key的hash值来确定存储位置,因为key的hash值计算最后有个对数组长度取余的操作,所以即使不同的key也可能计算出相同的hash值,这样就引起了hash冲突。hashMap的底层结构中的链表/红黑树就是用来解决这个问题的。

HashMap中的哈希冲突解决方式可以主要从三方面考虑(以JDK1.8为背景)

HashMap为什么不直接使用hashCode()处理后的哈希值直接作为table的下标? ***

hashCode()处理后的哈希值范围太大,不可能在内存建立这么大的数组。

能否使用任何类作为 Map 的 key? ***

可以,但要注意以下两点:

为什么HashMap中String、Integer这样的包装类适合作为Key? ***
如果使用Object作为HashMap的Key,应该怎么办呢? **
HashMap 多线程导致死循环问题 ***

由于JDK1.7的hashMap遇到hash冲突采用的是头插法,在多线程情况下会存在死循环问题,但JDK1.8已经改成了尾插法,不存在这个问题了。但需要注意的是JDK1.8中的HashMap仍然是不安全的,在多线程情况下使用仍然会出现线程安全问题。基本上面试时说到这里既可以了,具体流程用口述是很难说清的,感兴趣的可以看这篇文章。HASHMAP的死循环

ConcurrentHashMap 底层具体实现知道吗? **

有哪些Java集合面试题

有哪些Java集合面试题

总结一下:

HashTable的底层实现知道吗?

HashTable的底层数据结构是数组+链表,链表主要是为了解决哈希冲突,并且整个数组都是synchronized修饰的,所以HashTable是线程安全的,但锁的粒度太大,锁的竞争非常激烈,效率很低。

有哪些Java集合面试题

HashMap、ConcurrentHashMap及Hashtable 的区别 ***

HashMap(JDK1.8)ConcurrentHashMap(JDK1.8)Hashtable
底层实现数组+链表/红黑树数组+链表/红黑树数组+链表
线程安全不安全安全(Synchronized修饰Node节点)安全(Synchronized修饰整个表)
效率较高
扩容初始16,每次扩容成2n初始16,每次扩容成2n初始11,每次扩容成2n+1
是否支持Null key和Null Value可以有一个Null key,Null Value多个不支持不支持

Java集合的常用方法 **

这些常用方法是需要背下来的,虽然面试用不上,但是笔试或者面试写算法题时会经常用到。

Collection常用方法
方法
booean add(E e)在集合末尾添加元素
boolean remove(Object o) 若本类集中有值与o的值相等的元素,移除该元素并返回true
void clear()清除本类中所有元素
boolean contains(Object o)判断集合中是否包含该元素
boolean isEmpty()判断集合是否为空
int size()返回集合中元素的个数
boolean addAll(Collection c)将一个集合中c中的所有元素添加到另一个集合中
Object[] toArray()返回一个包含本集所有元素的数组,数组类型为Object[]
`boolean equals(Object c)``判断元素是否相等
int hashCode()返回元素的hash值
List特有方法
方法
void add(int index,Object obj)在指定位置添加元素
Object remove(int index)删除指定元素并返回
Object set(int index,Object obj)把指定索引位置的元素更改为指定值并返回修改前的值
int indexOf(Object o)返回指定元素在集合中第一次出现的索引
Object get(int index)返回指定位置的元素
List subList(int fromIndex,int toIndex)截取集合(左闭右开)
LinkedList特有方法
方法
addFirst()在头部添加元素
addLast()在尾部添加元素
removeFirst()在头部删除元素
removeLat()在尾部删除元素
getFirst()获取头部元素
getLast()获取尾部元素
Map
方法
void clear()清除集合内的元素
boolean containsKey(Object key)查询Map中是否包含指定key,如果包含则返回true
Set entrySet()返回Map中所包含的键值对所组成的Set集合,每个集合元素都是Map.Entry的对象
Object get(Object key)返回key指定的value,若Map中不包含key返回null
boolean isEmpty()查询Map是否为空,若为空返回true
Set keySet()返回Map中所有key所组成的集合
Object put(Object key,Object value)添加一个键值对,如果已有一个相同的key,则新的键值对会覆盖旧的键值对,返回值为覆盖前的value值,否则为null
void putAll(Map m)将制定Map中的键值对复制到Map中
Object remove(Object key)删除指定key所对应的键值对,返回所关联的value,如果key不存在返回null
int size()返回Map里面的键值对的个数
Collection values()返回Map里所有values所组成的Collection
boolean containsValue ( Object value)判断映像中是否存在值 value
Stack
方法
boolean empty() 测试堆栈是否为空。
E peek() 查看堆栈顶部的对象,但不从堆栈中移除它。
E pop() 移除堆栈顶部的对象,并作为此函数的值返回该对象。
E push(E item) 把项压入堆栈顶部。
int search(Object o) 返回对象在堆栈中的位置,以 1 为基数。
Queue
方法
boolean add(E e)将指定元素插入到队列的尾部(队列满了话,会抛出异常)
boolean offer(E e)将指定元素插入此队列的尾部(队列满了话,会返回false)
E remove()返回取队列头部的元素,并删除该元素(如果队列为空,则抛出异常)
E poll()返回队列头部的元素,并删除该元素(如果队列为空,则返回null)
E element()返回队列头部的元素,不删除该元素(如果队列为空,则抛出异常)
E peek()返回队列头部的元素,不删除该元素(如果队列为空,则返回null)

到此,相信大家对“有哪些Java集合面试题”有了更深的了解,不妨来实际操作一番吧!这里是亿速云网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

推荐阅读:
  1. Java集合ArrayList教程学习路线有哪些?
  2. JAVA集合篇的面试题有哪些

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

java

上一篇:阅读源码必备的C++技能有哪些

下一篇:如何使用HSDB探秘运行时数据区

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》