送给程序员的20个Java集合面试问题


Posted in 面试题 onAugust 06, 2014

1.Java集合框架是什么?说出一些集合框架的优点?
答:每种编程语言中都有集合,最初的Java版本包含几种集合类:Vector、Stack、HashTable和Array。随着集合的广泛使用,Java1.2提出了囊括所有集合接口、实现和算法的集合框架。在保证线程安全的情况下使用泛型和并发集合类,Java已经经历了很久。它还包括在Java并发包中,阻塞接口以及它们的实现。集合框架的部分优点如下:
(1)使用核心集合类降低开发成本,而非实现我们自己的集合类。
(2)随着使用经过严格测试的集合框架类,代码质量会得到提高。
(3)通过使用JDK附带的集合类,可以降低代码维护成本。
(4)复用性和可操作性。

2.集合框架中的泛型有什么优点?
答:Java1.5引入了泛型,所有的集合接口和实现都大量地使用它。泛型允许我们为集合提供一个可以容纳的对象类型,因此,如果你添加其它类型的任何元素,它会在编译时报错。这避免了在运行时出现ClassCastException,因为你将会在编译时得到报错信息。泛型也使得代码整洁,我们不需要使用显式转换和instanceOf操作符。它也给运行时带来好处,因为不会产生类型检查的字节码指令。

3.Java集合框架的基础接口有哪些?
答:Collection为集合层级的根接口。一个集合代表一组对象,这些对象即为它的元素。Java平台不提供这个接口任何直接的实现。Set是一个不能包含重复元素的集合。这个接口对数学集合抽象进行建模,被用来代表集合,就如一副牌。List是一个有序集合,可以包含重复元素。你可以通过它的索引来访问任何元素。List更像长度动态变换的数组。Map是一个将key映射到value的对象.一个Map不能包含重复的key:每个key最多只能映射一个value。一些其它的接口有Queue、Dequeue、SortedSet、SortedMap和ListIterator。

4.为何Collection不从Cloneable和Serializable接口继承?
答:Collection接口指定一组对象,对象即为它的元素。如何维护这些元素由Collection的具体实现决定。例如,一些如List的Collection实现允许重复的元素,而其它的如Set就不允许。很多Collection实现有一个公有的clone方法。然而,把它放到集合的所有实现中也是没有意义的。这是因为Collection是一个抽象表现。重要的是实现。当与具体实现打交道的时候,克隆或序列化的语义和含义才发挥作用。所以,具体实现应该决定如何对它进行克隆或序列化,或它是否可以被克隆或序列化。在所有的实现中授权克隆和序列化,最终导致更少的灵活性和更多的限制。特定的实现应该决定它是否可以被克隆和序列化。

5.为何Map接口不继承Collection接口?
答:尽管Map接口和它的实现也是集合框架的一部分,但Map不是集合,集合也不是Map。因此,Map继承Collection毫无意义,反之亦然。如果Map继承Collection接口,那么元素去哪儿?Map包含key-value对,它提供抽取key或value列表集合的方法,但是它不适合“一组对象”规范。

6.Iterator是什么?
答:Iterator接口提供遍历任何Collection的接口。我们可以从一个Collection中使用迭代器方法来获取迭代器实例。迭代器取代了Java集合框架中的Enumeration。迭代器允许调用者在迭代过程中移除元素。

7.Enumeration和Iterator接口的区别?
答:Enumeration的速度是Iterator的两倍,也使用更少的内存。Enumeration是非常基础的,也满足了基础的需要。但是,与Enumeration相比,Iterator更加安全,因为当一个集合正在被遍历的时候,它会阻止其它线程去修改集合。迭代器取代了Java集合框架中的Enumeration。迭代器允许调用者从集合中移除元素,而Enumeration不能做到。为了使它的功能更加清晰,迭代器方法名已经经过改善。

8.为何没有像Iterator.add()这样的方法,向集合中添加元素?
答:语义不明,已知的是,Iterator的协议不能确保迭代的次序。然而要注意,ListIterator没有提供一个add操作,它要确保迭代的顺序。

9.为何迭代器没有一个方法可以直接获取下一个元素,而不需要移动游标?
答:它可以在当前Iterator的顶层实现,但是它用得很少,如果将它加到接口中,每个继承都要去实现它,这没有意义。

10.Iterater和ListIterator之间有什么区别?
答:(1)我们可以使用Iterator来遍历Set和List集合,而ListIterator只能遍历List。
(2)Iterator只可以向前遍历,而LIstIterator可以双向遍历。
(3)ListIterator从Iterator接口继承,然后添加了一些额外的功能,比如添加一个元素、替换一个元素、获取前面或后面元素的索引位置。


