21个Java Collections面试问答

Java Collections框架是Java编程语言的核心API之一。java

这是Java面试问题的重要主题之一。在这里,我列出了一些重要的Java集合面试问题和解答,以帮助您进行面试。这直接来自我14年以上的Java编程经验。程序员

一、Java 8中与Collections相关的功能是什么?

Java 8对 Collection API 进行了重大更改。一些更改是:面试

  1. Java Stream API 用于集合类,以支持顺序处理和并行处理
  2. Iterable 接口中的默认方法forEach(),可用于迭代集合。与 lambda 表达式一块儿使用时,它很是有用,由于其参数 Consumer 是函数接口。
  3. Collections API 改进,如在Iterator接口中的forEachRemaining(Consumer action),MapreplaceAll()compute()merge()方法。

二、什么是 Java Collections Framework?列出 Collections 框架的一些好处?

每一个编程语言都使用集合,和最初的Java版本包含几个集合类:VectorStackHashtableArray。可是从较高的范围和用法来看,Java 1.2提出了Collections Framework,该框架将全部collections接口,实现和算法分组。算法

Java的集合经过使用泛型和并发集合类进行线程安全操做已经走了很长一段路。它还包括在Java的并发包中的阻塞接口及其实现。数据库

Collections 框架的一些好处是;编程

  • 经过使用核心集合类而不是实现咱们本身的集合类来减小开发工做。
  • 经过使用经过良好测试的集合框架类,能够提升代码质量。
  • 经过使用JDK附带的集合类,减小了代码维护工做。
  • 可重用性和互操做性

三、集合框架中泛型的好处是什么?

Java 1.5带有泛型,全部集合接口和实现都大量使用它。泛型容许咱们提供集合能够包含的Object的类型,所以,若是您尝试添加其余类型的任何元素,则引起编译时错误。数组

这样能够避免在运行时发生ClassCastException,由于您将在编译时收到错误。因为咱们不须要使用强制转换和_实例化_运算符,所以泛型也使代码更干净。缓存

四、Java Collections Framework的基本接口是什么?

Collection 表示集合层次结构的根。Collection表示一组元素的对象。Java平台不提供此接口的任何直接实现。安全

Set是一个不能包含重复元素的集合。此接口对数学集合的抽象进行建模,并表示集合,例如纸牌集合。并发

List是一个有序的集合,能够包含重复的元素。您能够从其索引访问任何元素。该列表更像是具备动态长度的数组。

一个Map是键映射到值的对象。映射不能包含重复的键:每一个键最多能够映射到一个值。

其余一些接口QueueDequeueIteratorSortedSetSortedMapListIterator

五、为何Collection不实现Cloneable和Serializable接口?

Collection接口指定为一组元素对象。元素的维护方式取决于Collection的具体实现。例如,某些Collection实现(例如List)容许重复元素,而其余实现(例如Set)则不容许重复元素。

许多Collection实现都有Cloneable方法。可是,将其包含在Collection的全部实现中没有意义。这是由于Collection是抽象表示。重要的是。
在处理实际实现时,克隆或序列化的语义及其含义都会发挥做用。所以具体的实现应决定如何克隆或序列化它,甚至能够对其进行克隆或序列化。
所以,在全部实现中强制进行克隆和序列化的灵活性较差,限制也更大。具体实现应决定是否能够克隆或序列化。

六、为何Map接口没有实现Collection接口?

尽管Map接口及其实现是Collections Framework的一部分,但Map不是集合,集合也不是Map。所以,Map扩展Collection是没有意义的,反之亦然。

若是Map扩展了Collection接口,那么元素在哪里?该映射包含key-value对,而且提供了一些方法来检索键或值的列表做为Collection,但它不适合“元素组”范式。

七、什么是迭代器?

迭代器接口提供了对任何Collection进行迭代的方法。咱们可使用_iterator()_方法从Collection中获取迭代器实例。在Java Collections Framework中,迭代器代替了枚举。迭代器容许调用者在迭代过程当中从基础集合中删除元素。Java Collection迭代器提供了遍历集合元素的通用方法,并实现了Iterator Design Pattern

八、Enumeration和Iterator接口之间有什么区别?

枚举的速度是Iterator的两倍,而且使用的内存更少。枚举是很是基本的,适合基本需求。可是,与Enumeration相比,Iterator安全得多,由于它始终拒绝其余线程修改被其迭代的集合对象。

