Java基础 - 09 Set之linkedHashSet , CopyOnWriteArraySet

news2024/11/26 2:22:19

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的元素数量。

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

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

相关文章

RC滤波电路的原理

RC滤波电路分为低通滤波和高通滤波 低通滤波通过低频信号 看上面这两个电路 先分析低通滤波 由于电容C具有隔直通交的特性&#xff0c;所以输入的高频分量相当于经过电阻R后直接对地短接&#xff0c;并没有输出到后端负载上&#xff0c;只有低频的输入分量才会输出到后端。 电…

022-安全开发-PHP应用留言板功能超全局变量数据库操作第三方插件引用

022-安全开发-PHP应用&留言板功能&超全局变量&数据库操作&第三方插件引用 #知识点&#xff1a; 1、PHP留言板前后端功能实现 2、数据库创建&架构&增删改查 3、内置超全局变量&HTML&JS混编 4、第三方应用插件&传参&对象调用 演示案例&a…

开源的测试平台快2千星了,能带来多少收益呢

最近看了下自己去年初开源的测试平台&#xff0c;star一起算的话也到1.7k了&#xff1a; 做开源的初心一方面是想把自己的理解和思想展示出来&#xff0c;另一方面是想进一步打造个人IP&#xff0c;提升影响力&#xff08;其实这个想法很早之前就有了&#xff0c;计划过无数次但…

威士忌品鉴色泽与味蕾:从颜色到味蕾,解读品质与特点

威士忌的色泽与味蕾是其品质和特点的重要体现。通过对威士忌颜色的观察&#xff0c;我们可以大致判断其酿造原料、陈酿时间以及酒龄等信息。而品尝威士忌的过程&#xff0c;则是对其色泽、香气和味蕾的综合体验。本文将结合雷盛537威士忌深入探讨威士忌的色泽与味蕾之间的关系&…

《WebKit 技术内幕》学习之九(2): JavaScript引擎

2 V8引擎 2.1 基础 V8是一个开源项目&#xff0c;也是一个JavaScript引擎的实现。它最开始是由一些语言方面的专家设计出来的&#xff0c;后被Google收购&#xff0c;成为了JavaScript引擎和众多相关技术的引领者。其目的很简单&#xff0c;就是为了提高性能。因为在当时之前…

houdini fft 使用三层for each结构 以及for 问题

for each 中 使用 attrib wrangle detail时&#xff0c;不连接foreach_count1&#xff0c;只运行一次 for each 问题 merge eachiteration 对结构进行合并 transform 位置的移动针对的是原位置对原点的距离&#xff0c;而非移动后置0后再移

Unity编程#region..#endregion以及面板提示语标签[Tooltip(““)]

C#中的#region..#endregion 在Unity中&#xff0c;#region和#endregion是用于代码折叠的预处理指令。它们并不是Unity特有的&#xff0c;而是C#语言本身提供的功能。 #region用于标记一段代码的开始&#xff0c;而#endregion用于标记一段代码的结束。在编辑器中&#xff0c;可…

C++:迭代器失效问题

目录 1.vector迭代器失效问题 1.底层空间改变 ​编辑 2.指定位置元素的删除操作 2.Linux下的迭代器失效检测 1.扩容 2.删除 3.解决方法 1.vector迭代器失效问题 迭代器的主要作用就是让算法能够不用关心底层数据结构&#xff0c;其底层实际就是一个指针&#xff0c;或者是…

计组与原理:系统总线

大家好啊&#xff0c;这里来到计组第二部分内容&#xff1a;系统总线 跳转上一篇&#xff1a;计组原理&#xff1a;系统概论与基本组成 系统总线 1.总线的基本概念单总线结构框图面向 CPU 的双总线结构框图以存储器为中心的双总线结构框图 2.总线的分类片内总线系统总线通信总线…

牛仔服装行业研究:预计到2025年将达到约650亿美元

牛仔服装是指原美国西部垦拓者(牛仔)穿着的服装&#xff0c;一般用纯棉或棉纤维为主要原材料混纺、交织的色织牛仔布制作。 牛仔布的生产起源于美国。牛仔服装历经百年变迁&#xff0c;由最初的工装演变为时装&#xff0c;征服了人们不同阶段挑剔的目光&#xff0c;最终成为服装…

