Java基础 - 09 Set之linkedHashSet , CopyOnWriteArraySet

2024-01-23 20:28

本文主要是介绍Java基础 - 09 Set之linkedHashSet , CopyOnWriteArraySet,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

LinkedHashSet和CopyOnWriteArraySet都是Java集合框架提供的特殊集合类,他们在特定场景下有不同的用途和特点。

LinkedHashSet是Java集合框架中的一种实现类,它继承自HashSet并且保持插入顺序。它使用哈希表来存储元素,并使用链表来维护插入顺序。由于使用哈希表,LinkedHashSet提供了常数时间的复杂度(O(1))来执行插入、删除和查找操作。同时,由于使用链表来维护插入顺序,LinkedHashSet可以按照元素的插入顺序进行迭代。因此,LinkedHashSet适用于需要保持插入顺序并且需要高效的插入、删除和查找操作的场景。

CopyOnWriteArraySet是Java并发包中的一种线程安全的Set实现。它实现了Set接口,并且使用了CopyOnWriteArrayList作为内部数据结构。CopyOnWriteArraySet通过在每次修改时创建一个新的副本来实现线程安全性,因此在并发修改操作时不会出现ConcurrentModificationException异常。它适用于读操作频繁、写操作较少的场景,因为每次修改都会创建一个新的副本,可能会带来一定的内存开销。由于CopyOnWriteArraySet是无序的,它不会维护插入顺序。因此,如果需要保持元素的插入顺序,应该使用LinkedHashSet。

LinkedHashSet

LinkedHashSet是一个基于哈希表链表实现的有序集合。它继承自HashSet,并且保留了元素插入的顺序。LinkedHashSet通过哈希表快速访问元素,同时使用链表维护元素的顺序。这使得LinkedHashSet在需要保持元素顺序的情况下更加适用。

在这里插入图片描述
在这里插入图片描述