11.通过迭代器fail-fast属性,你明白了什么?
答:每次我们尝试获取下一个元素的时候,Iterator fail-fast属性检查当前集合结构里的任何改动。如果发现任何改动,它抛出ConcurrentModificationException。Collection中所有Iterator的实现都是按fail-fast来设计的(ConcurrentHashMap和CopyOnWriteArrayList这类并发集合类除外)。

12.fail-fast与fail-safe有什么区别?
答:Iterator的fail-fast属性与当前的集合共同起作用,因此它不会受到集合中任何改动的影响。Java.util包中的所有集合类都被设计为fail-fast的,而java.util.concurrent中的集合类都为fail-safe的。Fail-fast迭代器抛出ConcurrentModificationException,而fail-safe迭代器从不抛出ConcurrentModificationException。

13.在迭代一个集合的时候,如何避免ConcurrentModificationException?
答:在遍历一个集合的时候,我们可以使用并发集合类来避免ConcurrentModificationException,比如使用CopyOnWriteArrayList,而不是ArrayList。

14.为何Iterator接口没有具体的实现?
答:Iterator接口定义了遍历集合的方法,但它的实现则是集合实现类的责任。每个能够返回用于遍历的Iterator的集合类都有它自己的Iterator实现内部类。这就允许集合类去选择迭代器是fail-fast还是fail-safe的。比如,ArrayList迭代器是fail-fast的,而CopyOnWriteArrayList迭代器是fail-safe的。

15.UnsupportedOperationException是什么?
答:UnsupportedOperationException是用于表明操作不支持的异常。在JDK类中已被大量运用,在集合框架java.util.Collections.UnmodifiableCollection将会在所有add和remove操作中抛出这个异常。

16.在Java中,HashMap是如何工作的?
答:HashMap在Map.Entry静态内部类实现中存储key-value对。HashMap使用哈希算法,在put和get方法中,它使用hashCode()和equals()方法。当我们通过传递key-value对调用put方法的时候,HashMap使用Key hashCode()和哈希算法来找出存储key-value对的索引。Entry存储在LinkedList中,所以如果存在entry,它使用equals()方法来检查传递的key是否已经存在,如果存在,它会覆盖value,如果不存在,它会创建一个新的entry然后保存。当我们通过传递key调用get方法时,它再次使用hashCode()来找到数组中的索引,然后使用equals()方法找出正确的Entry,然后返回它的值。下面的图片解释了详细内容。其它关于HashMap比较重要的问题是容量、负荷系数和阀值调整。HashMap默认的初始容量是32,负荷系数是0.75。阀值是为负荷系数乘以容量,无论何时我们尝试添加一个entry,如果map的大小比阀值大的时候,HashMap会对map的内容进行重新哈希,且使用更大的容量。容量总是2的幂,所以如果你知道你需要存储大量的key-value对,比如缓存从数据库里面拉取的数据,使用正确的容量和负荷系数对HashMap进行初始化是个不错的做法。

17.hashCode()和equals()方法有何重要性?
答:HashMap使用Key对象的hashCode()和equals()方法去决定key-value对的索引。当我们试着从HashMap中获取值的时候,这些方法也会被用到。如果这些方法没有被正确地实现,在这种情况下,两个不同Key也许会产生相同的hashCode()和equals()输出,HashMap将会认为它们是相同的,然后覆盖它们,而非把它们存储到不同的地方。同样的,所有不允许存储重复数据的集合类都使用hashCode()和equals()去查找重复,所以正确实现它们非常重要。equals()和hashCode()的实现应该遵循以下规则:
(1)如果o1.equals(o2),那么o1.hashCode() == o2.hashCode()总是为true的。
(2)如果o1.hashCode() == o2.hashCode(),并不意味着o1.equals(o2)会为true。

18.我们能否使用任何类作为Map的key?
答:我们可以使用任何类作为Map的key,然而在使用它们之前,需要考虑以下几点:
(1)如果类重写了equals()方法,它也应该重写hashCode()方法。
(2)类的所有实例需要遵循与equals()和hashCode()相关的规则。请参考之前提到的这些规则。
(3)如果一个类没有使用equals(),你不应该在hashCode()中使用它。
(4)用户自定义key类的最佳实践是使之为不可变的,这样,hashCode()值可以被缓存起来,拥有更好的性能。不可变的类也可以确保hashCode()和equals()在未来不会改变,这样就会解决与可变相关的问题了。比如,我有一个类MyKey,在HashMap中使用它。

