Java中的集合

2025年5月20日 | 阅读 12 分钟

Java 中的集合是一个框架,它提供了一种存储和操作一组对象的架构。

Java 集合可以实现我们对数据进行的所有操作,例如搜索、排序、插入、操作和删除。

Java 集合表示对象的单一单元。Java 集合框架提供了许多接口(Set、List、Queue、Deque)和类(ArrayListVectorLinkedListPriorityQueueHashSetLinkedHashSetTreeSet)。

什么是集合?

集合代表一个单一的对象单元,即一个组。

什么是框架?

框架提供了一个现成的类和接口结构,用于高效构建软件应用程序。它通过提供执行类似任务的可重用组件来简化新功能的添加,无需为每个新项目从头开始创建框架。这种方法增强了面向对象的设计,使开发更快、更一致和更可靠。

  • 它提供现成的架构。
  • 它代表一组类和接口。
  • 它是可选的。

什么是集合框架?

集合框架代表了一个统一的架构,用于存储和操作一组对象。它通过提供各种数据结构(包括数组、链表、树和哈希表)来提高代码效率和可读性,以适应不同的编程需求。它有

  1. 接口及其实现,即类
  2. 算法

为什么需要集合框架?

在 JDK 1.2 中引入集合框架之前,Java 处理集合的方法是使用数组、向量和哈希表,它们缺乏一个共同的接口。这意味着每种类型的集合都有自己的一套方法、语法和构造函数,它们之间没有标准化或关联。

这使得用户难以记住每种集合类型不同的功能,并阻碍了代码的一致性和可重用性。这些集合之间不同的性质凸显了需要一个统一的集合框架来简化和标准化 Java 中的集合操作。

Java 集合框架的优势

Java 集合框架提供了显著的优势,可以提高开发实践、代码质量和应用程序性能

  1. 可重用性: 框架提供了一套全面的常用类和实用方法,适用于各种类型的集合。此功能促进了代码重用,使开发人员无需为常用操作编写重复代码。
  2. 质量: 利用 Java 集合框架可以提高程序的质量。框架中的组件经过了广泛测试,并被广大开发人员社区广泛使用,从而确保了应用程序的可靠性和稳定性。
  3. 速度: 开发人员经常报告使用集合框架时开发速度的提高。它允许他们专注于应用程序的核心业务逻辑,而不是实现通用集合功能,从而加快了开发过程。
  4. 维护: Java 集合框架的开源性质,加上随时可用的 API 文档,使得代码维护更加容易。使用框架编写的代码可以很容易地被其他开发人员理解和接管,确保了连续性和易于维护。
  5. 减少设计新 API 的工作量: 另一个好处是减少了 API 设计者和实现者为每个新 API 创建新集合机制的必要性。他们可以转而依赖框架提供的标准集合接口,从而简化 API 开发过程并确保 Java 应用程序之间的一致性。

集合框架的层次结构

让我们看看集合框架的层次结构。java.util 包包含集合框架的所有接口

Java 集合框架围绕着关键接口——Collection、List、Set、Queue 和 Map——构建。每个接口都针对特定的数据管理任务进行了定制。ArrayList、HashSet 和 HashMap 等实现提供了处理这些集合的实用解决方案,为 Java 开发人员提供了一套多功能工具,可用于高效数据处理。

Hierarchy of Java Collection framework
  • 类: 类是创建单个对象的蓝图。它通过字段(属性)封装对象的数据,并通过方法定义行为。类支持继承,允许一个类继承另一个类的属性和方法,从而促进代码重用和多态性。
  • 接口: 接口是 Java 中的一种引用类型,可以包含常量和抽象方法(没有方法体的方法)。接口指定了类必须做什么,但未指定如何做,从而强制类必须实现一组方法。接口用于在 Java 中实现抽象和多重继承。

Collection 接口的方法

Collection 接口中声明了许多方法。Java 中的 Collection 接口提供了处理对象组的基本方法,例如添加、删除和遍历每个元素。它们如下:

方法描述

public boolean add(E e)

用于在此集合中插入一个元素。

public boolean addAll(Collection<? extends E> c)

用于将指定的集合元素插入到调用的集合中。

public boolean remove(Object element)

用于从集合中删除一个元素。

public boolean removeAll(Collection<?> c)

用于从调用的集合中删除指定集合的所有元素。

default boolean removeIf(Predicate<? super E> filter)

用于删除集合中满足指定谓词的所有元素。

public boolean retainAll(Collection<?> c)

用于删除调用的集合中除指定集合外的所有元素。

public int size()

返回集合中元素的总数。

public void clear()

从集合中删除所有元素。

