3到5年工作经验是如何回答面试中被问到的Java集合框架问题

可能很多人会问Java集合真的那么重要吗,就像为什么现在很多企业都喜欢先问算法一样,目的就是考察你对Java基础掌握的程度如何。下面我将列出了一些关于Java集合的重要问题,让我们一起看看3到5年的Java开发工程师是如何回答这些问题的。

Java集合中 List、Set、Map 之间的区别

比较/集合 List Set Map
元素 可以重复 不可重复(equals比较) 键必须唯一,但是值可以重复
顺序 有序 无序(有hashcode决定) 无序
常用方法 add( )、remove( )、clear( )、get( )、contains( )、size( ) add( )、remove( )、clear( )、contains( )、size( ) put( )、get( )、remove( )、clear( )、containsKey( )、containsValue( )、keySet( )、values( )、size( )
常见实现类 ArrayList、LinkedList、Vector HashSet、LinkedHashSet、TreeSet HashMap、HashTable
允许插入null 可以插入多个null 只允许插入一个null 键只允许插入一个null,值可以插入多个null值

一、浅谈一下ArrayList和LinkedList各自的优缺点

  1. 顺序插入速度ArrayList会比较快,因为ArrayList是基于数组实现的,数组是事先new好的,只要往指定位置塞一个数据就好了;LinkedList则不同,每次顺序插入的时候LinkedList将new一个对象出来,如果对象比较大,那么new的时间势必会长一点,再加上一些引用赋值的操作,所以顺序插入LinkedList必然慢于ArrayList。
  2. 基于上一点,因为LinkedList里面不仅维护了待插入的元素,还维护了Entry(单向链表)的前置Entry和后继Entry,如果一个LinkedList中的Entry非常多,那么LinkedList将比ArrayList更耗费一些内存。
  3. 数据遍历的速度,使用各自遍历效率最高的方式,ArrayList的遍历效率会比LinkedList的遍历效率高一些。
  4. LinkedList做插入、删除的时候,慢在寻址,快在只需要改变前后Entry(单向链表)的引用地址。ArrayList做插入、删除的时候,慢在数组元素的批量copy,快在寻址。

二、使用LinkedList实现堆栈和队列

1.堆栈:是一种先进后出的数据结构(容器),就像弹夹一样(压子弹)

2.队列:先进先出(当多个任务分配给打印机时,为了防止冲突,创建一个队列,把任务入队,按先入先出的原则处理任务。当多个用户要访问远程服务端的文件时,也用到队列,满足先来先服务的原则。)

原来这才是使用LinkedList实现堆栈和队列的方式!

三、for循环和foreach遍历集合哪个更快

1.当遍历数组结构的集合时用for或者foreach都行,在固定长度或长度不需要计算的时候for循环效率高于foreach。

2.在不确定长度或者计算长度有损性能的时候用foreach比较方便。

3.对于数组来说,for和foreach循环效率差不多,但是对于链表来说,for循环效率明显比foreach低。

如果使用foreach,当数据量大的时候有可能会导致系统崩溃,为什么会很糟糕,因为for循环时要获取第i个元素必须从头开始遍历,而iterator遍历就是从头开始遍历,遍历完只需要一次(foreach循环就是用的iterator)。 

四、如何快速的遍历map集合,哪种方式最快?

map.entrySet即可,entrySet的方式整体都是比keySet方式要高一些,代码如下:

public static void main(String[] args) {
	Map<Integer, String> map=new TreeMap<Integer, String>();
	map.put(11, "张三");
	map.put(22, "李四");
	map.put(33, "王五");
	map.put(11, "张三三");
	for(Map.Entry<Integer, String> entry:map.entrySet()){
		System.out.println("key:"+entry.getKey()+"\t"+"value:"+entry.getValue());
	} 
} 

 entrySet比keySet快的原因:

  • 如果就只获取key来说,两者的差别并不大,但是如果要获取value,还是entrySet的效率会更好。因为keySet需要从map中再次根据key获取value(keySet相当于遍历了2次),而entrySet是一次都全部获取出来。

  • map.get(key)获取的时候,底层其实根据key的hashcode值经过哈希算法得到一个hash值然后作为索引映射到对应table数组的索引位置,这是一次密集型计算,很耗费CPU,如果有大量的元素,则会使CPU使用率飙升,影响响应速度,而entrySet()返回的set里边元素都是Map.Entry类型,key和value就是这个类的一个属性,entry.getKey()和entry.getValue()效率肯定很高。

五、请说一说HashMap和HashSet有哪些区别?

