Java集合框架之LinkedHashSet详解

news2024/10/6 8:31:39

哈喽,各位小伙伴们,你们好呀,我是喵手。运营社区:C站/掘金/腾讯云;欢迎大家常来逛逛

  今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互相学习,一个人虽可以走的更快,但一群人可以走的更远。

  我是一名后端开发爱好者,工作日常接触到最多的就是Java语言啦,所以我都尽量抽业余时间把自己所学到所会的,通过文章的形式进行输出,希望以这种方式帮助到更多的初学者或者想入门的小伙伴们,同时也能对自己的技术进行沉淀,加以复盘,查缺补漏。

小伙伴们在批阅的过程中,如果觉得文章不错,欢迎点赞、收藏、关注哦。三连即是对作者我写作道路上最好的鼓励与支持!

前言

  在Java开发中,集合类是非常常用的一种数据类型。而集合类中的Set集合是一种不允许重复元素的集合。在Set集合中,除了HashSet和TreeSet之外,还有一种集合类叫做LinkedHashSet。本文将会介绍LinkedHashSet的概念,源代码解析,应用场景案例,优缺点分析,类代码方法介绍以及测试用例。

摘要

  LinkedHashSet是一种Set集合类,它是HashSet和LinkedHashMap的结合体。它既有HashSet的快速查找和不允许重复元素的特性,又有LinkedHashMap的有序性和迭代器的快速遍历特性。因此,在需要保持元素顺序的情况下,我们可以使用LinkedHashSet。

LinkedHashSet

简介

  LinkedHashSet是Java集合框架中Set接口的实现类,它继承自HashSet,并且实现了Set接口。LinkedHashSet底层是通过一个由链表和哈希表组成的数据结构来实现的。其中,链表用于保证元素插入的顺序,而哈希表用于保证元素的唯一性。

  与HashSet相比,LinkedHashSet可以保证元素的插入顺序,这是因为LinkedHashSet内部维护了一个链表来记录元素的插入顺序。与TreeSet相比,LinkedHashSet的元素不是按照自然排序或者指定的Comparator排序,而是按照插入顺序排序。

源代码解析

  LinkedHashSet的源代码中,我们可以看到它实现了Set接口,并且继承了HashSet类,HashSet又继承了AbstractSet类。而AbstractSet类实现了Set接口中的一些方法。

LinkedHashSet的构造函数如下:

public LinkedHashSet() {
        super();
        map = new LinkedHashMap<>();
    }

public LinkedHashSet(int initialCapacity, float loadFactor) {
        super();
        map = new LinkedHashMap<>(initialCapacity, loadFactor);
    }

public LinkedHashSet(int initialCapacity) {
        super();
        map = new LinkedHashMap<>(initialCapacity);
    }

public LinkedHashSet(Collection<? extends E> c) {
        super();
        map = new LinkedHashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
        addAll(c);
}

  可以看到,LinkedHashSet提供了多个构造函数,允许用户指定不同的初始容量和负载因子。其中,最后一个构造函数会通过调用addAll方法来添加集合中的所有元素。

在这里插入图片描述

LinkedHashSet的主要方法如下:

public boolean add(E e) {
        return map.put(e, PRESENT)==null;
}

public boolean remove(Object o) {
        return map.remove(o)==PRESENT;
}

public void clear() {
        map.clear();
}

public Object clone() {
        LinkedHashSet<?> clone = (LinkedHashSet<?>) super.clone();
        clone.map = (LinkedHashMap<E,Object>) map.clone();
        return clone;
}

  其中,add方法和remove方法都是通过调用LinkedHashMap中的put方法和remove方法来实现的。LinkedHashMapput方法和remove方法都是基于哈希表实现的,而又通过双向链表来维护元素的插入顺序。

  除此之外,LinkedHashSet还实现了Set接口中的一些方法,如contains、isEmpty、size等方法,这些方法都是基于LinkedHashMap来实现的。LinkedHashSet还提供了迭代器、并发修改异常等特性。

如下是部分源码截图:

在这里插入图片描述

应用场景案例

  1. 维护元素的顺序: 在需要维护元素插入顺序的情况下,可以使用LinkedHashSet。例如,在一个流式处理数据的应用中,需要对元素进行去重和排序操作。

  2. 避免并发修改异常: 在多线程程序中,使用LinkedHashSet可以避免并发修改异常。例如,在一个多线程爬虫程序中,需要对爬取到的URL进行去重操作,就可以使用LinkedHashSet来避免并发修改异常。

优缺点分析

