Collections 工具类

在 Java 编程中,集合(Collections)是处理数据的核心工具之一。为了简化集合操作并提高代码的可读性和可维护性,JDK 提供了一个强大的工具类:java.util.Collections。这个类包含了一系列静态方法,用于对集合进行各种操作,如排序、查找、同步控制、创建不可变集合等。

1 引入 Collections 类

Collections 类位于 java.util 包中,因此在使用之前需要导入:

import java.util.Collections;

2 排序操作

Collections 类提供了多种排序方法,可以对集合进行反转、洗牌、自然排序和自定义排序等操作。

  • reverse(List list):反转集合中元素的顺序。
  • shuffle(List list):随机打乱集合中元素的顺序。
  • sort(List list):对集合进行自然升序排序。
  • sort(List list, Comparator c):根据自定义比较器对集合进行排序。
  • swap(List list, int i, int j):交换集合中指定位置的两个元素。

示例代码

List<String> list = new ArrayList<>();
list.add("沉默王二");
list.add("沉默王三");
list.add("沉默王四");
list.add("沉默王五");
list.add("沉默王六");

System.out.println("原始顺序:" + list);

// 反转
Collections.reverse(list);
System.out.println("反转后:" + list);

// 洗牌
Collections.shuffle(list);
System.out.println("洗牌后:" + list);

// 自然升序
Collections.sort(list);
System.out.println("自然升序后:" + list);

// 交换
Collections.swap(list, 2, 4);
System.out.println("交换后:" + list);

输出结果

原始顺序:[沉默王二, 沉默王三, 沉默王四, 沉默王五, 沉默王六]
反转后:[沉默王六, 沉默王五, 沉默王四, 沉默王三, 沉默王二]
洗牌后:[沉默王五, 沉默王二, 沉默王六, 沉默王三, 沉默王四]
自然升序后:[沉默王三, 沉默王二, 沉默王五, 沉默王六, 沉默王四]
交换后:[沉默王三, 沉默王二, 沉默王四, 沉默王六, 沉默王五]

3 查找操作

Collections 类提供了多种查找方法,可以用于查找集合中的最大值、最小值、元素出现的次数等。

  • binarySearch(List list, Object key):二分查找法,前提是集合已经排序。
  • max(Collection coll):返回集合中的最大元素。
  • max(Collection coll, Comparator comp):根据自定义比较器返回集合中的最大元素。
  • min(Collection coll):返回集合中的最小元素。
  • min(Collection coll, Comparator comp):根据自定义比较器返回集合中的最小元素。
  • fill(List list, Object obj):使用指定对象填充集合。
  • frequency(Collection c, Object o):返回指定对象在集合中出现的次数。

示例代码:

System.out.println("最大元素:" + Collections.max(list));
System.out.println("最小元素:" + Collections.min(list));
System.out.println("出现的次数:" + Collections.frequency(list, "沉默王二"));

// 没有排序直接调用二分查找,结果是不确定的
System.out.println("排序前的二分查找结果:" + Collections.binarySearch(list, "沉默王二"));
Collections.sort(list);
// 排序后,查找结果和预期一致
System.out.println("排序后的二分查找结果:" + Collections.binarySearch(list, "沉默王二"));

Collections.fill(list, "沉默王八");
System.out.println("填充后的结果:" + list);

输出结果:

最大元素:沉默王四
最小元素:沉默王三
出现的次数:1
排序前的二分查找结果:0
排序后的二分查找结果:1
填充后的结果:[沉默王八, 沉默王八, 沉默王八, 沉默王八, 沉默王八]

4 同步控制

在多线程环境下,集合操作可能会引发线程安全问题。Collections 类提供了 synchronizedXxx 方法,用于返回一个同步的集合对象,从而避免线程安全问题。

示例代码:

SynchronizedList synchronizedList = Collections.synchronizedList(list);

SynchronizedList 的源码实现非常简单,只是在方法内部使用 synchronized 关键字加了一层锁。