public static void main(String[] args) {LinkedHashSet<String> set = new LinkedHashSet<>();// 添加元素set.add("apple");set.add("banana");set.add("orange");// 迭代元素,按照插入顺序输出for (String fruit : set) {System.out.println(fruit);}}

源码:

public class LinkedHashSet<E>extends HashSet<E>implements Set<E>, Cloneable, java.io.Serializable {/*** 构造一个带默认初始容量 (16) 和加载因子 (0.75) 的新空链接哈希 set。*/public LinkedHashSet() {super(16, .75f, true);}/***  构造一个与指定 collection 中的元素相同的新链接哈希 set。*/public LinkedHashSet(Collection<? extends E> c) {super(Math.max(2*c.size(), 11), .75f, true);addAll(c);}/*** 构造一个带指定初始容量和默认加载因子 (0.75) 的新空链接哈希 set。*/public LinkedHashSet(int initialCapacity) {super(initialCapacity, .75f, true);}/*** 构造一个带有指定初始容量和加载因子的新空链接哈希 set。*/public LinkedHashSet(int initialCapacity, float loadFactor) {super(initialCapacity, loadFactor, true);}
}

以下是一些LinkedHashSet的特点和用途:

  • LinkedHashSet保留了元素插入的顺序,因此可以按照插入顺序进行迭代
  • LinkedHashSet线程不安全的,不适用于多线程环境。
  • LinkedHashSet具有HashSet的高效查找特性,同时还可以保持元素的顺序。
  • LinkedHashSet的插入、删除和查找操作具有常数时间复杂度。

CopyOnWriteArraySet

CopyOnWriteArraySet是一个线程安全的集合类,它实现了Set接口,并且内部使用了Copy-On-Write技术。Copy-On-Write是一种并发策略,它在写操作时创建并复制整个集合,这样读操作不会受到写操作的影响。因此,CopyOnWriteArraySet非常适合用于读多写少的场景。

在这里插入图片描述

以下是一些CopyOnWriteArraySet的特点和用途:

  • CopyOnWriteArraySet是线程安全的,适用于多线程环境。
  • CopyOnWriteArraySet的迭代操作不需要加锁,并且不会抛出ConcurrentModificationException异常。
  • CopyOnWriteArraySet的写操作会复制整个集合,因此在写操作频繁的情况下,性能可能较低。
  • CopyOnWriteArraySet的读操作具有较低的性能开销
    在这里插入图片描述
    内部方法介绍
  • add(E e): 向集合中添加指定元素。该方法会创建一个新的数组,并将指定元素添加到新数组中
  • remove(Object o): 从集合中移除指定元素。该方法会创建一个新的数组,并将除指定元素之外的所有元素添加到新数组中。
  • contains(Object o): 判断集合中是否包含指定元素。该方法会遍历内部的数组,判断是否有相等的元素
  • isEmpty(): 判断集合是否为空。该方法会判断内部的数组是否为空。
  • size(): 返回集合的大小,即元素的个数。该方法会返回内部数组的长度。
  • iterator(): 返回一个迭代器**,用于遍历集合中的元素**。该方法返回的迭代器是通过拷贝内部数组创建的,因此不会受到集合修改的影响。
  • toArray(): 将集合中的元素转换为数组,并返回该数组。该方法会创建一个新的数组,并将集合中的元素复制到新数组中。

两者直接的区别

CopyOnWriteArraySet

CopyOnWriteArraySet适用于读多写少的并发场景。它通过使用Copy-On-Write技术,在写操作时创建并复制整个集合,这样读操作不会受到写操作的影响。这使得CopyOnWriteArraySet在多线程环境下具有较好的安全性,读操作不需要加锁,并且不会抛出ConcurrentModificationException异常。因此,当需要在多线程环境下进行读操作较多的场景时,可以使用CopyOnWriteArraySet。

import java.util.concurrent.CopyOnWriteArraySet;public class CopyOnWriteArraySetExample {public static void main(String[] args) {CopyOnWriteArraySet<String> set = new CopyOnWriteArraySet<>();// 添加元素set.add("apple");set.add("banana");set.add("cherry");// 遍历元素for (String element : set) {System.out.println(element);}// 删除元素set.remove("banana");// 判断元素是否存在boolean contains = set.contains("cherry");System.out.println("Contains 'cherry': " + contains);// 获取集合大小int size = set.size();System.out.println("Size: " + size);}
}

LinkedHashSet

LinkedHashSet是HashSet的一个子类,它维护了一个双向链表来保持元素的插入顺序。LinkedHashSet适用于需要保持元素插入顺序的场景。它提供了HashSet的高性能查找和插入操作,并且使用链表来保持插入顺序。因此,当需要在保持插入顺序的同时进行高效的查找和插入操作时,可以使用LinkedHashSet。

import java.util.LinkedHashSet;public class LinkedHashSetExample {public static void main(String[] args) {LinkedHashSet<String> set = new LinkedHashSet<>();// 添加元素set.add("apple");set.add("banana");set.add("cherry");// 遍历元素for (String element : set) {System.out.println(element);}// 删除元素set.remove("banana");// 判断元素是否存在boolean contains = set.contains("cherry");System.out.println("Contains 'cherry': " + contains);// 获取集合大小int size = set.size();System.out.println("Size: " + size);}
}

在多线程环境下,CopyOnWriteArraySet比LinkedHashSet具有更好的安全性。CopyOnWriteArraySet的读操作不需要加锁,并且不会抛出ConcurrentModificationException异常。而LinkedHashSet在多线程环境下需要使用外部同步机制来确保线程安全。例如,可以使用Collections.synchronizedSet()。

创建一个多线程环境下使用LinkedHashSet的示例

public class LinkedHashSetThreadSafetyExample {public static void main(String[] args) {Set<String> set = Collections.synchronizedSet(new LinkedHashSet<>());// 创建多个线程来同时对set进行操作Thread thread1 = new Thread(() -> {for (int i = 0; i < 1000; i++) {set.add("Thread 1 - Element " + i);}});Thread thread2 = new Thread(() -> {for (int i = 0; i < 1000; i++) {set.add("Thread 2 - Element " + i);}});// 启动线程thread1.start();thread2.start();try {// 等待线程执行完毕thread1.join();thread2.join();} catch (InterruptedException e) {e.printStackTrace();}// 输出set的元素数量System.out.println("Set size: " + set.size());}
}

在上述代码中,我们创建了一个多线程环境下使用LinkedHashSet的示例。首先,我们使用Collections.synchronizedSet()方法创建了一个线程安全的Set,即使用外部同步机制来确保线程安全。然后,我们创建了两个线程thread1和thread2,分别向set中添加1000个元素。最后,我们使用thread1.join()和thread2.join()方法等待两个线程执行完毕,然后输出set的元素数量。

使用CopyOnWriteArraySet类来实现多线程安全的Set。

import java.util.concurrent.CopyOnWriteArraySet;public class CopyOnWriteArraySetThreadSafetyExample {public static void main(String[] args) {CopyOnWriteArraySet<String> set = new CopyOnWriteArraySet<>();// 创建多个线程来同时对set进行操作Thread thread1 = new Thread(() -> {for (int i = 0; i < 1000; i++) {set.add("Thread 1 - Element " + i);}});Thread thread2 = new Thread(() -> {for (int i = 0; i < 1000; i++) {set.add("Thread 2 - Element " + i);}});// 启动线程thread1.start();thread2.start();try {// 等待线程执行完毕thread1.join();thread2.join();} catch (InterruptedException e) {e.printStackTrace();}// 输出set的元素数量System.out.println("Set size: " + set.size());}
}

在上述代码中,我们使用CopyOnWriteArraySet类来实现多线程安全的Set。CopyOnWriteArraySet是一个线程安全的Set实现,通过在每次修改时创建一个新的副本来实现线程安全性。这意味着在并发修改操作时,不会发生ConcurrentModificationException异常。

我们创建了一个CopyOnWriteArraySet对象,然后创建了两个线程thread1和thread2,分别向set中添加1000个元素。最后,我们使用thread1.join()和thread2.join()方法等待两个线程执行完毕,然后输出set的元素数量。

这篇关于Java基础 - 09 Set之linkedHashSet , CopyOnWriteArraySet的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/637421

相关文章

Spring Boot集成Druid实现数据源管理与监控的详细步骤

《SpringBoot集成Druid实现数据源管理与监控的详细步骤》本文介绍如何在SpringBoot项目中集成Druid数据库连接池,包括环境搭建、Maven依赖配置、SpringBoot配置文件... 目录1. 引言1.1 环境准备1.2 Druid介绍2. 配置Druid连接池3. 查看Druid监控

Java中读取YAML文件配置信息常见问题及解决方法

《Java中读取YAML文件配置信息常见问题及解决方法》:本文主要介绍Java中读取YAML文件配置信息常见问题及解决方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要... 目录1 使用Spring Boot的@ConfigurationProperties2. 使用@Valu

创建Java keystore文件的完整指南及详细步骤

《创建Javakeystore文件的完整指南及详细步骤》本文详解Java中keystore的创建与配置,涵盖私钥管理、自签名与CA证书生成、SSL/TLS应用,强调安全存储及验证机制,确保通信加密和... 目录1. 秘密键(私钥)的理解与管理私钥的定义与重要性私钥的管理策略私钥的生成与存储2. 证书的创建与

浅析Spring如何控制Bean的加载顺序

《浅析Spring如何控制Bean的加载顺序》在大多数情况下,我们不需要手动控制Bean的加载顺序,因为Spring的IoC容器足够智能,但在某些特殊场景下,这种隐式的依赖关系可能不存在,下面我们就来... 目录核心原则:依赖驱动加载手动控制 Bean 加载顺序的方法方法 1:使用@DependsOn(最直

SpringBoot中如何使用Assert进行断言校验

《SpringBoot中如何使用Assert进行断言校验》Java提供了内置的assert机制,而Spring框架也提供了更强大的Assert工具类来帮助开发者进行参数校验和状态检查,下... 目录前言一、Java 原生assert简介1.1 使用方式1.2 示例代码1.3 优缺点分析二、Spring Fr

java使用protobuf-maven-plugin的插件编译proto文件详解

《java使用protobuf-maven-plugin的插件编译proto文件详解》:本文主要介绍java使用protobuf-maven-plugin的插件编译proto文件,具有很好的参考价... 目录protobuf文件作为数据传输和存储的协议主要介绍在Java使用maven编译proto文件的插件

Java中的数组与集合基本用法详解

《Java中的数组与集合基本用法详解》本文介绍了Java数组和集合框架的基础知识,数组部分涵盖了一维、二维及多维数组的声明、初始化、访问与遍历方法,以及Arrays类的常用操作,对Java数组与集合相... 目录一、Java数组基础1.1 数组结构概述1.2 一维数组1.2.1 声明与初始化1.2.2 访问

Javaee多线程之进程和线程之间的区别和联系(最新整理)

《Javaee多线程之进程和线程之间的区别和联系(最新整理)》进程是资源分配单位,线程是调度执行单位,共享资源更高效,创建线程五种方式:继承Thread、Runnable接口、匿名类、lambda,r... 目录进程和线程进程线程进程和线程的区别创建线程的五种写法继承Thread,重写run实现Runnab

Java 方法重载Overload常见误区及注意事项

《Java方法重载Overload常见误区及注意事项》Java方法重载允许同一类中同名方法通过参数类型、数量、顺序差异实现功能扩展,提升代码灵活性,核心条件为参数列表不同,不涉及返回类型、访问修饰符... 目录Java 方法重载(Overload)详解一、方法重载的核心条件二、构成方法重载的具体情况三、不构

Java通过驱动包(jar包)连接MySQL数据库的步骤总结及验证方式

《Java通过驱动包(jar包)连接MySQL数据库的步骤总结及验证方式》本文详细介绍如何使用Java通过JDBC连接MySQL数据库,包括下载驱动、配置Eclipse环境、检测数据库连接等关键步骤,... 目录一、下载驱动包二、放jar包三、检测数据库连接JavaJava 如何使用 JDBC 连接 mys