优点

  1. LinkedHashSet支持元素的快速查找和不允许重复元素的特性。

  2. LinkedHashSet具有有序性,可以保证元素的插入顺序。

  3. LinkedHashSet内部维护了一个链表,可以利用迭代器快速遍历元素。

  4. 使用LinkedHashSet可以避免并发修改异常。

缺点

  1. LinkedHashSet的性能比HashSet略低,因为LinkedHashSet需要维护链表。

  2. LinkedHashSet相对于TreeSet来说,缺少排序功能。

类代码方法介绍

构造函数

public LinkedHashSet();
public LinkedHashSet(int initialCapacity);
public LinkedHashSet(int initialCapacity, float loadFactor);
public LinkedHashSet(Collection<? extends E> c);
  • 构造函数可以指定不同的初始容量和负载因子。

基本方法

public boolean add(E e);
public boolean remove(Object o);
public void clear();
public Object clone();
  • add方法和remove方法都是通过调用LinkedHashMap中的put方法和remove方法来实现的。

  • LinkedHashSet的clone方法会返回一个包含当前元素的拷贝集合。

Set接口方法

LinkedHashSet实现了Set接口中的一些方法,如contains、isEmpty、size等方法。

迭代器

  LinkedHashSet支持迭代器,它继承了HashSet的迭代器,而HashSet的迭代器又继承了AbstractSet的迭代器。

以下是一个通过迭代器遍历LinkedHashSet中元素的例子:

// 创建一个LinkedHashSet
LinkedHashSet<String> set = new LinkedHashSet<>();

// 添加元素
set.add("apple");
set.add("banana");
set.add("orange");

// 创建迭代器
Iterator<String> iterator = set.iterator();

// 遍历元素
while(iterator.hasNext()) {
    String element = iterator.next();
    System.out.println(element);
}

测试用例

测试代码

以下是一个使用LinkedHashSet的测试用例,该测试用例用于统计一段文本中每个单词出现的次数:

package com.example.javase.collection;

import java.util.LinkedHashSet;
import java.util.Scanner;

/**
 * @Author ms
 * @Date 2023-10-22 21:41
 */
public class LinkedHashSetTest {

    public static void main(String[] args) {
        // 读入文本
        Scanner scanner = new Scanner(System.in);
        String text = scanner.nextLine();

        // 分割单词
        String[] words = text.split("\\s+");

        // 创建集合
        LinkedHashSet<String> set = new LinkedHashSet<>();

        // 统计每个单词出现的次数
        int[] count = new int[words.length];
        for (int i = 0; i < words.length; i++) {
            if (!set.contains(words[i])) {
                set.add(words[i]);
            }
            count[i] = 1;
            for (int j = i + 1; j < words.length; j++) {
                if (words[i].equals(words[j])) {
                    count[i]++;
                }
            }
        }

        // 输出结果
        System.out.println("单词\t出现次数");
        for (String word : set) {
            int sum = 0;
            for (int i = 0; i < words.length; i++) {
                if (word.equals(words[i])) {
                    sum += count[i];
                }
            }
            System.out.println(word + "\t" + sum);
        }
    }
}

演示结果

  根据如上测试用例,本地测试结果如下,仅供参考,你们也可以自行修改测试用例或者添加更多的测试数据或测试方法,进行熟练学习以此加深理解。

在这里插入图片描述

代码分析

  根据如上测试用例,在此我给大家进行深入详细的解读一下测试代码,以便于更多的同学能够理解并加深印象。这是一个使用 LinkedHashSet 统计给定文本中每个单词出现次数的程序。

  首先通过 Scanner 读入文本,然后使用 split 方法将文本分割成单词数组。

  接着创建一个 LinkedHashSet 集合,用于存储出现过的单词,并通过循环遍历单词数组,将每个单词存入集合中。

  接下来,遍历单词数组,统计每个单词出现的次数。通过一个 count 数组记录每个单词的出现次数,count[i] 表示第 i 个单词的出现次数,初值为 1,然后再循环遍历之后的单词数组,如果找到了相同的单词,则将当前单词的出现次数加 1。

  最后再次遍历集合中的每个单词,利用 count 数组计算每个单词出现的总次数,并输出结果。

全文小结

  本文介绍了Java集合框架中的LinkedHashSet,包括概念、源代码解析、应用场景案例、优缺点分析、类代码方法介绍和测试用例。LinkedHashSet是一种既有HashSet的快速查找和不允许重复元素特性,又有LinkedHashMap的有序性和迭代器快速遍历特性的集合类。在需要保持元素顺序的情况下,我们可以使用LinkedHashSet。

