Java 集合全教程

news2024/10/5 13:56:09

一、集合简介

集合(有时称为容器)只是将多个元素分组到单个单元中的对象。集合用于存储、检索、操作和传达聚合数据。通常,它们表示形成自然组的数据项,例如扑克手(纸牌集合)、邮件文件夹(字母集合)或电话簿(名称到电话号码的映射)。如果您使用过 Java 编程语言(或者几乎任何其他编程语言),那么您已经熟悉集合。

1、什么是集合框架?

集合框架是用于表示和操作集合的统一体系结构。所有集合框架都包含以下内容:

  • 接口:这些是表示集合的抽象数据类型。接口允许独立于其表示形式的细节操作集合。在面向对象的语言中,接口通常形成层次结构。
  • 实现:这些是集合接口的具体实现。从本质上讲,它们是可重用的数据结构。
  • 算法:这些是对实现集合接口的对象执行有用计算(如搜索和排序)的方法。这些算法被称为多态的:也就是说,相同的方法可以用于相应集合接口的许多不同实现。从本质上讲,算法是可重用的功能。

除了Java集合框架之外,最著名的集合框架示例是C++标准模板库(STL)和Smalltalk的集合层次结构。从历史上看,集合框架一直非常复杂,这使它们以具有陡峭的学习曲线而闻名。我们相信 Java 集合框架打破了这一传统,您将在本章中亲自学习。

2、Java 集合框架的优势

Java 集合框架具有以下优点:

  • 减少编程工作量:通过提供有用的数据结构和算法,集合框架使您可以专注于程序的重要部分,而不是使其工作所需的低级“管道”。通过促进不相关的 API 之间的互操作性,Java 集合框架使您无需编写适配器对象或转换代码来连接 API。
  • 提高程序速度和质量:此集合框架提供了有用数据结构和算法的高性能、高质量实现。每个接口的各种实现是可互换的,因此可以通过切换集合实现轻松调整程序。因为您摆脱了编写自己的数据结构的苦差事,所以您将有更多时间致力于提高程序的质量和性能。
  • 允许不相关的 API 之间的互操作性:集合接口是 API 来回传递集合的方言。如果我的网络管理 API 提供节点名称的集合,并且您的 GUI 工具包需要列标题的集合,则我们的 API 将无缝互操作,即使它们是独立编写的。
  • 减少学习和使用新 API 的工作量:许多 API 自然地将集合作为输出提供。过去,每个这样的 API 都有一个专门用于操作其集合的小型子 API。这些临时集合子 API 之间几乎没有一致性,因此您必须从头开始学习每个子 API,并且在使用它们时很容易出错。随着标准集合接口的出现,问题消失了。
  • 减少设计新 API 的工作量:这是先前优势的另一面。设计人员和实现者不必在每次创建依赖于集合的 API 时都重新发明轮子;相反,它们可以使用标准集合接口。
  • 促进软件重用:符合标准集合接口的新数据结构本质上是可重用的。对实现这些接口的对象进行操作的新算法也是如此。

二、接口

核心集合接口封装了不同类型的集合,如下图所示。这些接口允许独立于其表示形式的细节操作集合。核心集合接口是 Java 集合框架的基础。如下图所示,核心集合接口形成层次结构。

集合是一种特殊的集合,SortedSet是一种特别的集合,依此类推。还要注意,层次结构由两个不同的树组成——Map不是真正的Collection。
请注意,所有核心集合接口都是通用的。例如,这是Collection接口的声明。

public interface Collection<E>...
<E>语法告诉接口是通用的。当您声明集合实例时,您可以并且应该指定集合中包含的对象的类型。通过指定类型,编译器可以(在编译时)验证放入集合中的对象的类型是否正确,从而减少运行时的错误。