在Java Collections Framework中,迭代器代替了枚举。迭代器容许调用者从基础集合中删除Enumeration没法实现的元素。迭代器方法名称已获得改进,以使其功能更清晰。

九、为何没有像Iterator.add()这样的方法将元素添加到集合中?

考虑到Iterator的约定不保证迭代顺序,缘由尚不清楚。可是请注意,ListIterator确实提供了add操做,由于它确实保证了迭代的顺序。

十、为何Iterator没有不移动光标就直接获取下一个元素的方法?

能够在当前Iterator接口的顶部实现它,可是因为不多使用它,所以将它包含在每一个人都必须实现的接口中没有意义。

十一、Iterator和ListIterator有什么区别?

  • 咱们可使用Iterator遍历Set和List集合,而ListIterator只能与Lists一块儿使用。
  • Iterator只能向前移动,而ListIterator能够用于两个方向。
  • ListIterator继承自Iterator接口,并具备其余功能,例如添加元素,替换元素,获取上一个和下一个元素的索引位置。

十二、有哪些不一样的方法能够遍历列表?

咱们能够经过两种不一样的方式遍历列表-使用迭代器和使用for-each循环。

List <String> strList = new ArrayList<>();

for(String obj:strList){
    System.out.println(obj);
}

Iterator<String> it= strList.iterator();
while(it.hasNext()){
    String obj = it.next();
    System.out.println(obj);
}

使用迭代器更加线程安全,由于它能够确保若是基础列表元素被修改,它将抛出异常ConcurrentModificationException

1三、您对Iterator fail-fast属性有什么了解?

每当咱们尝试获取下一个元素时,迭代器fail-fast属性都会检查基础集合的结构是否有任何修改。若是找到任何修改,则抛出ConcurrentModificationException。除了并行并发类(例如ConcurrentHashMap和CopyOnWriteArrayList)以外,Collection类中Iterator的全部实如今设计上都是fail-fast的。

1四、fail-fast和fail-safe之间有何区别?

Iterato fail-safe属性可与基础集合的克隆一块儿使用,所以不受集合中任何修改的影响。按照设计,java.util包中的全部集合类都是fail-fast的,而其中的集合类java.util.concurrent是fail-safe的。
fail-fast迭代器会抛出ConcurrentModificationException,而fail-safe迭代器毫不会抛出ConcurrentModificationException。

1五、如何在迭代集合时避免ConcurrentModificationException?

咱们可使用并发集合类来避免ConcurrentModificationException在集合上进行迭代,例如使用CopyOnWriteArrayList而不是ArrayList。

1六、为何没有Iterator接口的具体实现?

Iterator接口声明了用于迭代集合的方法,可是其实现是Collection实现类的责任。每一个返回迭代器以进行遍历的集合类都有其本身的Iterator实现嵌套类。

这使集合类能够选择迭代器是fail-fast仍是fail-safe的。例如,ArrayList迭代器是fail-fast的,而CopyOnWriteArrayList迭代器是fail-safe的。

1七、什么是UnsupportedOperationException?

UnsupportedOperationException是用于指示不支持该操做的异常。它普遍用于在JDK类,在集合框架java.util.Collections.UnmodifiableCollection抛出该异常全部addremove操做。

1八、HashMap如何在Java中工做?

HashMap在Map.Entry静态嵌套类实现中存储键值对。HashMap使用哈希算法,并在putget方法中使用hashCode()和equals()方法。

当咱们put经过传递键值对来调用方法时,HashMap使用带有哈希值的Key hashCode()来查找存储键值对的索引。该条目存储在LinkedList中,所以,若是已经存在一个条目,则使用equals()方法检查传递的键是否已存在,若是是,它将覆盖该值,不然它将建立一个新条目并存储此键值条目。

当咱们get经过传递Key来调用method时,它再次使用hashCode()在数组中找到索引,而后使用equals()方法找到正确的Entry并返回其值。下图将清楚地解释这些细节。

有关HashMap的其余重要信息是容量,负载因子,阈值大小调整。HashMap的初始默认容量为16,负载系数为0.75。阈值是容量乘以负载因子,而且若是Map大小大于阈值,则每当咱们尝试添加条目时,HashMap都会将Map的内容从新映射为容量更大的新数组。容量始终是2的乘方,所以,若是您知道须要存储大量的键值对,例如在缓存数据库中的数据时,最好使用正确的容量和负载因子来初始化HashMap。 。