总结

  本文介绍了Java集合框架中的LinkedHashSet,它是一种既有HashSet的快速查找和不允许重复元素特性,又有LinkedHashMap的有序性和迭代器快速遍历特性的集合类。LinkedHashSet的底层是通过一个由链表和哈希表组成的数据结构来实现的,其中链表用于保证元素插入顺序,哈希表用于保证元素的唯一性。相比于HashSet,LinkedHashSet可以保证元素插入顺序;相比于TreeSet,LinkedHashSet的元素不是按照自然排序或者指定的Comparator排序,而是按照插入顺序排序。在需要维护元素插入顺序的情况下,我们可以使用LinkedHashSet。同时,使用LinkedHashSet可以避免并发修改异常。

… …

文末

好啦,以上就是我这期的全部内容,如果有任何疑问,欢迎下方留言哦,咱们下期见。

… …

学习不分先后,知识不分多少;事无巨细,当以虚心求教;三人行,必有我师焉!!!

wished for you successed !!!


⭐️若喜欢我,就请关注我叭。

⭐️若对您有用,就请点赞叭。

⭐️若有疑问,就请评论留言告诉我叭。

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

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

相关文章

uniapp、web网页跨站数据交互及通讯

来来来&#xff0c;说说你的创作灵感&#xff01;这就跟吃饭睡觉一样&#xff0c;饿了就找吃的&#xff0c;渴了就倒水张口灌。 最近一个多月实在是忙的没再更新日志&#xff0c;好多粉丝私信说之前的创作于他们而言非常有用&#xff01;受益菲浅&#xff0c;这里非常感谢粉丝…

分布式与集群的区别

先说区别&#xff1a; 分布式是并联工作的&#xff0c;集群是串联工作的。 分布式中的每一个节点都可以做集群。而集群并不一定就是分布式的。 集群举例&#xff1a;比如新浪网&#xff0c;访问的人很多&#xff0c;他可以做一个集群&#xff0c;前面放一个相应的服务器&…

MySQL变量的四则运算以及取模运算

1、定义多个变量在一条语句中&#xff0c;需要使用,作为分隔符 除法默认保留4位有效数字 2、浮点数运算&#xff1a; 除法默认保留4位有效数字

《这就是ChatGPT》读书笔记

书名&#xff1a;这就是ChatGPT 作者&#xff1a;[美] 斯蒂芬沃尔弗拉姆&#xff08;Stephen Wolfram&#xff09; ChatGPT在做什么&#xff1f; ChatGPT可以生成类似于人类书写的文本&#xff0c;它基本任务是弄清楚如何针对它得到的任何文本产生“合理的延续”。当ChatGPT写…

2024 年最新使用 ntwork 框架搭建企业微信机器人详细教程

NTWORK 概述 基于 PC 企业微信的 api 接口&#xff0c;支持收发文本、群、名片、图片、文件、视频、链接卡片等。 下载安装 ntwork pip install ntwork国内源安装 pip install -i https://pypi.tuna.tsinghua.edu.cn/simple ntwork企业微信版本下载 官方下载&#xff1a;h…

无列名注入

在进行sql注入时&#xff0c;一般都是使用 information_schema 库来获取表名与列名&#xff0c;因此有一种场景是传入参数时会将 information_schema 过滤 在这种情况下&#xff0c;由于 information_schema 无法使用&#xff0c;我们无法获取表名与列名。 表名获取方式 Inn…

使用chatglm3本地部署形成的api给上一篇得到的网页信息text_content做内容提取

使用chatglm3本地部署形成的api给上一篇得到的网页信息text_content做内容提取&#xff0c; chatglm3的api调用见&#xff1a;chatglm3的api调用_启动chatglm3的api服务报错-CSDN博客 import os from openai import OpenAIbase_url "http://localhost:5000/v1/" c…

书生作业:XTuner

作业链接&#xff1a; https://github.com/InternLM/Tutorial/blob/camp2/xtuner/homework.md xtuner: https://github.com/InternLM/xtuner 环境配置 首先&#xff0c;按照xtuner的指令依次完成conda环境安装&#xff0c;以及xtuner库的安装。 然后&#xff0c;我们开始尝试…

基于Vant UI的微信小程序开发(随时更新的写手)

基于Vant UI的微信小程序开发✨ &#xff08;一&#xff09;悬浮浮动1、效果图&#xff1a;只要无脑引用样式就可以了2、页面代码3、js代码4、样式代码 &#xff08;二&#xff09;底部跳转1、效果图&#xff1a;点击我要发布跳转到发布的页面2、js代码3、页面代码4、app.json代…