public boolean contains(Object element)

用于搜索一个元素。

public boolean containsAll(Collection<?> c)

用于在集合中搜索指定的集合。

public Iterator iterator()

返回一个迭代器。

public Object[] toArray()

将集合转换为数组。

public <T> T[] toArray(T[] a)

将集合转换为数组。这里,返回数组的运行时类型是指定数组的类型。

public boolean isEmpty()

检查集合是否为空。

default Stream<E> parallelStream()

返回一个可能并行的 Stream,以集合作为其源。

default Stream<E> stream()

返回一个顺序 Stream,以集合作为其源。

default Spliterator<E> spliterator()

生成一个遍历集合中指定元素的 Spliterator

public boolean equals(Object element)

比较两个集合。

public int hashCode()

返回集合的哈希码。

Iterator 接口

Iterator 接口提供仅向前迭代元素的功能。

Iterator 接口的方法

Iterator 接口中只有三个方法。它们是:

方法描述
public boolean hasNext()如果迭代器有更多元素,则返回 true;否则返回 false。
public Object next()返回元素并将光标指针移动到下一个元素。
public void remove()删除迭代器返回的最后一个元素。它使用较少。

Iterable 接口

Iterable 接口是所有集合类的根接口。Collection 接口扩展了 Iterable 接口,因此,Collection 接口的所有子类也实现了 Iterable 接口。

它只包含一个抽象方法。即,

返回类型为 T 的元素的迭代器。

Collection 接口

Collection 接口是集合框架中所有类都实现的接口。它声明了每个集合都将拥有的方法。换句话说,我们可以说 Collection 接口构建了集合框架所依赖的基础。

Collection 接口的一些方法是 Boolean add (Object obj)、Boolean addAll (Collection c)、void clear() 等,它们由 Collection 接口的所有子类实现。

了解更多:Java 集合接口

List 接口

List 接口是 Collection 接口的子接口。它具有列表类型的数据结构,我们可以在其中存储对象的有序集合。它可以有重复值。List 接口由 ArrayList、LinkedList、Vector 和 Stack 类实现。要实例化 List 接口,我们必须使用

List 接口中的各种方法可用于从列表中插入、删除和访问元素。实现 List 接口的类如下所示:

  • ArrayList
  • LinkedList
  • Vector
  • Stack

了解更多:Java List 接口

ArrayList

ArrayList 类实现了 List 接口。它使用动态数组来存储不同数据类型的重复元素。ArrayList 类维护插入顺序并且是非同步的。存储在 ArrayList 类中的元素可以随机访问。考虑以下示例。

了解更多:Java ArrayList

ArrayList 示例

示例

编译并运行

输出

John
Peter
Lucy
Johnson

LinkedList

LinkedList 实现了 Collection 接口。它在内部使用双向链表来存储元素。它可以存储重复元素。它维护插入顺序并且不同步。在 LinkedList 中,操作很快,因为不需要移位。考虑以下示例。

了解更多:Java LinkedList

LinkedList 示例

示例

编译并运行

输出

Lucy
Peter
Lucy
John

Vector

Vector 使用动态数组来存储数据元素。它与 ArrayList 相似。但是,它是同步的,并且包含许多不属于集合框架的方法。考虑以下示例。

了解更多:Java Vector

示例

编译并运行

输出

Apple
Banana
Orange
Plum

Stack

Stack 是 Vector 的子类。它实现了后进先出的数据结构,即堆栈。堆栈包含 Vector 类的所有方法,还提供自己的方法,如 boolean push()、boolean peek()、boolean push(object o),这些方法定义了它的属性。考虑以下示例。

了解更多:Java Stack 类

示例

编译并运行

输出

CPU
Monitor
Mouse
Keyboard

Queue 接口

队列接口维护先进先出的顺序。它可以定义为一个有序列表,用于保存即将处理的元素。有各种类,如 PriorityQueue、Deque 和 ArrayDeque,它们实现了 Queue 接口。

Queue 接口可以实例化为

各种类实现了 Queue 接口;其中一些如下所示

  • PriorityQueue
  • Deque
  • ArrayDeque

PriorityQueue

PriorityQueue 类实现了 Queue 接口。它根据元素的优先级存储要处理的元素或对象。PriorityQueue 不允许在队列中存储 null 值。考虑以下示例。

了解更多:Java Stack 类

PriorityQueue 示例

示例

编译并运行

输出

head:Alice
head:Alice
iterating the queue elements:
Alice
Daniel
Jones
Smith
after removing two elements:
Jones
Smith

Deque 接口

Deque 接口扩展了 Queue 接口。在 Deque 中,我们可以从两端删除和添加元素。Deque 代表双端队列,它使我们能够从两端执行操作。