static class SynchronizedList<E>
    extends SynchronizedCollection<E>
    implements List<E> {
    private static final long serialVersionUID = -7754090372962971524L;

    final List<E> list;

    SynchronizedList(List<E> list) {
        super(list); // 调用父类 SynchronizedCollection 的构造方法,传入 list
        this.list = list; // 初始化成员变量 list
    }

    // 获取指定索引处的元素
    public E get(int index) {
        synchronized (mutex) {return list.get(index);} // 加锁,调用 list 的 get 方法获取元素
    }
    
    // 在指定索引处插入指定元素
    public void add(int index, E element) {
        synchronized (mutex) {list.add(index, element);} // 加锁,调用 list 的 add 方法插入元素
    }
    
    // 移除指定索引处的元素
    public E remove(int index) {
        synchronized (mutex) {return list.remove(index);} // 加锁,调用 list 的 remove 方法移除元素
    }
}

那这样的话,其实效率和那些直接在方法上加 synchronized 关键字的 VectorHashtable 差不多(JDK 1.0 时期就有了),而这些集合类基本上已经废弃了,几乎不怎么用。

public class Vector<E>
    extends AbstractList<E>
    implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{

    // 获取指定索引处的元素
    public synchronized E get(int index) {
        if (index >= elementCount) // 如果索引超出了列表的大小,则抛出数组下标越界异常
            throw new ArrayIndexOutOfBoundsException(index);

        return elementData(index); // 返回指定索引处的元素
    }

    // 移除指定索引处的元素
    public synchronized E remove(int index) {
        modCount++; // 修改计数器,标识列表已被修改
        if (index >= elementCount) // 如果索引超出了列表的大小,则抛出数组下标越界异常
            throw new ArrayIndexOutOfBoundsException(index);
        E oldValue = elementData(index); // 获取指定索引处的元素

        int numMoved = elementCount - index - 1; // 计算需要移动的元素个数
        if (numMoved > 0) // 如果需要移动元素
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved); // 将数组中的元素向左移动一位
        elementData[--elementCount] = null; // 将最后一个元素设置为 null,等待垃圾回收

        return oldValue; // 返回被移除的元素
    }
}

正确的做法是使用并发包下的 CopyOnWriteArrayListConcurrentHashMap

5 不可变集合

Collections 类提供了多种方法来创建不可变集合,这些集合一旦创建,就无法进行修改操作。

  • emptyXxx():创建一个空的不可变集合。
  • singletonXxx():创建一个只包含一个元素的不可变集合。
  • unmodifiableXxx():为指定集合创建一个不可变视图。

示例代码:

List emptyList = Collections.emptyList();
emptyList.add("非空");  // 抛出 UnsupportedOperationException
System.out.println(emptyList);

输出结果:

Exception in thread "main" java.lang.UnsupportedOperationException
	at java.util.AbstractList.add(AbstractList.java:148)
	at java.util.AbstractList.add(AbstractList.java:108)
	at com.itwanger.s64.Demo.main(Demo.java:61)

6 其他操作

Collections 类还提供了一些其他常用的方法:

  • addAll(Collection<? super T> c, T... elements):将多个元素添加到集合中。
  • disjoint(Collection<?> c1, Collection<?> c2):判断两个集合是否没有交集。

示例代码:

List<String> allList = new ArrayList<>();
Collections.addAll(allList, "沉默王九", "沉默王十", "沉默王二");
System.out.println("addAll 后:" + allList);

System.out.println("是否没有交集:" + (Collections.disjoint(list, allList) ? "是" : "否"));

输出结果:

addAll 后:[沉默王九, 沉默王十, 沉默王二]
是否没有交集:否

7 CollectionUtils:Spring 和 Apache 的集合工具类

除了 JDK 提供的 Collections 工具类,Spring 和 Apache 也提供了各自的集合工具类,如 org.springframework.util.CollectionUtilsorg.apache.commons.collections.CollectionUtils

Apache 的 CollectionUtils 提供了更多实用的方法,如集合判空、集合操作(交集、并集、差集等)。

Maven 坐标:

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-collections4</artifactId>
    <version>4.4</version>
</dependency>

示例代码:

List<Integer> list = new ArrayList<>();
list.add(2);
list.add(1);
list.add(3);

List<Integer> list2 = new ArrayList<>();
list2.add(2);
list2.add(4);

// 获取并集
Collection<Integer> unionList = CollectionUtils.union(list, list2);
System.out.println(unionList);

// 获取交集
Collection<Integer> intersectionList = CollectionUtils.intersection(list, list2);
System.out.println(intersectionList);

// 获取交集的补集
Collection<Integer> disjunctionList = CollectionUtils.disjunction(list, list2);
System.out.println(disjunctionList);