当您了解如何使用这些接口时,您将了解关于Java Collections Framework的大部分内容。本章讨论了有效使用接口的一般准则,包括何时使用哪个接口。您还将学习每个接口的编程习惯用法,以帮助您充分利用它。
为了保持核心集合接口的数量可管理,Java平台没有为每个集合类型的每个变体提供单独的接口。(这样的变体可能包括不可变、固定大小和仅追加。)相反,每个接口中的修改操作都被指定为可选的——给定的实现可能会选择不支持所有操作。如果调用了不支持的操作,则集合将抛出UnsupportedOperationException。实施负责记录他们支持的可选操作。Java平台的所有通用实现都支持所有可选操作。
以下列表介绍了核心集合接口:

  • 集合-集合层次结构的根。集合表示一组称为其元素的对象。Collection接口是所有集合实现的最基本的接口,用于传递集合,并在需要最大通用性时对其进行操作。某些类型的集合允许重复元素,而另一些则不允许。有些是有序的,有些是无序的。Java平台不提供该接口的任何直接实现,但提供了更具体的子接口的实现,如Set和List。
  • 集合-不能包含重复元素的集合。该接口对数学集合抽象进行建模,并用于表示集合,例如组成扑克手的卡片、组成学生时间表的课程或机器上运行的过程。另请参见“设置接口”部分。
  • 列表-有序集合(有时称为序列)。列表可以包含重复的元素。列表的用户通常可以精确控制每个元素在列表中的插入位置,并可以通过其整数索引(位置)访问元素。如果您使用过Vector,那么您就熟悉List的一般风格。另请参阅“列表接口”部分。队列-用于在处理之前容纳多个元素的集合。除了基本的“收集”操作外,“队列”还提供其他插入、提取和检查操作。队列通常(但不一定)以FIFO(先进先出)方式对元素进行排序。例外情况包括优先级队列,它根据提供的比较器或元素的自然排序对元素进行排序。无论使用何种排序,队列的头都是将通过调用remove或poll来移除的元素。在FIFO队列中,所有新元素都插入到队列的尾部。其他类型的队列可以使用不同的放置规则。每个队列实现都必须指定其排序属性。另请参阅队列接口部分。
  • Deque-在处理之前用于容纳多个元素的集合。除了基本的“收集”操作外,Deque还提供额外的插入、提取和检查操作。
  • Deques既可以用作FIFO(先进先出)也可以用作LIFO(后进先出)。在deque中,所有新元素都可以在两端插入、检索和移除。另请参阅Deque接口部分。
  • 映射-将关键点映射到值的对象。映射不能包含重复的键;每个键最多可以映射到一个值。如果您使用过Hashtable,那么您已经熟悉了Map的基本知识。

最后两个核心集合接口只是Set和Map的排序版本:

  • SortedSet-一个按升序维护其元素的集合。提供了几个额外的操作来利用订购。排序集用于自然排序集,例如单词列表和成员名册。另请参阅“排序集接口”部分。
  • SortedMap-一个按升序维护映射的Map。这是SortedSet的Map模拟。排序映射用于键/值对的自然排序集合,例如字典和电话簿。另请参阅“已排序映射接口”部分。

三、集合接口

集合表示一组称为其元素的对象。Collection接口用于传递需要最大通用性的对象集合。例如,按照惯例,所有通用集合实现都有一个接受collection参数的构造函数。此构造函数被称为转换构造函数,它初始化新集合以包含指定集合中的所有元素,无论给定集合的子接口或实现类型如何。换句话说,它允许您转换集合的类型。
例如,假设您有一个Collection<String>c,它可能是List、Set或其他类型的Collection。这个习惯用法创建了一个新的ArrayList(List接口的实现),最初包含c中的所有元素。

List<String> list = new ArrayList<String>(c);

Collection接口包含执行基本操作的方法,如int size()、boolean isEmpty()、boolean  contains(Object  element)、boolean add(E element)、boolean remove(Object element)和Iterator<E>Iterator()。
它还包含对整个集合进行操作的方法,如boolean containsAll(Collection<?>c)、boolean addAll(Collection<±extends E>c)、boolean removeAll(Collection>?>c(Collection<?>c))、boole retanall(Collection<>c)和void clear()。
数组操作的其他方法(如Object[] toArray() and <T> T[] toArray(T[] a))也存在。
在JDK8及更高版本中,Collection接口还公开了Stream<E>Stream()和 Stream<E> parallelStream() 方法,用于从底层集合中获取顺序或并行流。(有关使用流的更多信息,请参阅题为“聚合操作”的课程。)
Collection接口实现了您所期望的功能,因为Collection表示一组对象。它有告诉您集合中有多少元素的方法(size,isEmpty),检查给定对象是否在集合中的方法(contains),向集合中添加和移除元素的方法,以及在集合上提供迭代器的方法(迭代器)。
add方法定义得足够一般,因此它对允许重复的集合和不允许重复的集都有意义。它保证在调用完成后Collection将包含指定的元素,如果Collection因调用而更改,则返回true。类似地,remove方法被设计为从Collection中删除指定元素的单个实例,假设它包含要开始的元素,并且如果Collection因此被修改,则返回true。