STM32CubeMX软件使用(超详细)

1、Cube启动页介绍 2、芯片选择页面介绍 3、输入自己的芯片型号&#xff0c;这里以STM32U575RIT6举例 4、芯片配置页码介绍 5、芯片外设配置栏详细说明 6、点击ClockConfiguration进行时钟树的配置&#xff0c;选择时钟树后可以选择自己想使用的时钟源&#xff0c;也可以直接输…

LeetCode题练习与总结:反转链表Ⅱ--92

一、题目描述 给你单链表的头指针 head 和两个整数 left 和 right &#xff0c;其中 left < right 。请你反转从位置 left 到位置 right 的链表节点&#xff0c;返回 反转后的链表 。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5], left 2, right 4 输出&#…

e 值的故事:从复利到自然增长的数学之旅

自然对数函数的底数 e&#xff08;也称为自然常数或欧拉数&#xff09;与 π 一样&#xff0c;是数学中最伟大的常数之一。它大约为 2.718281828&#xff0c;是一个无理数&#xff0c;意味着它的小数部分无限且不重复。 与 π 和 √2 这些由几何发现而来的常数不同&#xff0c…

【高阶数据结构】图 -- 详解

一、图的基本概念 图 是由顶点集合及顶点间的关系组成的一种数据结构&#xff1a;G (V&#xff0c; E)。其中&#xff1a; 顶点集合 V {x | x属于某个数据对象集} 是有穷非空集合&#xff1b; E {(x,y) | x,y属于V} 或者 E {<x, y> | x,y属于V && Path(x, y…

解决常见的Android问题

常见问题&#xff1a; 1、查杀&#xff1a; 查杀一般分为两个方向一种是内存不足的查杀&#xff0c;一种的是因为温度限频查杀&#xff0c;统称为内存查杀&#xff0c;两个问题的分析思路不同 1、内存不足查杀&#xff1a; 主要是因为当用户出现后台运行多个APP或者是相机等…

LeetCode96:不同的二叉搜索树

题目描述 给你一个整数 n &#xff0c;求恰由 n 个节点组成且节点值从 1 到 n 互不相同的 二叉搜索树 有多少种&#xff1f;返回满足题意的二叉搜索树的种数。 代码 /*dp[i]&#xff1a;表示i个节点有dp[i]个不同的二搜索叉树递推公式&#xff1a;dp[i] dp[j-1] * dp[i-j], j…

【JavaSE】/*运算符—快速总结*/

目录 前言 一、什么是运算符 二、算术运算符 三、增量运算符 四、自增/自减运算符 五、关系运算符 六、逻辑运算符 七、位运算符 八、移位运算符 九、条件运算符 十、运算符的优先级 前言 Java 中的运算符和 C语言 的运算符规则有很多类型的地方&#xff0c;我们只…

K8s源码分析(二)-K8s调度队列介绍

本文首发在个人博客上&#xff0c;欢迎来踩&#xff01; 本次分析参考的K8s版本是 文章目录 调度队列简介调度队列源代码分析队列初始化QueuedPodInfo元素介绍ActiveQ源代码介绍UnschedulableQ源代码介绍**BackoffQ**源代码介绍队列弹出待调度的Pod队列增加新的待调度的Podpod调…

LinkedList链表

LinkedList 的全面说明 LinkList底层实现了双向链表和双端队列特点可以添加任意元素&#xff08;元素可以重复&#xff09;&#xff0c;包括null线程不安全&#xff0c;没有实现同步 LinkedList 的底层操作机制 LinkedList底层维护了一个双向链表LinkList中维护了两个属性fi…

【C#进阶】简单数据结构类

简单数据结构类 文章目录 1、Arraylist1、ArrayList的本质2、声明3、增删查改4、装箱拆箱思考 背包售卖 2、Stack1、Stack的本质2、声明3、增取查改4、遍历思考 计算一个数的二进制 3、Queue1、Queue的本质2、声明3、增取查改4、遍历思考 每隔一段时间打印一条消息 4、Hashtab…

运营商的mpls专线

在当今高速发展的数字化时代&#xff0c;网络已成为企业发展不可或缺的基础设施。作为企业网络 连接的重要组成部分&#xff0c;MPLS专线在运营商的推动下逐渐成为了企业选择的首选。 MPLS&#xff08;Multi-Protocol Label Switching&#xff09;是一种基于标签的交换技术&am…