// 获取差集
Collection<Integer> subtractList = CollectionUtils.subtract(list, list2);
System.out.println(subtractList);

输出结果:

[1, 2, 3, 4]
[2]
[1, 3, 4]
[1, 3]

8 小结

Collections 工具类作为集合框架的大管家,提供了丰富的静态方法,帮助开发者简化集合操作,提高代码的可读性和可维护性。掌握这些方法,可以显著提升编程效率,减少出错的可能性。

虽然 Collections 工具类非常强大,但更重要的是理解其背后的设计思想和实现原理。通过阅读源码,学习 JDK 设计者的编程技巧,可以进一步提升自己的编码水平。

在实际工作中,合理利用 Collections 工具类和第三方工具类(如 Apache 的 CollectionUtils),可以大大简化集合操作,提高代码质量。

9 思维导图

在这里插入图片描述

10 参考链接

Java Collections:专为集合框架而生的工具类

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Nginx在Windows上和Linux上(Docker启动)分别配置基本身份认证示例

场景 Nginx代理的资源或网站等&#xff0c;url直接暴露有风险&#xff0c;需要添加身份认证&#xff0c;即输入用户名密码后才能成功访问。 注&#xff1a; 博客&#xff1a;霸道流氓气质-CSDN博客 实现 Windows上配置Nginx实现基本身份认证 修改nginx的配置文件 添加基…

K8S之Prometheus 部署(二十)

部署方式&#xff1a;https://github.com/kubernetes/kubernetes/tree/master/cluster/addons/prometheus 源码目录&#xff1a;kubernetes/cluster/addons/prometheus 服务发现&#xff1a;https://prometheus.io/docs/prometheus/latest/configuration/configuration/#kube…

Spring Boot——日志介绍和配置

1. 日志的介绍 在前面的学习中&#xff0c;控制台上打印出来的一大堆内容就是日志&#xff0c;可以帮助我们发现问题&#xff0c;分析问题&#xff0c;定位问题&#xff0c;除此之外&#xff0c;日志还可以进行系统的监控&#xff0c;数据采集等 2. 日志的使用 在程序中获取日…

systemd

文章目录 运行模式获取需要开机启动的服务UnitServiceInstall 添加开机自启程序 在centos6之前使用上面方式&#xff08;串&#xff09; 在centos7之后(含centos7)使用systemd来管理程序, 通过ls -al /sbin/init 查看链接指向了systemd程序&#xff1a;&#xff08;并&#xf…

LeetCode 热题100之技巧关卡

1.只出现一次的数字 思路分析1&#xff1a;使用哈希表存储每个数字和该数字出现的次数。遍历数组即可得到每个数字出现的次数&#xff0c;并更新哈希表&#xff0c;最后遍历哈希表&#xff0c;得到只出现一次的数字。 具体实现代码&#xff08;详解版&#xff09;&#xff1a;…

如何优化Kafka消费者的性能

要优化 Kafka 消费者性能&#xff0c;你可以考虑以下策略&#xff1a; 并行消费&#xff1a;通过增加消费者组中的消费者数量来并行处理更多的消息&#xff0c;从而提升消费速度。 批量消费&#xff1a;配置 fetch.min.bytes 和 fetch.max.wait.ms 参数来控制批量消费的大小和…

服务器数据恢复——Ext4文件系统使用fsck后mount不上的数据恢复案例

关于Ext4文件系统的几个概念&#xff1a; 块组&#xff1a;Ext4文件系统的全部空间被划分为若干个块组&#xff0c;每个块组结构基本上相同。 块组描述符表&#xff1a;每个块组都对应一个块组描述符&#xff0c;这些块组描述符统一放在文件系统的前部&#xff0c;称为块组描述…

GIC寄存器介绍

往期内容 本专栏往期内容&#xff0c;interrtupr子系统&#xff1a; 深入解析Linux内核中断管理&#xff1a;从IRQ描述符到irq domain的设计与实现Linux内核中IRQ Domain的结构、操作及映射机制详解中断描述符irq_desc成员详解Linux 内核中断描述符 (irq_desc) 的初始化与动态分…

并发基础:(淘宝笔试题)三个线程分别打印 A,B,C,要求这三个线程一起运行,打印 n 次,输出形如“ABCABCABC....”的字符串【举一反三】