HashMap HashSet
实现了Map接口 实现了Set接口
储存键值对 只存储对象
使用put()方法将元素放入map中 使用add()方法将元素放入set中
使用键对象来计算hashcode值    HashSet使用成员对象来计算hashcode值,对于两个对象来说hashcode可能相同,所以equals()方法用来判断对象的相等性,如果两个对象不同的话,那么返回false。
HashMap比较快,因为是使用唯一的键来获取对象 HashSet较HashMap来说比较慢

六、HashSet、TreeSet、LinkedHashSet区别?

  • HashSet:插入速度快
  • TreeSet:可以确保集合元素处于排序状态
  • LinkedHashSet:可以按照插入的顺序存储集合

1.HashSet是基于Hash算法实现的,其性能通常都优于TreeSet。为快速查找而设计的Set,我们通常都应该使用HashSet,在我们需要排序的功能时,我们才使用TreeSet。

2.HashSet还有一个子类LinkedHashSet,LinkedHashSet集合也是根据元素hashCode值来决定元素存储位置,但它同时使用链表维护元素的次序,当遍历该集合时候,LinkedHashSet将会以元素的添加顺序访问集合的元素。 如果我们需要迭代遍历的顺序为插入顺序或者访问顺序,那么 LinkedHashSet 是需要我们首先考虑的。

七、HashMap的数据存储和实现原理你了解多少?

HashMap中的数据结构是数组+单链表的组合,以键值对(key-value)的形式存储元素的,通过put()和get()方法储存和获取对象。可以理解为两列多行的表格,第一列中存储索引或者起标识作用的对象,第二列存储我们实际要用的对象,当我们需要第二列中某个对象时,就去找这个对象的索引。

  • 当我们给put()方法传递键和值时,HashMap会由key来调用hash()方法,返回键的hash值,计算Index后用于找到bucket(哈希桶)的位置来储存Entry对象。
  • 我们调用get()方法,HashMap会使用key的hashcode找到bucket位置,因为HashMap在链表中存储的是Entry键值对,所以找到bucket位置之后,会调用key的equals()方法,按顺序遍历链表的每个 Entry,直到找到想获取的 Entry 为止。

八、在什么场景下要重写equals()和hashcode()方法?

1.将对象放到Set集合或者是想作为Map的key时,那么你必须重写equals()方法,这样才能保证唯一性。hashCode 和 equals的关系:两个对象 equals的时候,hashCode必须相等,但hashCode相等,对象不一定equals。                                
2.必须重写hashCode()的情况:如果你的对象想放进散列存储的集合中(比如:HashSet,LinkedHashSet)或者想作为散列Map(例如:HashMap,LinkedHashMap等等)的Key时,在重写equals()方法的同时,必须重写hashCode()方法。hashCode()方法存在的主要目的就是提高效率,但是如果你想把对象放到散列存储结构的集合中时,是必须要重写的。

hashCode并不能表现其唯一性,但是有离散性,其意义就是类似于进行hashMap等操作时,加快对象比较的速度,进而加快对象搜索的速度。 

九、HashMap和TreeMap有什么不同?

1.当Map中插入、删除和定位元素这类操作时,HashMap是最好的选择。

2.如果你需要对一个有序的key集合进行遍历,TreeMap是更好的选择。基于你的collection的大小,向HashMap中添加元素会更快,将map换为TreeMap可以进行有序key的遍历。

十、Collections和Collection有哪些区别?

Collection 是一个集合根接口,Collections 是一个包装类(工具类/帮助类)。它包含有各种有关集合操作的静态多态方法。此类不能实例化,就像一个工具类,用于对集合中元素进行排序、搜索以及线程安全等各种操作,服务于Java的Collection框架。

十一、如何对一组对象进行排序?

  1. 如果我们需要对一个对象数组进行排序,我们可以使用Arrays.sort()方法。
  2. 如果我们需要排序一个对象列表,我们可以使用Collection.sort()方法。

两个都有用于自然排序(使用Comparable)或基于标准的排序(使用Comparator)的重载方法sort()。Collections内部使用数组排序方法,所有它们两者都有相同的性能,只是Collections需要花时间将列表转换为数组。

十二、Comparable和Comparator接口有何区别?

Comparable 用来提供对象的自然排序,我们可以使用它来提供基于单个逻辑的排序。
Comparator 提供不同的排序算法,我们可以选择需要使用的Comparator来对给定的对象集合进行排序。

Comparable和Comparator接口被用来对对象集合或者数组进行排序。

 

--------------------------------------------保持专注,世界才会为你让路。--------------------------------------------

发布了48 篇原创文章 · 获赞 176 · 访问量 34万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 技术黑板 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览