19.队列和栈是什么,列出它们的区别?
答:栈和队列两者都被用来预存储数据。java.util.Queue是一个接口,它的实现类在Java并发包中。队列允许先进先出(FIFO)检索元素,但并非总是这样。Deque接口允许从两端检索元素。栈与队列很相似,但它允许对元素进行后进先出(LIFO)进行检索。Stack是一个扩展自Vector的类,而Queue是一个接口。

20.Comparable和Comparator接口有何区别?
答:Comparable和Comparator接口被用来对对象集合或者数组进行排序。Comparable接口被用来提供对象的自然排序,我们可以使用它来提供基于单个逻辑的排序。
Comparator接口被用来提供不同的排序算法,我们可以选择需要使用的Comparator来对给定的对象集合进行排序。
 



Tags in this post...

面试题 相关文章推荐
PHP开发工程师面试问题集锦
Nov 01 面试题
请说出几个常用的异常类
Jan 08 面试题
编写函数,将一个3*3矩阵转置
Oct 09 面试题
What is view? why do we have view?
Jun 22 面试题
C# Debug和Testing相关面试题
Oct 25 面试题
介绍一下Linux中的链接
Jun 05 面试题
Linux内核的同步机制是什么?主要有哪几种内核锁
Jul 11 面试题
Linux常见面试题
Mar 18 面试题
Ajax请求总共有多少种Callback
Jul 17 面试题
Ajax和javascript的区别
Jul 20 面试题
腾讯公司的一个sql题
Jan 22 面试题
介绍一下如何优化MySql
Dec 20 面试题
IBatis持久层技术
Jul 18 #面试题
Hibernate持久层技术
Dec 16 #面试题
Jdbc数据访问技术面试题
Mar 30 #面试题
Java基础类库面试题
Sep 04 #面试题
25道Java面试题集合
May 21 #面试题
Java面试题汇总
Dec 06 #面试题
Java面向对象面试题
Dec 26 #面试题
You might like
DC宇宙的第一个英雄,堪称动漫史鼻祖,如今成为美国文化的象征
2020/04/09 欧美动漫
有关 PHP 和 MySQL 时区的一点总结
2008/03/26 PHP
PHP 一个随机字符串生成代码
2010/05/26 PHP
PHP版网站缓存加快打开速度的方法分享
2012/06/03 PHP
PHP生成条形图的方法
2014/12/10 PHP
php隐藏实际地址的文件下载方法
2015/04/18 PHP
php实现基于openssl的加密解密方法
2016/09/30 PHP
PHP程序员简单的开展服务治理架构操作详解(三)
2020/05/14 PHP
javascript vvorld 在线加密破解方法
2008/11/13 Javascript
JavaScript学习笔记(十)
2010/01/17 Javascript
javascript特殊用法示例介绍
2013/11/29 Javascript
jquery 判断滚动条到达了底部和顶端的方法
2014/04/02 Javascript
JavaScript拆分字符串时产生空字符的解决方案
2014/09/26 Javascript
用模版生成HTML的的框架jquery.tmpl使用详解
2015/01/07 Javascript
详解Angular 中 ngOnInit 和 constructor 使用场景
2017/06/22 Javascript
探索webpack模块及webpack3新特性
2017/09/18 Javascript
在vue-cli的组件模板里使用font-awesome的两种方法
2018/09/28 Javascript
Node.js原生api搭建web服务器的方法步骤
2019/02/15 Javascript
JS 遍历 json 和 JQuery 遍历json操作完整示例
2019/11/11 jQuery
js实现点击上传图片并设为模糊背景
2020/08/02 Javascript
jquery实现穿梭框功能
2021/01/19 jQuery
Python中进程和线程的区别详解
2017/10/29 Python
Python实现进程同步和通信的方法
2018/01/02 Python
Python While循环语句实例演示及原理解析
2020/01/03 Python
pytorch下的unsqueeze和squeeze的用法说明
2021/02/06 Python
Pharmacy Online中文直邮网站:澳洲大型药房
2020/06/27 全球购物
学期自我评价
2014/01/27 职场文书
军训口号
2014/06/13 职场文书
2015公务员试用期工作总结
2014/12/12 职场文书
优秀工作者事迹材料
2014/12/26 职场文书
后勤个人工作总结
2015/02/28 职场文书
幼儿园教师自我评价
2015/03/04 职场文书
2015年电话客服工作总结
2015/05/18 职场文书
六一活动主持词
2015/06/30 职场文书
医疗纠纷调解协议书
2015/08/06 职场文书
深入浅出的讲解:信号调制到底是如何实现的
2022/02/18 无线电