Java 中的集合是什么?
在 Java 中,集合是一个框架,它提供了用于存储和操作对象集合的体系结构。在 JDK 1.2 中,创建了一个名为“集合框架”的新框架,其中包含所有集合类和接口。
Java中的集合能够执行任何数据操作,例如搜索、排序、插入、操作和删除。
Java 中的单个对象单元称为集合。Java 集合类的两个基本“根”接口是 Collection 接口 (java.util.Collection) 和 Map 接口 (java.util.Map)。Java 集合框架中提供了许多接口(Set、List、Queue、Deque)和类(ArrayList、Vector、LinkedList、PriorityQueue、HashSet、LinkedHashSet、TreeSet)。
对集合框架的需求:-
在引入集合框架(或 JDK 1.2)之前,聚合 Java 对象(或集合)的标准技术是数组、向量或哈希表。所有这些集合都没有通用接口。结果,虽然所有集合的基本目标是相同的,但它们的实现是独立指定的,它们之间没有关联。此外,用户发现很难记住每个集合类中包含的所有各种方法、语法和构造函数。
1. java中的Array和Collection有什么区别?
Array 和 Collection 在存储对象引用和操作数据方面是等价的,但它们在许多方面有所不同。以下是数组和集合之间的主要区别:
Array | Collection |
数组有一个固定的大小,这意味着一旦我们构建了一个,我们就不能改变它来满足我们的需要。 | 收藏品是自然生长的,可以定制以满足我们的需求。我们可以根据我们的要求改变它的大小。 |
在性能方面,Arrays 是 Collection 的首选。 | 考虑到性能,Collection 不优于 Arrays。 |
只有同类数据类型元素可以存储在数组中。 | 同质和异质组件都可以存储在集合中。 |
因为数组没有底层数据结构,所以没有现成的方法支持。 | 任何集合类都是建立在标准数据结构之上的,因此对于每一个需求作为性能都有现成的方法支持。这些方法可以直接使用,我们不负责它们的实现。 |
对象和原语都可以存储在数组中。 | 只有对象类型可以存储在集合中。 |
在内存方面,数组不优于集合。 | 考虑到内存,Collection 优于 Arrays。 |
2. java中的Collection和Collections有什么区别?
Collection:在 java.util.package 中有一个叫做集合的接口。它用于将单独对象的集合表示为单个实体。它相当于 C++ 编程语言中的容器。集合框架的根接口称为集合。它有许多类和接口,用于将单个对象的集合表示为一个单元。采集接口的关键子接口有List、Set、Queue。虽然 map 接口是 Java 集合框架的一部分,但它不继承接口的集合。Collection 接口最重要的函数是 add()、remove()、clear()、size() 和 contains()。
Collections:java.util.package 有一个名为 Collections 的实用程序类。它定义了用于处理集合的各种实用方法,例如排序和搜索。所有方法都是静态的。这些技术为开发人员提供了急需的便利,使他们能够更成功地与 Collection Framework 交互。它提供了类似 sort() 的方法来按正常排序顺序对集合元素进行排序,并提供 min() 和 max() 来分别获取集合元素中的最小值和最大值。
Collection | Collections |
它用于将单独对象的集合表示为单个实体。 | 它定义了许多处理集合的有用方法。 |
它是一个接口。 | 它是一个实用程序类。 |
从 Java 8 开始,Collection 是一个带有静态函数的接口。抽象和默认方法也可以在接口中找到。 | 它只有静态方法。 |
3. 解释 Java 中 Collection 框架的层次结构。
整个集合框架层次结构由四个基本接口组成:Collection、List、Set、Map,以及两个用于排序的特定接口,称为 SortedSet 和 SortedMap。java.util 包包含集合框架的所有接口和类。下图描述了 Java 集合结构。
这里,e表示扩展,i表示实现
- Extends:关键字extends用于在两个类和两个接口之间创建继承。
- Implements:关键字 implements 用于创建跨类和接口的继承。
4、Collection框架有什么优势?
以下是 Collection 框架的优点:-
一致的 API:API 有一组核心接口,如 Collection、Set、List 或 Map,实现这些接口的所有类(ArrayList、LinkedList、Vector 等)都有一些通用的方法集。
减少编程工作量:程序员不必担心 Collection 的设计,而可以专注于如何在他的程序中最好地使用它。结果,面向对象程序设计(即抽象)的基本原理得到了成功的应用。
通过提供有用的数据结构和算法的高性能实现来提高程序速度和质量,因为程序员不必担心在这种情况下某个数据结构的最佳实现。他们可以简单地使用最佳实现来显着提高程序的性能。
5. 解释 Collection 框架中使用的各种接口。
集合框架有几个接口,每个接口用于存储不同类型的数据。下面列出了框架中包含的接口。
1. 可迭代接口:这是集合框架的主要接口。可迭代接口由集合接口扩展。因此,所有的接口和类都默认实现了这个接口。这个接口的主要目的是为集合提供一个迭代器。结果,这个接口只有一个抽象方法,迭代器。
2. 集合接口:集合框架的类实现了这个接口,扩展了可迭代接口。该接口涵盖了每个集合具有的所有基本方法,例如向集合中添加数据、从集合中删除数据、清除数据等。所有这些方法都包含在此接口中,因为所有类都使用它们,而不管它们的实现风格如何。此外,在此接口中包含这些方法可确保方法名称在所有集合中保持一致。总之,我们可以得出结论,这个接口为集合类的实现奠定了基础。
3 List接口:集合接口有一个子接口,称为列表接口。该接口专门用于列表数据,我们可以将所有对象存储在有序集合中。这也允许存在冗余数据。ArrayList、Vector、Stack 等各种类都实现了这个列表接口。我们可以用这些类中的任何一个创建一个列表对象,因为它们都实现了列表。
4.队列接口:队列接口,顾名思义,遵循现实世界队列行的FIFO(先进先出)顺序。该接口用于存储元素顺序很重要的所有元素。例如,当我们尝试在商店购物时,账单是按照先到先得的原则发放的。结果,请求排在第一位的个人首先收到账单。PriorityQueue、Deque、ArrayDeque 和其他类可用。因为所有这些子类都实现了队列,所以我们可以使用它们中的任何一个来创建队列对象。
5. Deque Interface:与队列数据结构略有不同。双端队列,也称为双端队列,是一种数据结构,可以从两端添加和删除元素。该接口扩展了队列接口。ArrayDeque 是实现这个接口的类。因为这个类实现了双端队列,我们可以用它来创建双端队列对象。
6. Set接口:集合是一组无序的对象,其中不能保留重复值。当我们想要避免重复事物并只保留唯一的事物时,就会使用此集合。HashSet、TreeSet、LinkedHashSet 等各种类都实现了这个集合接口。我们可以用这些类中的任何一个创建一个集合对象,因为它们都实现了集合。
7. 排序集界面:该界面在外观上类似于集合界面。唯一的区别是这个接口提供了额外的方法来维护元素的顺序。排序集接口是集合接口的扩展,用于管理排序数据。TreeSet 就是实现这个接口的类。我们可以使用这个类创建一个 SortedSet 对象,因为它实现了 SortedSet 接口。
6、ArrayList和LinkedList的区别。
数组列表 | 链表 |
此类的元素存储在动态数组中。由于添加了泛型,该类现在支持存储所有类型的对象。 | 此类的元素存储在双向链表中。这个类和 ArrayList 一样,允许存储任何类型的对象。 |
List 接口由该类实现。结果,这用作列表。 | List 和 Deque 接口都由这个类实现。因此,它既可以用作列表,也可以用作双端队列。 |
由于内部实现,操作 ArrayList 需要更长的时间。在内部,每当我们删除一个元素时,都会扫描数组并移动内存位。 | 因为在双向链表中没有改变内存位的概念,所以操作它比操作 ArrayList 花费的时间更少。遍历列表后,参考链接发生变化。 |
当应用程序需要数据存储和访问时,此类更有用。 | 当应用程序需要数据操作时,此类更有用。 |
7、java中ArrayList和Vector的区别。
以下是 java 中 ArrayList 和 Vector 之间的区别:
- Vector是同步的,也就是说一次只能有一个线程访问代码,而ArrayList是不同步的,就是多个线程可以同时对ArrayList进行操作。例如,在多线程系统中,如果一个线程正在执行添加操作,则另一个线程可能正在执行删除操作。
如果多个线程同时访问 ArrayList,我们必须同步从根本上更新列表的代码或启用简单的元素更改。从列表中添加或删除元素称为结构更改。更改现有元素的值不是结构更改。 - 数据增长:ArrayList 和 Vector 都动态扩展和收缩以最大限度地利用存储空间,但它们的方式不同。如果数组中的元素数量超过其限制,ArrayList 会增加当前数组大小的 50%,而 vector 会增加 100%,从而使当前数组大小增加一倍。
- 性能:ArrayList 比向量操作快,因为它是非同步的,但向量操作较慢,因为它们是同步的(线程安全的)。当一个线程在一个向量上工作时,它会在它上面获得一个锁,要求任何其他在它上面工作的线程等待直到锁被释放。
- Vector 可以使用 Enumeration 和 Iterator 遍历其元素,而 ArrayList 只能使用 Iterator 遍历。
8. 区分Java中的List和Set。
List 接口用于跟踪有序集合。它是 Collection 的子接口。它是允许存储重复值的有序对象集合。插入顺序保存在一个列表中,它支持位置访问和元素插入。
set 接口是 java.util 包的一部分,并扩展了 Collection 接口。它是一个无序的对象集合,其中不能存储重复值。它是使用数学集的接口。该接口继承了 Collection 接口的方法,并添加了防止插入重复元素的功能。
Set | List |
这是一个无序的序列。 | 它是一个有序的序列。 |
Set 中不允许有重复的元素。 | 列表中允许重复元素 |
不允许从某个位置访问项目。 | 可以根据元素的位置访问元素。 |
一个空元素只能存储一次。 | 可以存储多个空元素。 |
9. 区分Java中的Iterator和ListIterator。
在 Java 的 Collection 框架中,迭代器用于一个一个地获取元素。它可以用于任何类型的 Collection 对象。我们可以使用迭代器执行读取和删除操作。当我们想要迭代所有 Collection 框架实现的接口中的元素时,必须使用迭代器,例如 Set、List、Queue 和 Deque,以及所有 Map 接口实现的类。整个集合框架唯一可访问的游标是迭代器。
ListIterator 仅对实现 List 集合的类有用,例如数组列表和链表。它可以双向迭代。当我们希望枚举 List 元素时,我们必须使用 ListIterator。此游标具有比迭代器更多的方法和功能。
image.png
迭代器 Iterator | 列表迭代器 ListIterator |
只能向前遍历 Collection 中的组件。 | 在向前和向后的方向上,都可以遍历 Collection 中的组件。 |
迭代器不能用于获取索引。 | 它提供了在遍历 List 时随时获取元素索引的方法,例如 next Index() 和 previous Index()。 |
它有助于遍历 Maps、Lists 和 Sets。 | 只有 List 可以被遍历,而不是其他两个。 |
由于无法添加元素,因此会引发并发修改异常。 | 您可以随时将元素快速添加到集合中。 |
next()、remove() 和 has Next 是 Iterator 的一些函数 ()。 | next()、previous()、has Next()、has Previous() 和 add() 是 List Iterator 的一些方法 |
10.区分HashSet和TreeSet。什么时候你更喜欢 TreeSet 而不是 HashSet?
以下是 HashSet 和 TreeSet 之间的区别:-
内部实施和速度
- HashSet:对于搜索、插入和删除操作,平均需要恒定的时间。TreeSet 比 HashSet 慢。哈希表用于实现 HashSet。
- TreeSet:对于查找、插入和删除,TreeSet 取 O(Log n),高于 HashSet。另一方面,TreeSet 保留有序数据。Higher()(返回最低高的元素)、floor()、ceiling() 等操作也受支持。在 TreeSet 中,这些操作同样是 O(Log n),而 HashSet 没有实现它们。自平衡二叉搜索树用于实现 TreeSet(红黑树)。在 Java 中,TreeSet 由 TreeMap 支持。
- 存储元素
的方式 HashSet 的元素是无序的。在 Java 中,TreeSet 类以由 Comparable 或 Comparator 方法定义的排序顺序保存对象。默认情况下,TreeSet 组件按升序排序。它有很多处理有序集合的方法,包括first()、last()、headSet()、tailSet()等。 - **允许 Null 值 **
在 HashSet 中允许 Null 对象。TreeSet 不允许空对象并引发 NullPointerException。这是因为 TreeSet 使用 compareTo() 方法比较键,该方法抛出 java.lang。空指针异常。 - 比较
HashSet 比较 Set 中的两个对象并使用 equals() 方法检测重复项。出于同样的目的,TreeSet 使用了 compareTo() 方法。如果 equals() 和 compareTo() 不一致,即如果 equals() 对两个相等的对象返回 true 但 compareTo() 返回零,则 Set 接口的约定将被破坏,允许在 TreeSet 等 Set 实现中重复。
以下是 TreeSet 优于 HashSet 的情况:
- 需要排序的唯一元素,而不是唯一元素。TreeSet 返回一个始终按升序排列的排序列表。
- TreeSet 的局部性高于 HashSet。如果两个条目按顺序靠近,TreeSet 将它们放在相同的数据结构中,因此放在内存中,但 HashSet 将条目分散在内存中,而不管它们链接到的键是什么。
- 为了对组件进行排序,TreeSet 采用了红黑树方法。如果您需要定期进行读/写操作,TreeSet 是一个很棒的解决方案。
11. 可以在 TreeSet 或 HashSet 中添加 null 元素吗?
我们可以在 HashSet 中添加 null 元素,但不能在 TreeSet 中添加 null 元素。原因是 TreeSet 使用 compareTo() 方法进行比较,当遇到空元素时会抛出 NullPointerException。
12. Java 中的优先级队列是什么?
如果要按优先级顺序处理对象,则使用 PriorityQueue。众所周知,队列遵循先进先出方法,但是,有时必须按优先级顺序处理队列的组件,这就是 PriorityQueue 发挥作用的地方。优先级堆是 PriorityQueue 的基础。优先级队列的成员根据自然顺序或队列构建时提供的比较器进行排序。
Serializable、Iterable<E>、Collection<E>、Queue<E> 接口由 Java 中的 PriorityQueue 类实现。
13. 使用 Java 集合时有哪些最佳实践?
以下是使用 Java 集合时的一些最佳实践:
- 选择合适的集合:
在我们使用集合之前,我们必须为我们正在寻求解决的问题选择最相关的集合。如果我们选错了,我们的程序可能仍然可以运行,但效率会很低。另一方面,如果我们选择了正确的,我们的解决方案会简单很多,我们的程序会运行得更快。 - 指定集合的初始容量:
几乎所有集合类都包含一个重载的构造函数,用于确定集合的初始容量。也就是说,如果我们确切地知道将要添加多少块到集合中,我们就可以在建立新实例时定义初始容量。 - 使用 isEmpty() 代替 size():
要检查集合是否为空,我们应该使用 isEmpty() 方法,而不是查找集合的大小并将其与零进行比较。这增强了代码的可读性。 - 使用迭代器遍历集合:
我们应该使用迭代器来遍历集合元素,而不是使用 for 循环。原因是如果任何其他线程在创建迭代器后尝试修改集合,迭代器可能会抛出 ConcurrentModificationException。这使我们免于错误。 - 在同步包装器上使用并发集合:
我们应该考虑在多线程应用程序中使用来自 java.util.concurrent 包的并发集合,而不是使用由 Collections.synchronizedXXX() 方法生成的同步集合。因为并发集合采用各种同步策略,例如写时复制、比较和交换和特定锁,所以它们旨在为并发应用程序提供最大性能。 - 消除未经检查的警告:
我们不应忽视来自 Java 编译器的未经检查的警告。理想的做法是摆脱任何未检查的警告。 - 偏爱泛型类型:
我们应该考虑使用泛型参数构建新方法,并将现有方法转换为使用类型参数,就像我们应该使用泛型类型一样,因为泛型方法比非泛型方法更安全、更容易使用。泛型方法还有助于创建通用且可重用的 API。
14. Java中Set和Map的区别。
Set接口由Java.util 包提供。集合接口是通过扩展集合接口建立的。我们不能向它添加相同的元素,因为它不允许我们这样做。因为它包含按排序顺序的元素,所以它不保持插入顺序。Java 中的 Set 接口用于构建数学 Set。
Map与 Set 类似,用于将对象集合存储为单个实体。键值对用于存储每个对象。因为每个值都与唯一的键相关联,所以我们可以仅使用键快速获取值。
set | map |
它不能有重复的值。无法将相同的元素添加到集合中。每个实现 Set 接口的类中只存储唯一值。 | 不同的键可能具有相同的值。该地图具有重复的唯一键和值。 |
使用 keyset() 和 entryset() 方法,我们可以快速迭代 Set 项。 | 无法遍历地图元素。要迭代元素,我们必须将 Map 转换为 Set。 |
Set 接口不跟踪插入顺序。但是,它的某些类(例如 LinkedHashSet)保持插入顺序。 | Map 不跟踪插入序列。一些 Map 类,例如 TreeMap 和 LinkedHashMap,做同样的事情。 |
15. HashSet和HashMap的区别。
HashSet是一个不允许重复值的 Set 接口实现。要点是存储在 HashSet 中的对象必须覆盖 equals() 和 hashCode() 方法,以确保没有重复值存储在我们的集合中。
HashMap是一种映射接口实现,将键映射到值。在地图中,不允许重复键。
image.png
HashSet | HashMap |
它实现了 Set 接口。 | 它实现了Map接口。 |
它不允许重复值。 | 键必须是唯一的,而两个不同的键可以具有相同的值。 |
添加元素时,它只需要一个对象作为参数。 | 添加条目时,它需要两个对象值,即Key和Value作为参数。 |
在内部,HashSet 使用 HashMap 来添加条目。HashSet 中的键 K 是 add(Object) 方法中提供的参数。对于 add(Object) 方法中提供的每个值,Java 分配一个虚拟值。 | 没有重复值的概念。 |
它比 HashMap 慢。 | 它比 HashSet 快。 |
它使用 add() 方法添加元素。 | 它使用 put() 方法添加数据元素。 |
16. 在基于散列的集合中负载因子的默认大小是多少?
默认负载因子大小为0.75。默认容量是通过将初始容量乘以负载系数来计算的。