1、 遍历集合

遍历集合有三种方法:(1)使用聚合运算(2)使用for每个构造;(3)使用Iterator。

1.1 聚合操作

在JDK8及更高版本中,迭代集合的首选方法是获得流并对其执行聚合操作。聚合操作通常与lambda表达式一起使用,以使编程更具表达性,使用更少的代码行。以下代码依次遍历一组形状并打印出红色对象:

myShapesCollection.stream()
.filter(e -> e.getColor() == Color.RED)
.forEach(e -> System.out.println(e.getName()));

同样,您可以很容易地请求并行流,如果集合足够大并且您的计算机有足够的计算能力,这可能是有意义的:

myShapesCollection.parallelStream()
.filter(e -> e.getColor() == Color.RED)
.forEach(e -> System.out.println(e.getName()));

使用此API有许多不同的数据收集方法。例如,您可能希望将Collection的元素转换为String对象,然后将它们连接起来,用逗号分隔:

 String joined = elements.stream()
    .map(Object::toString)
    .collect(Collectors.joining(", "));

或者也许将所有员工的工资相加:

int total = employees.stream()
.collect(Collectors.summingInt(Employee::getSalary)));

1.2 for-each

for each构造允许您使用for循环简明地遍历集合或数组。以下代码使用for each构造在单独的一行上打印出集合的每个元素:

for (Object o : collection)
    System.out.println(o);

1.2 Iterators

迭代器是一个对象,使您能够遍历集合,并根据需要选择性地从集合中删除元素。通过调用集合的迭代器方法,可以获得该集合的一个迭代器。以下是Iterator接口:

public interface Iterator<E> {
    boolean hasNext();
    E next();
    void remove(); //optional
}

如果迭代有更多的元素,那么hasNext方法返回true,next方法返回迭代中的下一个元素。remove方法从基础集合中移除next返回的最后一个元素。remove方法每次调用next只能调用一次,如果违反此规则,就会抛出异常。
请注意,Iterator.remove是在迭代过程中修改集合的唯一安全方法;如果在迭代过程中以任何其他方式修改了基础集合,则行为是未指定的。
当需要执行以下操作时,请使用迭代器而不是用于每个构造:

  • 删除当前元素。for each构造隐藏迭代器,因此不能调用remove。因此,for each构造不可用于过滤。
  • 并行遍历多个集合。

下面的方法向您展示了如何使用迭代器来筛选任意集合——也就是说,遍历集合以删除特定元素:

static void filter(Collection<?> c) {
    for (Iterator<?> it = c.iterator(); it.hasNext(); )
        if (!cond(it.next()))
            it.remove();
}


这段简单的代码是多态的,这意味着无论实现如何,它都适用于任何Collection。这个例子展示了使用Java集合框架编写多态算法是多么容易。

2、集合接口批量操作

批量操作对整个集合执行操作。您可以使用基本操作来实现这些简写操作,尽管在大多数情况下,这样的实现效率较低。以下是批量操作:

  • containsAll-如果目标集合包含指定集合中的所有元素,则返回true。
  • addAll-将指定集合中的所有元素添加到目标集合中。
  • removeAll-从目标集合中删除指定集合中包含的所有元素。
  • retainAll-从目标集合中删除指定集合中未包含的所有元素。也就是说,它只保留目标集合中也包含在指定集合中的那些元素。
  • clear-从集合中删除所有元素。

如果在执行操作的过程中修改了目标Collection,那么addAll、removeAll和retainAll方法都返回true。
作为批量操作能力的一个简单示例,请考虑以下习语,从Collection,c中删除指定元素e的所有实例。

c.removeAll(Collections.singleton(e));

更具体地说,假设您想从集合中删除所有null元素。

c.removeAll(Collections.singleton(null));

这个习惯用法使用Collections.singleton,这是一个静态工厂方法,返回一个只包含指定元素的不可变Set。

3、集合接口数组操作

toArray方法是作为集合和旧API之间的桥梁提供的,旧API期望在输入时使用数组。数组操作允许将集合的内容转换为数组。不带参数的简单表单会创建一个新的Object数组。更复杂的形式允许调用方提供数组或选择输出数组的运行时类型。
例如,假设c是一个集合。下面的代码段将c的内容转储到新分配的Object数组中,该数组的长度与c中的元素数相同。

Object[] a = c.toArray();