🚀 博主介绍:大家好,我是无休居士!一枚任职于一线Top3互联网大厂的Java开发工程师! 🚀 🌟 在这里,你将找到通往Java技术大门的钥匙。作为一个爱敲代码技术人,我不仅热衷于探索一些框架源码和算法技巧奥秘,还乐于分享这些宝贵的知识和经验。 💡 无论你是刚刚踏…

vue计算属性 初步使用案例

<template><div><h1>购物车</h1><div v-for"item in filteredItems" :key"item.id"><p>{{ item.name }} - {{ item.price }} 元</p><input type"number" v-model.number"item.quantity"…

springboot读取modbus数据

1、引入依赖 jlibmodbus <dependency><groupId>com.intelligt.modbus</groupId><artifactId>jlibmodbus</artifactId><version>1.2.9.7</version> </dependency> 2、数据获取 public String processData(String ip) {tr…

【0x0045】HCI_Write_Inquiry_Mode详解

目录 一、命令概述 二、命令格式及参数说明 2.1. HCI_Write_Inquiry_Mode命令格式 2.2. Inquiry_Mode 三、响应事件格式及参数 3.1. HCI_Command_Complete事件格式 3.2. 参数说明 3.2.1. 事件代码(Event Code) 3.2.2. 参数总长度(Parameter Total Length) 3.2.3.…

【C语言】指针的运算

指针的增量操作&#xff1a; int i 10; int *p &i;printf("p %p\n", p);//1024p; // 增加int 4个字节大小printf("p %p\n", p);//1028指针的增量运算取决于指针的数据类型&#xff0c;它将会增加数据类型的大小的字节。 指针的减量操作与增量同理…

电商系统开发:Spring Boot框架实战

3 系统分析 当用户确定开发一款程序时&#xff0c;是需要遵循下面的顺序进行工作&#xff0c;概括为&#xff1a;系统分析–>系统设计–>系统开发–>系统测试&#xff0c;无论这个过程是否有变更或者迭代&#xff0c;都是按照这样的顺序开展工作的。系统分析就是分析系…

【数据库】数据库迁移的注意事项有哪些?

数据库迁移是一个复杂且关键的过程&#xff0c;需要谨慎处理以确保数据的完整性和应用程序的正常运行。以下是一些数据库迁移时需要注意的事项&#xff1a; 1. 充分的前期准备 1.1 评估迁移需求 明确目标&#xff1a;确定迁移的具体目标&#xff0c;例如添加新字段、修改现…

pgsql和mysql的自增主键差异

1. 当有历史数据存在时&#xff0c; mysql的自增主键是默认从最大值自增。 pgsql的自增主键取初始值开始逐个尝试&#xff0c;所以存在可能与历史数据的主键重复的情况。 pgsql解决上述问题的方式&#xff1a;重设自增值。 SELECT SETVAL(t_db_filed_id_seq, (SELECT MAX(&q…

opencv入门学习总结

opencv学习总结 不多bb&#xff0c;直接上代码&#xff01;&#xff01;&#xff01; 案例一&#xff1a; import cv2 # 返回当前安装的 OpenCV 库的版本信息 并且是字符串格式 print(cv2.getVersionString()) """ 作用&#xff1a;它可以读取不同格式的图像文…

【VBA实战】用Excel制作排序算法动画续

为什么会产生用excel来制作排序算法动画的念头&#xff0c;参见【VBA实战】用Excel制作排序算法动画一文。这篇文章贴出我所制作的所有排序算法动画效果和源码&#xff0c;供大家参考。 冒泡排序&#xff1a; 插入排序&#xff1a; 选择排序&#xff1a; 快速排序&#xff1a;…

Go 语言已立足主流,编程语言排行榜24 年 11 月

Go语言概述 Go语言&#xff0c;简称Golang&#xff0c;是由Google的Robert Griesemer、Rob Pike和Ken Thompson在2007年设计&#xff0c;并于2009年11月正式宣布推出的静态类型、编译型开源编程语言。Go语言以其提高编程效率、软件构建速度和运行时性能的设计目标&#xff0c;…

《基于深度学习的车辆行驶三维环境双目感知方法研究》

复原论文思路&#xff1a; 《基于深度学习的车辆行驶三维环境双目感知方法研究》 1、双目测距的原理 按照上述公式算的话&#xff0c;求d的话&#xff0c;只和xl-xr有关系&#xff0c;这样一来&#xff0c;是不是只要两张图像上一个测试点的像素位置确定&#xff0c;对应的深…