Deque 可以实例化为

ArrayDeque

ArrayDeque 类实现了 Deque 接口。它方便我们使用 Deque。与队列不同,我们可以从两端添加或删除元素。ArrayDeque 比 ArrayList 和 Stack 更快,并且没有容量限制。考虑以下示例。

了解更多:Java Deque 接口

ArrayDeque 示例

示例

编译并运行

输出

Lucy
Andrew
Henery

Set 接口

Java 中的 Set 接口存在于 java.util 包中。它扩展了 Collection 接口。它代表元素的无序集合,不允许我们存储重复项。我们最多可以在 Set 中存储一个 null 值。HashSet、LinkedHashSet 和 TreeSet 实现了 Set。Set 可以实例化为

HashSet

HashSet 类实现了 Set 接口。它表示使用哈希表进行存储的集合。哈希用于在 HashSet 中存储元素。它包含唯一的项。考虑以下示例。

了解更多:Java HashSet

示例

编译并运行

输出

Johnson
Andrew
Mark
Peter

LinkedHashSet

LinkedHashSet 类表示 Set 接口的 LinkedList 实现。它扩展了 HashSet 类并实现了 Set 接口。与 HashSet 一样,它也包含唯一元素。它维护插入顺序并允许 null 元素。考虑以下示例。

了解更多:Java LinkedHashSet 类

示例

编译并运行

输出

Peter
Jack
Johnson

SortedSet 接口

SortedSet 是 Set 接口的替代方案,它提供了对其元素的总排序。SortedSet 的元素按升序排列。SortedSet 提供了额外的抑制组件自然排序的方法。

SortedSet 可以实例化为

了解更多:Java SortedSet 接口

TreeSet

Java TreeSet 类实现了 Set 接口,它使用树进行存储。与 HashSet 一样,TreeSet 也包含唯一元素。但是,TreeSet 的访问和检索时间相当快。TreeSet 中的方面按升序存储。考虑以下示例。

了解更多:Java TreeSet 类

示例

编译并运行

输出

Davis
Donald
Thomas

Map 接口

Java 中的 Map 接口是 Java 集合框架的一部分。它表示一组键及其对应值之间的映射。Map 不能包含重复的键;每个键最多可以映射到一个值。Map 接口用于存储键值对,其中每个键都是唯一的,它提供了一种基于键检索、更新和操作数据的高效方法。

语法

了解更多:Java Map 接口

HashMap

Java 中的 HashMap 是一种键值数据结构,通过哈希使用键提供高效的数据访问。哈希将大字符串或其他对象转换为较小的、一致的值,以便快速索引和搜索。HashMap 实现了 Map 接口,用于高效管理大型数据集。此外,HashSet 内部使用 HashMap 来唯一地存储元素,展示了哈希在 Java 集合框架中用于快速数据检索和管理的实用性。

了解更多:Java HashMap

示例

编译并运行

输出

Value for 'Alice': 10Bob: 20
Alice: 10
Charlie: 30
Map contains key 'Bob'.

Java 集合 MCQ

1. 您将使用哪种方法在 List 的特定位置插入元素?

  1. add()
  2. addAt()
  3. insert()
  4. addElement()
 

答案:a)

解释: add(int index, E element) 方法用于在 List 的特定位置插入元素。


2. HashSet 中 contains 方法的时间复杂度是多少?

  1. O(1)
  2. O(log n)
  3. O(n)
  4. O(n^2)
 

答案:a)

解释: 由于其底层的哈希表结构,HashSet 中 contains 方法的时间复杂度为 O(1)。


3. HashMap 和 TreeMap 之间的主要区别是什么?

  1. HashMap 是同步的,TreeMap 不是
  2. HashMap 维护元素的顺序,TreeMap 不维护
  3. HashMap 允许 null 键,TreeMap 不允许
  4. TreeMap 排序键,HashMap 不排序
 

答案:d)

解释: TreeMap 以自然顺序或由指定的比较器对键进行排序,而 HashMap 不维护任何顺序。


4. 除了 Set,LinkedHashSet 还实现了哪个接口?

  1. 列表
  2. Map
  3. SortedSet
  4. 集合
 

答案:d)

解释: LinkedHashSet 实现了 Set 接口,该接口扩展了 Collection。


5. 如果尝试向 TreeSet 添加重复元素会发生什么?

  1. 添加重复元素
  2. 现有元素被替换
  3. TreeSet 抛出异常
  4. 重复元素被忽略
 

答案:d)

解释: 在 TreeSet 中,重复元素被忽略并且不会被添加。


下一个主题Java ArrayList