面试Java集合框架问题

Java集合中 List、Set、Map 之间的区别
在这里插入图片描述
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.队列:先进先出(当多个任务分配给打印机时,为了防止冲突,创建一个队列,把任务入队,按先入先出的原则处理任务。当多个用户要访问远程服务端的文件时,也用到队列,满足先来先服务的原则。)
    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区别::
HashSet、TreeSet、LinkedHashSet区别

  1. HashSet:插入速度快
  2. TreeSet:可以确保集合元素处于排序状态
  3. 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有什么不同?
  3. 当Map中插入、删除和定位元素这类操作时,HashMap是最好的选择。
  4. 如果你需要对一个有序的key集合进行遍历,TreeMap是更好的选择。基于你的collection的大小,向HashMap中添加元素会更快,将map换为TreeMap可以进行有序key的遍历。
    Collections和Collection有哪些区别?
    Collection 是一个集合根接口,Collections 是一个包装类(工具类/帮助类)。它包含有各种有关集合操作的静态多态方法。此类不能实例化,就像一个工具类,用于对集合中元素进行排序、搜索以及线程安全等各种操作,服务于Java的Collection框架。
    如何对一组对象进行排序
  5. 如果我们需要对一个对象数组进行排序,我们可以使用Arrays.sort()方法。
  6. 如果我们需要排序一个对象列表,我们可以使用Collection.sort()方法。
    两个都有用于自然排序(使用Comparable)或基于标准的排序(使用Comparator)的重载方法sort()。Collections内部使用数组排序方法,所有它们两者都有相同的性能,只是Collections需要花时间将列表转换为数组。
    Comparable和Comparator接口有何区别
    在这里插入图片描述
    Comparable和Comparator接口被用来对对象集合或者数组进行排序。

猜你喜欢

转载自blog.csdn.net/Samurai77/article/details/88744572