网站建设年费,银川微信网站制作,专业网站制作案例,中国企业网站建设Java Collections Framework是Java编程语言的基本方面。 这是Java面试问题的重要主题之一。 在这里#xff0c;我列出了Java集合框架的一些重要问题和解答。 什么是Java Collections Framework#xff1f; 列出Collections框架的一些好处#xff1f; 集合框架中泛型的好处… Java Collections Framework是Java编程语言的基本方面。 这是Java面试问题的重要主题之一。 在这里我列出了Java集合框架的一些重要问题和解答。 什么是Java Collections Framework 列出Collections框架的一些好处 集合框架中泛型的好处是什么 Java Collections Framework的基本接口是什么 为什么Collection不扩展Cloneable和Serializable接口 为什么Map界面不扩展Collection界面 什么是迭代器 Enumeration和Iterator接口之间有什么区别 为什么没有像Iterator.add这样的方法将元素添加到集合中 为什么Iterator没有不移动光标就直接获取下一个元素的方法 Iterator和ListIterator有什么区别 有哪些不同的方法可以遍历列表 您对迭代器快速失败属性有什么了解 快速故障和故障安全之间有何区别 如何在迭代集合时避免ConcurrentModificationException 为什么没有Iterator接口的具体实现 什么是UnsupportedOperationException HashMap如何在Java中工作 hashCode和equals方法的重要性是什么 我们可以使用任何类作为Map键吗 Map界面提供哪些不同的Collection视图 HashMap和Hashtable有什么区别 如何在HashMap和TreeMap之间进行选择 ArrayList和Vector有什么异同 Array和ArrayList有什么区别 什么时候在ArrayList上使用Array ArrayList和LinkedList有什么区别 哪些集合类提供对其元素的随机访问 什么是EnumSet 哪些集合类是线程安全的 什么是并发集合类 什么是BlockingQueue 什么是队列和堆栈列出它们的区别 什么是收藏课 什么是可比和比较器界面 Comparable和Comparator接口之间有什么区别 我们如何排序对象列表 在将Collection作为参数传递给函数时我们如何确保该函数将无法对其进行修改 我们如何从给定的集合中创建一个同步的集合 Collections Framework中实现了哪些常见算法 什么是Big-O表示法 举一些例子 与Java Collections Framework相关的最佳实践是什么 Java Collections面试问题答案 列出Collections框架的一些好处 每种编程语言都使用集合并且最初的Java版本包含几个集合类 Vector Stack Hashtable和Array 。 但是从更大的范围和用法来看Java 1.2提出了Collections Framework该框架将所有collections接口实现和算法分组。 Java集合通过使用泛型和并发集合类进行线程安全操作已经走了很长一段路。 它还包括在Java并发包中的阻塞接口及其实现。 收款框架的一些好处是 通过使用核心集合类而不是实现我们自己的集合类来减少开发工作。 通过使用经过良好测试的集合框架类可以提高代码质量。 通过使用JDK附带的收集类减少了代码维护工作。 可重用性和互操作性 集合框架中泛型的好处是什么 Java 1.5带有泛型所有集合接口和实现都大量使用它。 泛型允许我们提供集合可以包含的Object的类型因此如果您尝试添加其他类型的任何元素则会引发编译时错误。 这样可以避免在运行时发生ClassCastException因为您将在编译时收到错误。 由于我们不需要使用强制转换和instanceof运算符因此泛型也使代码更干净。 由于不会生成进行类型检查的字节码指令因此它还可以增加运行时的收益。 Java Collections Framework的基本接口是什么 集合是集合层次结构的根。 集合表示一组称为其元素的对象。 Java平台不提供此接口的任何直接实现。 Set是一个不能包含重复元素的集合。 此接口对数学集合的抽象进行建模并用于表示集合例如纸牌组。 List是一个有序的集合可以包含重复的元素。 您可以从索引中访问任何元素。 列表更像是具有动态长度的数组。 映射是将键映射到值的对象。 映射不能包含重复的键每个键最多可以映射到一个值。 其他一些接口是Queue Dequeue Iterator SortedSet SortedMap和ListIterator 。 为什么Collection不扩展Cloneable和Serializable接口 集合接口指定一组称为元素的对象。 元素的维护方式取决于Collection的具体实现。 例如某些Collection实现例如List允许重复元素而其他实现例如Set则不允许重复元素。 许多Collection实现都有公共克隆方法。 但是将其包含在Collection的所有实现中并没有任何意义。 这是因为Collection是抽象表示。 重要的是实施。 在处理实际实现时克隆或序列化的语义及其含义都会发挥作用。 因此具体的实现应决定如何克隆或序列化它甚至可以对其进行克隆或序列化。 因此在所有实现中强制进行克隆和序列化实际上不太灵活而且限制更大。 具体实现应决定是否可以克隆或序列化。 为什么Map界面不扩展Collection界面 尽管Map接口及其实现是Collections Framework的一部分但Map不是集合集合也不是Map。 因此Map扩展Collection是没有意义的反之亦然。 如果Map扩展了Collection接口那么元素在哪里 Map包含键值对并且提供了一些方法来检索键或值的列表作为Collection但它不适合“元素组”范式。 什么是迭代器 迭代器接口提供了对任何Collection进行迭代的方法。 我们可以使用迭代器方法从Collection中获取迭代器实例。 在Java Collections Framework中迭代器代替了枚举。 迭代器允许调用者在迭代过程中从基础集合中删除元素。 Enumeration和Iterator接口之间有什么区别 枚举的速度是Iterator的两倍并且使用的内存更少。 枚举是非常基本的适合基本需求。 但是与Enumeration相比Iterator安全得多因为它始终拒绝其他线程修改被其迭代的集合对象。 在Java Collections Framework中迭代器代替了枚举。 迭代器允许调用者从基础集合中删除Enumeration无法实现的元素。 迭代器方法名称已得到改进以使其功能更清晰。 为什么没有像Iterator.add这样的方法将元素添加到集合中 考虑到Iterator的约定不保证迭代顺序语义尚不清楚。 但是请注意ListIterator确实提供了添加操作因为它确实保证了迭代的顺序。 为什么Iterator没有不移动光标就直接获取下一个元素的方法 它可以在当前Iterator接口的顶部实现但由于很少使用因此将其包含在每个人都必须实现的接口中没有意义。 Iterator和ListIterator有什么区别 我们可以使用Iterator遍历Set和List集合而ListIterator只能与Lists一起使用。 迭代器只能向前移动而ListIterator可以用于两个方向。 ListIterator继承自Iterator接口并具有其他功能例如添加元素替换元素获取上一个和下一个元素的索引位置。 有哪些不同的方法可以遍历列表 我们可以通过两种不同的方式遍历列表-使用迭代器和使用for-each循环。 ListString strList new ArrayList();//using for-each loopfor(String obj : strList){System.out.println(obj);}//using iteratorIteratorString it strList.iterator();while(it.hasNext()){String obj it.next();System.out.println(obj);} 使用迭代器更加线程安全因为它可以确保如果基础列表元素被修改它将抛出ConcurrentModificationException 。 您对迭代器快速失败属性有什么了解 每当我们尝试获取下一个元素时迭代器fail-fast属性都会检查基础集合的结构是否有任何修改。 如果找到任何修改则抛出ConcurrentModificationException 。 除了并行并发类例如ConcurrentHashMap和CopyOnWriteArrayList之外Collection类中Iterator的所有实现在设计上都是快速失败的。 快速故障和故障安全之间有何区别 Iterator故障安全属性可与基础集合的克隆一起使用因此不受集合中任何修改的影响。 按照设计 java.util包中的所有收集类都是快速失败的而java.util.concurrent中的收集类是故障安全的。 快速故障迭代器会抛出ConcurrentModificationException而安全故障迭代器绝不会抛出ConcurrentModificationException。 检查这篇文章中的CopyOnWriteArrayList示例 。 如何在迭代集合时避免ConcurrentModificationException 我们可以使用并发集合类来避免在迭代集合时发生ConcurrentModificationException 例如使用CopyOnWriteArrayList而不是ArrayList。 在这篇文章中查看ConcurrentHashMap示例 。 为什么没有Iterator接口的具体实现 迭代器接口声明了用于迭代集合的方法但是其实现是Collection实现类的责任。 每个返回遍历迭代器的集合类都有其自己的Iterator实现嵌套类。 这使集合类可以选择迭代器是快速失败还是故障安全的。 例如ArrayList迭代器是快速失败的而CopyOnWriteArrayList迭代器是故障安全的。 什么是UnsupportedOperationException UnsupportedOperationException是用于指示不支持该操作的异常。 它在JDK类中得到了广泛使用在集合框架java.util.Collections.UnmodifiableCollection 所有add和remove操作都会抛出此异常。 HashMap如何在Java中工作 HashMap将键值对存储在Map.Entry静态嵌套类实现中。 HashMap使用哈希算法并在put和get方法中使用hashCode和equals方法。当我们通过传递键值对来调用put方法时HashMap使用带有哈希的Key hashCode来找出存储密钥的索引-值对。 该条目存储在LinkedList中因此如果已经存在条目则使用equals方法检查传递的键是否已经存在如果是它将覆盖该值否则它将创建一个新条目并存储此键值条目当我们通过传递Key调用get方法时它再次使用hashCode在数组中查找索引然后使用equals方法找到正确的Entry并返回其值。 下图将清楚地解释这些细节。 有关HashMap的其他重要信息是容量负载因子阈值大小调整。 HashMap的初始默认容量为32负载系数为0.75。 阈值是容量乘以负载因子每当我们尝试添加条目时如果映射大小大于阈值则HashMap会将映射的内容重新映射为容量更大的新数组。 容量始终是2的幂因此如果您知道需要存储大量键值对例如在从数据库缓存数据时最好使用正确的容量和负载因子来初始化HashMap。 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为true则并不意味着o1.equals(o2)为true 。 我们可以使用任何类作为Map键吗 我们可以将任何类用作Map Key但是在使用它们之前应考虑以下几点。 如果该类重写equals方法则它也应该重写hashCode方法。 对于所有实例该类应遵循与equals和hashCode关联的规则。 这些规则请参考前面的问题。 如果equals中未使用类字段则不应在hashCode方法中使用它。 用户定义的键类的最佳实践是使其不可变以便可以将hashCode值缓存起来以提高性能。 不可变的类还确保hashCode和equals将来不会更改这将解决任何可变性问题。 例如假设我有一个用于MyHashMap键的类MyKey 。 //MyKey name argument passed is used for equals() and hashCode()
MyKey key new MyKey(Pankaj); //assume hashCode1234
myHashMap.put(key, Value);// Below code will change the key hashCode() and equals()
// but its location is not changed.
key.setName(Amit); //assume new hashCode7890//below will return null, because HashMap will try to look for key
//in the same index as it was stored but since key is mutated,
//there will be no match and it will return null.
myHashMap.get(new MyKey(Pankaj)); 这就是为什么String和Integer大多用作HashMap键的原因。 Map界面提供哪些不同的Collection视图 Map界面提供了三个集合视图 Set keySet返回此映射中包含的键的Set视图。 该集合由地图支持因此对地图的更改会反映在集合中反之亦然。 如果在对集合进行迭代时修改了映射通过迭代器自己的remove操作除外则迭代的结果不确定。 该集合支持元素删除该元素通过Iterator.removeSet.removeremoveAllretainAll和clear操作从映射中删除相应的映射。 它不支持add或addAll操作。 Collection values返回此映射中包含的值的Collection视图。 集合由地图支持因此对地图的更改会反映在集合中反之亦然。 如果在对集合进行迭代时修改了映射通过迭代器自己的remove操作除外则迭代的结果是不确定的。 集合支持元素删除该元素通过Iterator.removeCollection.removeremoveAllretainAll和clear操作从映射中删除相应的映射。 它不支持add或addAll操作。 Set Map.Entry KV entrySet 返回此映射中包含的映射的Set视图。 该集合由地图支持因此对地图的更改会反映在集合中反之亦然。 如果在进行集合迭代时修改了映射除非通过迭代器自己的remove操作或通过迭代器返回的映射条目上的setValue操作则迭代的结果是不确定的。 该集合支持元素删除该元素通过Iterator.removeSet.removeremoveAllretainAll和clear操作从映射中删除相应的映射。 它不支持add或addAll操作。 HashMap和Hashtable有什么区别 HashMap和Hashtable都实现了Map接口外观相似但是HashMap和Hashtable之间存在以下区别。 HashMap允许空键和值而Hashtable不允许空键和值。 Hashtable已同步但HashMap未同步。 因此HashMap更适合单线程环境而Hashtable适合多线程环境。 LinkedHashMap是Java 1.4中作为HashMap的子类引入的因此如果需要迭代顺序则可以轻松地从HashMap切换到LinkedHashMap但是对于Hashtable而言情况并非如此其迭代顺序是不可预测的。 HashMap提供了要迭代的键集因此它是快速失败的但是Hashtable提供了不支持此功能的键枚举。 Hashtable被认为是旧类如果在迭代时要查找Map的修改则应使用ConcurrentHashMap。 如何在HashMap和TreeMap之间进行选择 为了在Map中插入删除和定位元素HashMap提供了最佳选择。 但是如果需要按排序顺序遍历键则TreeMap是更好的选择。 根据集合的大小向HashMap中添加元素然后将地图转换为TreeMap以进行排序的键遍历可能更快。 ArrayList和Vector有什么异同 ArrayList和Vector在许多方面都是相似的类。 两者均基于索引并由内部数组进行备份。 两者都保持插入顺序我们可以按插入顺序获得元素。 ArrayList和Vector的迭代器实现在设计上都是快速失败的。 ArrayList和Vector都允许空值和使用索引号随机访问元素。 这些是ArrayList和Vector之间的区别。 向量已同步而ArrayList未同步。 但是如果要在迭代时查找列表的修改则应使用CopyOnWriteArrayList。 ArrayList比Vector更快因为它没有任何开销因为同步。 ArrayList更具通用性因为我们可以使用Collections实用程序类从其中轻松获取同步列表或只读列表。 什么时候在ArrayList上使用Array 数组可以包含原语或对象而ArrayList只能包含对象。 数组是固定大小的而ArrayList是动态的。 数组没有提供ArrayList之类的许多功能例如addAllremoveAll迭代器等。虽然ArrayList是我们处理列表时的明显选择但很少有数组可以很好地使用。 如果列表的大小是固定的并且主要用于存储和遍历它们。 对于原始数据类型的列表尽管Collections使用自动装箱来减少编码工作但是在处理固定大小的原始数据类型时它仍然使它们变慢。 如果您正在处理固定的多维情况则使用[] []远比List List 更容易 ArrayList和LinkedList有什么区别 ArrayList和LinkedList都实现List接口但是它们之间有一些区别。 ArrayList是由Array支持的基于索引的数据结构因此它提供对元素的随机访问性能为O1但LinkedList将数据存储为节点列表每个节点都链接到其上一个和下一个节点。 因此即使有一种使用索引获取元素的方法在内部它也会从开始遍历到索引节点然后返回该元素因此性能为On比ArrayList慢。 与ArrayList相比LinkedList中元素的插入添加或删除要快于ArrayList因为在中间添加元素时没有调整数组大小或更新索引的概念。 LinkedList比ArrayList消耗更多的内存因为LinkedList中的每个节点都存储上一个和下一个元素的引用。 哪些集合类提供对其元素的随机访问 ArrayListHashMapTreeMapHashtable类提供对其元素的随机访问。 下载java collections pdf了解更多信息。 什么是EnumSet java.util.EnumSet是设置实现以用于枚举类型。 枚举集中的所有元素都必须来自创建集时明确或隐式指定的单个枚举类型。 EnumSet不同步并且不允许使用null元素。 它还提供了一些有用的方法例如copyOfCollection cofE firstE…rest和complementOfEnumSet s。请查看此文章以获取Java枚举教程 。 哪些集合类是线程安全的 VectorHashtableProperties和Stack是同步类因此它们是线程安全的可以在多线程环境中使用。 Java 1.5 Concurrent API包含一些集合类这些类允许在迭代时修改集合因为它们在集合的克隆上起作用因此可以在多线程环境中安全使用。 什么是并发集合类 Java 1.5并发包 java.util.concurrent 包含线程安全的集合类这些类允许在迭代时修改集合。 通过设计迭代器是快速失败的并抛出ConcurrentModificationException。 这些类中的一些是CopyOnWriteArrayList ConcurrentHashMap CopyOnWriteArraySet 。阅读这些文章以更详细地了解它们。 避免ConcurrentModificationException CopyOnWriteArrayList示例 HashMap与ConcurrentHashMap 什么是BlockingQueue java.util.concurrent.BlockingQueue是一个Queue它支持以下操作在检索和删除元素时等待队列变为非空在添加元素时等待队列中的空间变为可用。BlockingQueue接口是其中的一部分java collections框架它主要用于实现生产者使用者问题。 我们不需要担心在BlockingQueue中等待生产者或对象对消费者可用的空间因为它由BlockingQueue的实现类处理.Java提供了几种BlockingQueue实现例如ArrayBlockingQueueLinkedBlockingQueuePriorityBlockingQueueSynchronousQueue等。 查看此帖子了解使用BlockingQueue解决生产者消费者问题 。 什么是队列和堆栈列出它们的区别 队列和堆栈都用于存储数据然后再处理它们。 java.util.Queue是一个接口其实现类存在于Java并发包中。 队列允许按照先进先出FIFO的顺序检索元素但情况并非总是如此。 还有一个Deque接口该接口允许从队列的两端检索元素。 堆栈类似于队列不同之处在于堆栈允许按后进先出LIFO顺序检索元素。 堆栈是扩展Vector的类而Queue是接口。 什么是收藏课 java.util.Collections是一个实用工具类仅由对集合进行操作或返回集合的静态方法组成。 它包含对集合进行操作的多态算法“包装器”这些包装器返回由指定集合支持的新集合以及其他一些零碎的东西。此类包含集合框架算法的方法例如二进制搜索排序改组反向等 什么是可比和比较器界面 Java提供了Comparable接口如果我们想使用Arrays或Collections排序方法则可以由任何自定义类实现。 可比接口具有compareToT obj方法该方法由排序方法使用。 如果“此”对象小于等于或大于作为参数传递的对象则应以使其返回负整数零或正整数的方式重写此方法。但是在大多数现实情况中我们希望根据不同的参数进行排序。 例如作为首席执行官我想根据薪水对员工进行分类而人力资源则想根据年龄对员工进行分类。 在这种情况下我们需要使用Comparator接口因为Comparable.compareTo(Object o)方法实现只能基于一个字段进行排序而我们无法选择要对compare(Object o1, Object o2)进行排序的字段.Comparator接口compare(Object o1, Object o2)方法需要采用两个Object参数必须以这样的方式实现如果第一个参数小于第二个参数则返回负int如果相等则返回零如果第一个参数等于正数则返回正int参数大于第二个参数。 检查此帖子以了解使用Comparable和Comparator接口对对象进行排序 。 Comparable和Comparator接口之间有什么区别 Comparable和Comparator接口用于对对象的集合或数组进行排序。Comparable接口用于对对象进行自然排序我们可以使用它来基于单个逻辑进行排序。 比较器接口用于提供不同的排序算法我们可以选择要用于比较给定对象集合的比较器。 我们如何排序对象列表 如果需要对对象数组进行排序则可以使用Arrays.sort() 。 如果需要对对象列表进行排序则可以使用Collections.sort() 。 这两个类都具有重载的sort方法用于自然排序使用Comparable或基于条件的排序使用Comparator。 集合内部使用数组排序方法因此两者的性能相同只是集合需要一些时间才能将列表转换为数组。 在将Collection作为参数传递给函数时我们如何确保该函数将无法对其进行修改 我们可以使用Collections.unmodifiableCollection(Collection c)方法创建一个只读集合然后再将其作为参数传递这将确保任何更改集合的操作都将抛出UnsupportedOperationException 。 我们如何从给定的集合中创建一个同步的集合 我们可以使用Collections.synchronizedCollection(Collection c)来获取指定集合支持的同步线程安全集合。 Collections Framework中实现了哪些常见算法 Java Collections Framework提供了常用的算法实现例如排序和搜索。 集合类包含这些方法实现。 这些算法大多数都可以在List上使用但是其中一些算法适用于所有类型的集合。 其中一些是排序搜索混排最小-最大值。 举一些例子 Big-O表示法根据数据结构中元素的数量来描述算法的性能。 由于Collection类实际上是数据结构因此我们通常倾向于使用Big-O表示法根据时间内存和性能来选择要使用的collection实现。示例1ArrayList get(index i)是一个恒定时间的操作并且不会t取决于列表中元素的数量。 因此它在Big-O表示法中的性能为O1。 示例2对数组或列表性能的线性搜索为On因为我们需要搜索整个元素列表以找到该元素。 与Java Collections Framework相关的最佳实践是什么 根据需要选择正确的集合类型例如如果大小固定我们可能要在ArrayList上使用Array。 如果必须按插入顺序遍历Map则需要使用TreeMap。 如果我们不希望重复则应使用Set。 一些收集类允许指定初始容量因此如果我们估计要存储的元素数量则可以使用它来避免重新哈希或调整大小。 根据接口而不是实现来编写程序它使我们可以在以后的时间轻松更改实现。 始终将泛型用于类型安全并在运行时避免ClassCastException。 使用JDK提供的不可变类作为Map中的键以避免为我们的自定义类实现hashCode和equals。 尽可能将Collections实用程序类用于算法或获取只读同步或空的Collection而不是编写自己的实现。 它将以更高的稳定性和较低的可维护性来增强代码重用。 当我找到它们时我将继续在java集合框架上添加更多问题如果您发现它有用请也与他人分享这会激发我编写更多此类问题的动力。 参考 40个Java Collections面试问题来自JCG合作伙伴 Pankaj Kumar来自Developer Recipes博客。 翻译自: https://www.javacodegeeks.com/2013/02/40-java-collections-interview-questions-and-answers.html