UDP和TCP代理协议有什么区别?哪个更好

在互联网的世界里&#xff0c;数据传输的方式有很多种&#xff0c;其中 UDP 和 TCP 是两种常见的传输协议。而代理协议则是为了在网络中传输数据时提供安全、稳定和高效的传输环境。那么&#xff0c;UDP 和 TCP 代理协议有什么区别呢&#xff1f;哪个更好呢&#xff1f;接下来&…

自然语言处理的崛起:从初步分析到深度理解

自然语言处理&#xff08;NLP&#xff09;是计算机科学、人工智能和语言学的交叉领域&#xff0c;旨在让计算机能够理解和生成人类语言。随着时间的推移&#xff0c;NLP 经历了一系列革命性的变化&#xff0c;从简单的规则和模式匹配到如今的深度学习模型&#xff0c;它们使计算…

什么是BMC

BMC全称为Baseboard Management Controller&#xff08;基板管理控制器&#xff09;&#xff0c;是一种独立于服务器操作系统和主处理器的专用微控制器&#xff0c;它内置在服务器、网络设备和其他复杂电子系统的主板上。BMC主要负责监控和管理系统硬件的状态&#xff0c;并提供…

ubuntu上创建ftp服务器

今天在linux电脑上安装了ftp服务器&#xff0c;中间碰到不少问题&#xff0c;参照各路攻略&#xff0c;修改多次配置后终于完成了服务器搭建 1&#xff1a;安装vsftp服务器 最简答的一步&#xff0c;直接&#xff1a;apt-get install vsftp 安装完成后&#xff0c;查看版本号…

华为发布 HarmonyOS NEXT 鸿蒙星河版

文章目录 个人简介 在 2024-01-18 下午于深圳举办的鸿蒙生态千帆启航仪式上&#xff0c;华为常务董事兼终端BG CEO余承东宣布了HarmonyOS NEXT&#xff08;鸿蒙星河版&#xff09;的开发者预览版面向开发者开放申请。这一版本旨在实现六大极致原生体验&#xff0c;包括原生精致…

C++——IOStream

什么是IO&#xff1f; C语言和C&#xff0c;我们其实已经接触到了两个IO的概念 #include<stdio.h> #include<iostream> iostream&#xff0c;便是IO流&#xff0c;其中I表示in&#xff0c;O表示out&#xff0c;代表着用户的输入和终端的输出。在之前的C语法中&a…

前端使用css去除input框的默认样式

关键点&#xff1a; /* 关键点&#xff0c;让输入框无边框 */outline:none; border:none; 1.效果图 2.html <div class"container"><input type"text" placeholder"请输入用户名"><input type"text" placeholder&q…

【学习】focal loss 损失函数

focal loss用于解决正负样本的不均衡情况 通常我们需要预测的正样本要少于负样本&#xff0c;正负样本分布不均衡会带来什么影响&#xff1f;主要是两个方面。 样本不均衡的话&#xff0c;训练是低效不充分的。因为困难的正样本数量较少&#xff0c;大部分时间都在学习没有用…

【B站最全唱歌教学】逼自己30天练完这些,唱歌变态好听!从零基础入门让你唱歌彻底变好听,学不会退出音乐圈!第一天

打基础 腹式呼吸&#xff08;口鼻同吸&#xff09;速度要快&#xff0c;练习狗哈气吐气吐快了容易没气&#xff0c;练吐丝&#xff08;男生&#xff1a;40s&#xff0c;女生&#xff1a;30s&#xff09;&#xff0c;要用腹式呼吸&#xff0c;而不是胸式呼吸&#xff08;肺活量…

35岁了,怎么办?

从裁员联想到程序员的转折点——35岁。35岁是一个尴尬的年纪&#xff0c;这个阶段&#xff0c;我们好像失去任性的资本&#xff0c;却也不像更年长的人一样通达而不惑。在这个不上不下的年纪&#xff0c;35岁有着无尽的烦恼&#xff1a;高昂的房价、上有老下有小的家庭、被裁员…