假设已知c只包含字符串(可能是因为c的类型为Collection<String>)。下面的代码段将c的内容转储到新分配的String数组中,该数组的长度与c中的元素数量相同。

String[] a = c.toArray(new String[0]);

Java 集合全教程—Set 接口_Doker 多克的博客-CSDN博客

📢文章下方有交流学习区!一起学习进步!也可以前往官网,加入官方微信交流群💪💪💪
📢首发CSDN博客,创作不易,如果觉得文章不错,可以点赞👍收藏📁评论📒
📢你的支持和鼓励是我创作的动力❗❗❗ 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/618365.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Java多线程进阶】synchronized工作原理

前言 本期讲解 synchronized 工作的原理以及常见的锁优化机制&#xff0c;相信大家在看完这篇博文后对 synchronized 工作流程有一定的理解。话不多说&#xff0c;让我们快速进入学习吧~ 目录 1. 锁的工作流程 2. 偏向锁 3. 轻量级锁和重量级锁 3.1 轻量级锁 3.2 重量级锁…

Kubernetes基本存储

Kubernetes基本存储 容器的生命周期可能很短&#xff0c;会被频繁地创建和销毁&#xff0c;容器销毁时&#xff0c;保存在容器中的数据也会被清除。为了持久化保存容器中数据&#xff0c;引入Volume概念。 Volume时Pod中多个容器共同访问的共享目录&#xff0c;它被定义在Pod中…

“碳”寻青蓝锦色,锦江酒店(中国区)用行动点亮酒店可持续发展

第52个世界环境日之际&#xff0c;为响应“减塑捡塑”号召&#xff0c;锦江酒店&#xff08;中国区&#xff09;以“‘碳’寻青蓝锦色”为主题&#xff0c;在6月5日至6月11日期间&#xff0c;开启第二届“绿色生活创益周”&#xff0c;通过线上线下联动&#xff0c;倡导时尚低碳…

2023智源大会议程公开丨类脑计算论坛

6月9日&#xff0c;2023北京智源大会&#xff0c;将邀请这一领域的探索者、实践者、以及关心智能科学的每个人&#xff0c;共同拉开未来舞台的帷幕&#xff0c;你准备好了吗&#xff1f;与会知名嘉宾包括&#xff0c;图灵奖得主Yann LeCun、图灵奖得主Geoffrey Hinton、OpenAI创…

Mocha AE:Clip 模块

Clip&#xff08;剪辑&#xff09;模块主要用于对素材或遮罩文件的格式进行查看或设置&#xff0c;包括视频格式、时间码格式、色彩空间等&#xff0c;还可以进行裁剪。 General 常规 Input 输入 当前图层素材。 Matte for Layer n 图层 n 的遮罩 Name 名称 显示素材的名称。 …

通信大史记:互联网的起源故事

点击文末“阅读原文”即可参与节目互动 剪辑、音频 / 卷圈 运营 / SandLiu 卷圈 监制 / 姝琦 文案 / 朱峰 产品统筹 / bobo 这是一期“两年更”的节目&#xff0c;通信大史记录完第一期后&#xff0c;因为资料准备和主播时间的关系一直没有后续更新。今天&#xff0c;我们…

nodejs的path模块

path路径模块 path模块是Node.js官方提供的&#xff0c;用来处理路径的模块。提供一系列的方法和属性&#xff0c;用来满足用户对路径的处理需求。 例如&#xff1a; 如果在js代码中&#xff0c;使用path模块来处理路径&#xff0c;需要先导入 const pathrequire(path)常用的…

chatgpt赋能python:Python如何调成白色的SEO文章

Python 如何调成白色的 SEO 文章 介绍 Python 是一种流行的编程语言&#xff0c;在数据分析、人工智能、Web 开发以及其他许多领域都有广泛的应用。然而&#xff0c;很少有人会把 Python 与 SEO 联系起来。 事实上&#xff0c;Python 是一个强大的工具&#xff0c;可以帮助 …

软件工程师,学会封装不香么

什么是封装 从面向对象编程的角度来说&#xff0c;封装是指利用抽象数据类型将数据和基于数据的操作封装在一起&#xff0c;使其构成一个不可分割的独立实体&#xff0c;数据被保护在抽象数据类型的内部&#xff0c;尽可能地隐藏内部的细节&#xff0c;只保留一些对外接口使之与…

rk3568 TF卡启动