1九、hashCode()和equals()方法的重要性是什么?

HashMap使用Key对象的hashCode()和equals()方法来肯定放置键值对的索引。当咱们尝试从HashMap中获取价值时,也会使用这些方法。若是这些方法的实现不正确,则两个不一样的Key可能会产生相同的hashCode()和equals()输出,在这种状况下,HashMap不会考虑将它们存储在不一样的位置,而是将其覆盖并覆盖它们。

一样,全部不存储重复数据的集合类都使用hashCode()和equals()查找重复项,所以正确实现它们很是重要。equals()和hashCode()的实现应遵循如下规则。

  • 若是o1.equals(o2),那么o1.hashCode() == o2.hashCode()应该永远如此true
  • 若是o1.hashCode() == o2.hashCode是真的,这并不意味着o1.equals(o2)true

20、咱们可使用任何类做为Map键吗?

咱们能够将任何类用做Map Key,可是在使用它们以前应考虑如下几点。

  • 若是该类重写equals()方法,则它也应该重写hashCode()方法。
  • 对于全部实例,该类应遵循与equals()和hashCode()关联的规则。这些规则请参考前面的问题。
  • 若是equals()中未使用类字段,则不该在hashCode()方法中使用它。
  • 用户定义的键类的最佳实践是使其不可变,以即可以将hashCode()值缓存起来以提升性能。不可变的类还确保hashCode()和equals()未来不会更改,这将解决任何可变性问题。
    例如,假设我有一个MyKey用于HashMap键的类。

    //传递的mykey name参数用于equals()和hashcode()
    MyKey key = new MyKey("Pankaj"); //假定hashCode=1234
    myHashMap.put(key, "Value");
    
    // 下面的代码将更改equals()和hashcode()的key
    // 可是它的位置不会改变
    key.setName("Amit"); //假定新的hashCode=7890
    
    //下面将返回null,由于HashMap将尝试查找键
    //与存储在同一索引中,但因为密钥发生了变化,
    //不匹配,返回空。
    myHashMap.get(new MyKey("Pankaj"));

    这就是为何String和Integer大多用做HashMap键的缘由。

2一、Map接口提供哪些不一样的Collection视图?

Map接口提供了三个集合视图:

  1. Set keySet() :返回此映射中包含的键的Set视图。该集合由Map支持,所以对Map的更改会反映在集合中,反之亦然。若是在对集合进行迭代时修改了映射(经过迭代器的remove操做除外),则迭代的结果不肯定。该集合支持元素删除,该元素经过迭代器remove,Set.remove,removeAll,retainAll和clear操做从映射中删除相应的映射。它不支持add或addAll操做。
  2. Collection values() :返回此映射中包含的值的Collection视图。集合由Map支持,所以对Map的更改会反映在集合中,反之亦然。若是在对集合进行迭代时修改了映射(经过迭代器的remove操做除外),则迭代结果不肯定。集合支持元素删除,该元素经过迭代器remove,Collection.remove,removeAll,retainAll和clear操做从映射中删除相应的映射。它不支持add或addAll操做。
  3. Set <Map.Entry <K,V >> entrySet():返回此映射中包含的映射的Set视图。该集合由Map支持,所以对Map的更改会反映在集合中,反之亦然。若是在对集合进行迭代时修改了映射(经过迭代器的remove操做或迭代器返回的映射条目上的setValue操做除外),则迭代的结果不肯定。该集合支持元素删除,该元素经过迭代器remove,Set.remove,removeAll,retainAll和clear操做从映射中删除相应的映射。它不支持add或addAll操做。

“不积跬步,无以致千里”,但愿将来的你能:有梦为马 随处可栖!加油,少年!

关注公众号:「Java 知己」,天天更新Java知识哦,期待你的到来!

  • 发送「Group」,与 10 万程序员一块儿进步。
  • 发送「面试」,领取BATJ面试资料、面试视频攻略。
  • 发送「玩转算法」,领取《玩转算法》系列视频教程。
  • 千万不要发送「1024」...

每日福利

相关文章
相关标签/搜索