Java面试复习6 Java中的集合list,map,set,collection等等

Java面试复习6 Java中的集合collection(list,set),Map等等

声明:本面试复习都基于一本未署名的Java面试宝典所述,根据自己的理解写出了这一专栏的复习博客

  1. 已知一个HashMap<Integer, User> 集合,User 有name (String) 和age (int) 属性。请写一个方法实现对HashMap的排序功能,该方法接收HashMap<Integer, User> 为形参,返回类型为HashMap<Integer, User> ,
    要求对HashMap中的User的age倒序进行排序。排序时key=value键值对不得拆散。
    (作者说这是他的面试题,hhh)

    看到这个题,第一反应是头都大了,因为过去好久了,对于集合这块的只是已经遗忘的差不多额,那就借助此题复习了。

    首先是集合的体系分类

    Java 集合可分为 Collection 和 Map 两种体系。

    1. Collection接口: 单列数据, 定义了存取一组对象的方法的集合
      其中一种是list集合,元素有序可重复,可以有多个null值
      ArrayList,可变数组
      LinkedList,双向链表
      Vector,可变数组,线程安全
      ---------
      另一种是
      set集合,元素无序且不可重复,只能有一个null值

      collection接口是list和set还有Queue接口的父接口。
      该接口有一个iterator迭代器方法用于遍历集合

      Iterator iter = coll.iterator();//回到集合起点
      while(iter.hasNext()){//必须进行此判断,判断是否有下一个元素可读取
          Object obj = iter.next();//获取下一元素
          if(obj.equals("Tom")){
          iter.remove();//删除符合条件的集合元素
      }
      //Iterator可以删除集合的元素, 但是是遍历过程中通过迭代器对象的remove方法, 
      //不是集合对象的remove方法。
      //如果还未调用next()或在上一次调用 next 方法之后已经调用了 remove 方法,
      //再调用remove都会报IllegalStateException。
      

      还有另外一种遍历方式我们经常用:foreach循环

      for(Person p : persons){//Person:遍历元素的类型
      						//p:便利后自定义元素的名称
      						//persons:要遍历的结构名称
      	...
      }
      //Java 5.0 提供了 foreach 循环迭代访问 Collection和数组。
      //遍历操作不需获取Collection或数组的长度,无需使用索引访问元素。
      //遍历集合的底层调用Iterator完成操作。
      //foreach还可以用来遍历数组。
      
    2. Map接口: 双列数据,保存具有映射关系“key-value对”的集合

      ①Map与Collection并列存在。用于保存具有映射关系的数据:key-value

      ②Map 中的 key 和 value 都可以是任何引用类型的数据

      ③Map 中的 key 用Set来存放, 不允许重复,即同一个 Map 对象所对应的类,须重写hashCode()和equals()方法

      常用String类作为Map的“键”

      key 和 value 之间存在单向一对一关系,即通过指定的 key 总能找到唯一的、确定的 value

      ⑥Map接口的常用实现类: HashMap、 TreeMap、 LinkedHashMap和Properties。 其中, HashMap是 Map 接口使用频率最高的实现类

    OK,我们继续看这道题,这道题主要是考的HashMap相关的知识,
    HashMap

    HashMap是 Map 接口使用频率最高的实现类

    允许使用null键和null值,与HashSet一样,不保证映射的顺序

    ③所有的key构成的集合是Set:无序的、不可重复的所以, key所在的类要重写:equals()和hashCode()

    ④所有的value构成的集合是Collection:无序的、可以重复的所以, value所在的类要重写: equals()

    一个key-value构成一个entry所有的entry构成的集合是Set:无序的、不可重复的

    HashMap 判断两个 key 相等的标准是:两个 key 通过 equals() 方法返回 true,hashCode 值也相等。

    HashMap 判断两个 value相等的标准是:两个 value 通过 equals() 方法返回 true。

    复习到这里,就非常纳闷了,既然HashMap和Map都是无序的,为什么题目还要求给排序呢?那就得看Map接口的实现类中谁是可以排序的。

    那我们就挨个看看:

    1. LinkedHashMap

      LinkedHashMap 是 HashMap 的子类
      ②在HashMap存储结构的基础上,使用了一对双向链表来记录添加元素的顺序
      ③与LinkedHashSet类似, LinkedHashMap 可以维护 Map 的迭代顺序:迭代顺序与 Key-Value 对的插入顺序一致

    2. TreeMap

      ①TreeMap存储 Key-Value 对时, 需要根据 key-value 对进行排序。
      ②TreeMap 可以保证所有的 Key-Value 对处于有序状态。
      ③TreeSet底层使用红黑树结构存储数据
      ④TreeMap 的 Key 的排序:
      <1>自然排序: TreeMap 的所有的 Key 必须实现 Comparable 接口,而且所有的 Key 应该是同一个类的对象,否则将会抛出 ClasssCastException
      <2>定制排序:创建 TreeMap 时,传入一个 Comparator 对象,该对象负责对TreeMap 中的所有 key 进行排序。此时不需要 Map 的 Key 实现Comparable 接口
      ⑤TreeMap判断两个key相等的标准:两个key通过compareTo()方法或者compare()方法返回0。

    3. HashTable

      ①Hashtable是个古老的 Map 实现类, JDK1.0就提供了。不同于HashMap,
      Hashtable是线程安全的
      ③Hashtable实现原理和HashMap相同,功能相同。底层都使用哈希表结构,查询速度快,很多情况下可以互用。
      与HashMap不同, Hashtable 不允许使用 null 作为 key 和 value
      ⑤与HashMap一样, Hashtable 也不能保证其中 Key-Value 对的顺序
      ⑥Hashtable判断两个key相等、两个value相等的标准, 与HashMap一致。

    4. Properties

      ①Properties 类是 Hashtable 的子类,该对象用于处理属性文件
      ②由于属性文件里的 key、 value 都是字符串类型,所以 Properties 里的 key和 value 都是字符串类型
      ③存取数据时,建议使用setProperty(String key,String value)方法和getProperty(String key)方法

    作者找到的就是Map的链表结构LinkedHashMap类,由于它是HashMap的子类,那么我们获取到的子类对象,就和父类的属性相同。

    想好了一切,就是对排序方法的选择,在集合这里的对排序方法的选择侧重于集合所提供的的Collections工具类中的方法,直接调用就可以了。

    工具类中的排序操作: (均为static方法)
    reverse(List): 反转 List 中元素的顺序
    shuffle(List): 对 List 集合元素进行随机排序
    sort(List): 根据元素的自然顺序对指定 List 集合元素按升序排序
    sort(List, Comparator): 根据指定的 Comparator 产生的顺序对 List 集合元素进行排序
    swap(List, int, int): 将指定 list 集合中的 i 处元素和 j 处元素进行交换

    看作者的解答:
    在这里插入图片描述
    在这里插入图片描述
    可以看到的是,这里是对于无法拆分键值对的情况下进行的排序,先通过set集合获取map的键值对集合(整体获取),再将无序的set集合转换为有序的list集合,然后通过工具类比较对象中的age属性,得出排序后的list集合,最后给创建一个LinkHashMap的对象,将其存储进去,就得到了一个按照age排序的LinkHashMap集合。然后通过父类的引用,得到父类的相同集合。就算是解答完成了。

  2. 集合的安全性问题。请问ArrayList,HashSet,HashMap是线程安全的吗?如果不是怎样得到想要的线程安全的集合

    这里我们需要知道的是:在默认的集合中,HashTable和Vector是线程安全的其他的如果未经设置,都不是线程安全的。其实区分线程的安全与否也就是看他是否加上了同步锁,也就是synchronized关键字,是同步锁的标志。
    Collections工具类提供了相关的API,可以让上面那3个不安全的集合变为安全的。如下:其实本质上就是加上了synchronized关键字。
    在这里插入图片描述

  3. ArrayList内部是用什么实现的?

    内部是Object[]数组,当传入参数(即为数组长度)为空时,返回一个空的数组,相当于new了一个 Object[0] 数组,当传入参数小于零时报错,当大于零时就根据传入参数创建对应长度的新的数组。

    这里我们需要注意的是,传入集合转变为数组的过程。

    集合和数组作为两种不同的存放数据的方式,有什么不同?

    ①数组一旦被创建,其长度就是确定的。而集合是动态可变的。

    ②数组声明的类型,就决定了进行元素初始化时的类型,集合却可以有多种类型的存放

    数组在存储数据方面的弊端

    数组初始化以后,长度就不可变了,不便于扩展(即使扩展利用了ArrayList也是在根本上new 了一个全新的list集合(也就是ArrayList可变数组),而本来的数组仍然不变

    数组中提供的属性和方法少,不便于进行添加、删除、插入等操作且效率不高。同时无法直接获取存储元素的个数

    存储数据的特点单一,数组存储的数据是有序的、可以重复的。集合中有不同的接口可以满足不同的需要。

    具体代码说明
    将集合转变为数组的过程中,底层的代码是这么实现的:

    在这里插入图片描述

  4. 并发集合和普通集合如何区别?

    额…这个是真的没看明白,但是还是要粘贴上作者的解答,算是挖个坑吧。

    在这里插入图片描述
    在这里插入图片描述
    文中链接地址:https://my.oschina.net/zhupanxin/blog/269037

  5. List的三个实现类是哪几个,各有什么特点?

    ①ArrayList底层结构是数组,底层查询快,增删慢。

    ②LinkedList底层结构是链表型的,增删快,查询慢。

    ③vector底层结构是数组 线程安全的,增删慢,查询慢。

  6. List,Map,Set的区别?

    结构上

    List和Set都属于单列存储数据Map属于双列存储数据(键值对形式)

    List是有序的,可重复的允许有多个null值得存在

    Set是无序的不可重复的,只允许有一个null值存在,但是元素在集合中的位置由元素的hashcode值决定(也就是其位置是固定改的,用户无法做出更改,所以这个相对的确定因为其不可控也被归为无序)

    Map中的无序的,其key值是不可重复的,value值是允许重复的

    Map对于null值得处理是根据其子类不尽相同的,具体如下。
    在这里插入图片描述

    实现类上

    List有三个实现类,一个是ArrayList(其特点是查询快,增删慢的一个可变数组);另一个是LinkedList(其特点是查询慢,增删快的一个链表);最后是Vector(其特点是线程安全,但是效率低下,查询增删都比较慢的一个可变数组)

    Set有三个实现类,一个是Hashset(底层是HashMap实现,无序不可重复,使用时需要重写equals和hashcode方法),另一个是LinkedHashSet(继承HashSet,同时又基于LinkedHashMap来进行实现,底层使用的是LinkedHashMap),TreeSet(SortedSet接口实现类,可保证集合元素处于有序的状态,底层使用红黑树结构存储,查询速度比List快)

    红黑树参考博客:https://www.cnblogs.com/yangecnu/p/Introduce-Red-Black-Tree.html

    Map有五个接口实现类,一个是最常用的HashMap(支持null值和null键,key要重写两个方法,且key值是个set集合无序不可重复,value只需要重写equals方法,且value是个collection集合无序但是可重复),另一个是LinkedHashMap(保存记录了插入顺序的双向链表),还有一个是HashTable(是线程安全的,但是效率低,并且不允许有null值的存在),还有TreeMap(SortMap接口实现类,和TreeSet一样,底层都是红黑树结构存储数据,可以保证key-value的有序状态(默认为自然排序,根据键值得升序),但是使用之前需要进行排序),还有一个Properties(HashTable的子类,用于处理属性文件,其key和value都为字符串类型)

  7. HashMap和HashTable的区别

    看上面的就够了,上面的写的足够详细了,或者看作者写的,懒得码字了…
    在这里插入图片描述
    在这里插入图片描述

  8. 数组和链表分别比较适合于什么场景?为什么?

    数组适用于在数据比较少,并且对于存放的数据大都做的是查找工作的情况下
    原因数组是在内存中连续存储的(因此数据在数组中的内存地址就是连续的,在查找起来就比较快),但是他一经创建,申请出的内存大小便是确定的,在进行数据的增加操作时,就时常会发生数组越界异常,使操作变得异常繁琐,又会在进行删除操作时,因为空值而浪费内存空间,所以在进行增删插入时想要避免这些问题所要做的工作就相对繁琐,操作时效率比较低

    链表适用于在对数据的量无法估计的时候,并且对于数据的操作多是一些增删插入的操作。
    原因链表是在内存中离散存储的(因此他在执行查找操作时的效率较低),但由于是动态申请内存空间,形成链表,所以只有在需用的时候才会向JVM申请内存空间,每个数据申请的内存空间可以在内存的任意位置而后再通过元素的指针来使这些数据关联起来,根据需求来动态地执行插入增删操作效率较高

  9. Java中ArrayList和LinkedList的区别?

    在这里插入图片描述

  10. List a=new ArrayList()和ArrayList a =new ArrayList()的区别?

    这就是一种多态的体现,区别就是前者是一个List集合,是父类,所以他无法使用ArrayList,是子类,中所特有的方法。

  11. 要对集合更新操作时,ArrayList 和LinkedList哪个更适合?

    参考数组和链表的特点回答,因为二者的根本就分别是他们。
    更新属有查询,有删除,有插入,有增加,因此要根据不同情况下做不同的回答。

  12. 请用两个队列模拟堆栈结构。

    队列是先进先出,而堆栈属于先进后出。

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

本篇博客的最后附上两张collection和Map的概览图

在这里插入图片描述

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值