rk3568 SD卡启动 SD卡启动系统&#xff0c;它可以让rk3568在没有硬盘或其他存储设备的情况下启动和运行操作系统。这使得rk3568变得与树梅派一样灵活切换系统&#xff0c;与此同时进行故障排查和修复&#xff0c;而不需要拆卸设备或者使用专业的烧录工具。SD卡启动还可以方便地…

音视频同步的方法:深入探索基于FFmpeg的音视频同步策略

音视频同步艺术&#xff1a;深入探索基于FFmpeg的同步策略 &#xff08;一&#xff09;音视频同步的基本概念与重要性&#xff08;Basic Concepts and Importance of Audio-Video Synchronization&#xff09;1.1 音视频同步的定义与影响&#xff08;Definition and Impact of …

【SQL】Oracle数据库实现远程访问

文章目录 前言1. 数据库搭建2. 内网穿透2.1 安装cpolar内网穿透2.2 创建隧道映射 3. 公网远程访问4. 配置固定TCP端口地址4.1 保留一个固定的公网TCP端口地址4.2 配置固定公网TCP端口地址4.3 测试使用固定TCP端口地址远程Oracle 前言 Oracle&#xff0c;是甲骨文公司的一款关系…

【Python入门】Python循环语句(for循环的基础语法)

前言 Python循环语句 1. for循环的基础语法1.1 for循环1.2 程序中的for循环1.3 for循环语句1.4 for循环注意点1.5 总结1.6 练习案例&#xff1a;数一数有几个a 2. range语句2.1 range语句讲解2.2 for循环遍历range序列2.3 总结2.4 练习案例&#xff1a;有几个偶数 3. 变量作用域…

RFID软件:简介、功能和应用范围

在当今快节奏的商业环境中&#xff0c;RFID&#xff08;射频识别&#xff09;技术已经成为物流、供应链和库存管理等领域中不可或缺的工具。本文将向您介绍RFID软件的基本知识&#xff0c;探讨其功能和广泛应用的范围。 第一部分&#xff1a;RFID软件简介 RFID软件是一种应用…

【开源项目】SofaBoot实现Spring Bean 异步初始化的源码拆解

使用场景 在实际使用 Spring/Spring Boot 开发中&#xff0c;一些 Bean 在初始化过程中执行准备操作&#xff0c;如拉取远程配置、初始化数据源等等。在应用启动期间&#xff0c;这些 Bean 会增加 Spring 上下文刷新时间&#xff0c;导致应用启动耗时变长。 Demo展示 Spring…

苹果 Apple 发布的 AR 头显 Vision Pro 介绍

苹果今天凌晨的发布会&#xff0c;隆重推出了用了8 年时间研发的AR&#xff08;增强现实&#xff09;头戴显示器 Vision Pro。作为苹果 AR系列的最新成员&#xff0c;为用户带来了前所未有的沉浸式增强现实体验。 硬件 12个摄像头 &#xff0c;包括苹果首个 3D 相机&#xff0c…

【容器云架构】Calico 组件架构

Calico 组件 下图显示了 Kubernetes 的必需和可选 Calico 组件&#xff0c;具有网络和网络策略的本地部署。 Calico 组件 Calico API serverFelixBIRDconfdDikastesCNI pluginDatastore pluginIPAM pluginkube-controllersTyphacalicoctl 云编排器的插件 Plugins for cloud orc…

【vulnhub靶场】node 1

文章目录 前言开启靶机信息收集二层发现三层信息收集 攻击利用web信息收集权限提升后渗透 前言 描述&#xff1a;Node是一个中等级别的boot2root挑战&#xff0c;最初是为HackTheBox创建的。有两个标志可供查找&#xff08;用户和根标志&#xff09;和多种不同的技术可供使用。…

IDEA启动图片更改替换(2021.1/2022及其之后的版本)

目录 先说2022.1及其之后的版本: 2022.1之前的版本: 2022其他版本修改方法 最近一直在整理接口数据&#xff0c;盯屏幕太久了&#xff0c;然后打开IDEA突然感觉这个启动页面好刺眼&#xff0c;正好整理工作做完了&#xff0c;中午有空就找了下方法,发现了不少坑&#xff0c;…

项目管理中,如何减少项目风险?

我们公司&#xff0c;有一个项目已经做了一年多了&#xff0c;并且与客户进行了多次沟通&#xff0c;项目需求变更&#xff0c;范围扩大等&#xff0c;项目一直不能完成&#xff0c;客户生气&#xff0c;领导一直催&#xff0c;决定换一个项目经理把&#xff0c;领导让一个同事…