【JAVA语言-第16话】集合框架(三)——Set、HashSet、LinkedHashSet、TreeSet集合的详细解析

目录

Set集合

1.1 概述 

1.2 特点

1.3 HashSet集合

1.3.1 概述 

1.3.2 哈希表 

1.3.3 哈希值

1.3.4 练习

1.3.5 HashSet存储自定义类型元素

1.4 LinkedHashSet集合

1.4.1 概述

1.4.2 特点

1.4.3 练习

1.5 TreeSet集合

1.5.1 概述

1.5.2 练习

1.6 HashSet、LinkedHashSet、TreeSet 的异同点


Set集合

1.1 概述 

         java.util.Set:是一个接口,和List一样,也是继承自Collection,常用的实现类有TreeSet、HashSet,LinkedHashSet。

1.2 特点

  • 存取无序,存储的顺便和取出的数据不一定一致。 
  • 没有索引,不能通过索引操作元素。
  • 不可以存储重复的元素。相同元素的判断:哈希值相同,内容相同。

1.3 HashSet集合

1.3.1 概述 

         java.util.HashSet:在Java中,HashSet是一种基于哈希表的集合实现。它继承自AbstractSet类并实现了Set接口。HashSet类在内部使用哈希表来存储元素,并且不保证元素的顺序。它允许存储唯一的元素,不允许重复。HashSet提供了常量时间的查找、插入和删除操作,因此可以在大多数情况下提供高效的性能。 

1.3.2 哈希表 

        在jdk1.8之前,哈希表底层采用数组+链表实现,即使用链表处理冲突,同一个哈希值的元素都存储在一个链表中,但是当位于一个链表中的元素较多,即哈希值相等的元素较多时,通过Key值依次查找的效率较低;所以在jdk1.8中,哈希表存储采用数组+链表/红黑树实现,当链表的长度超过8时,将链表转换为红黑树,这样大大减少了查找时间。

1.3.3 哈希值

        是一个十进制整数,由系统随机给出(就是对象的地址,是一个逻辑地址,是模拟出来得到的地址,不是数据实际存储的物理地址),在Object类中有一个方法,可以获取对象的哈希值。

public native int hashCode():返回该对象的哈希码值。

        

toString方法的源码:内部就是调用hashCode()方法
        public String toString(){
            return getClass().getName() + "@" + Integer.toHaxString(hashCode());
        }

1.3.4 练习

package com.zhy.coll;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

public class TestHashSet {
    public static void main(String[] args) {
        //多态,接口引用 指向 实现类对象
        Set<Integer> set = new HashSet<>();

        //往Set集合中添加元素,Set和List一样继承了Collection,所有两个类操作元素有着相似的方法
        set.add(10);
        set.add(20);
        set.add(30);
        //猜猜:这个元素能不能存储进Set集合?
        set.add(10);

        //打印Set集合印证一下
        //输出:初始化Set集合:[20, 10, 30]
        //明明添加了4个元素,但是最终Set集合中只有三个,这就是Set区别于List的地方,前者是不允许存储重复数据的
        //且存储是10,20,30,但是输出且不是按照存储数据打印,这也是Set区别于List的地方,前者是无序的
        System.out.println("初始化Set集合:" + set);

        //遍历集合,可以使用迭代器或者增强for循环
        //1.使用迭代器
        Iterator<Integer> iterator = set.iterator();
        while(iterator.hasNext()){
            Integer integer = iterator.next();
            System.out.print(integer + " ");
        }

        //2.使用增强for
        for(Integer integer : set){
            System.out.print(integer + " ");
        }
    }
}

1.3.5 HashSet存储自定义类型元素

        Set集合保证元素唯一:(String,Integer,...Student,Person),自定义的类如果想要使用Set集合存储,必须重写hashCode方法和equals方法,才能过滤掉重复的数据。

 源代码:

package com.zhy.coll;

import java.util.Objects;

public class Persion {
    private String name;

    private int age;

    public Persion() {
    }

    public Persion(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    /**
     * 自定义类型,重写equals方法
     *  比较规则:name 和 age 内容都相同,返回true,否则,返回false
     * @param o
     * @return
     */
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Persion persion = (Persion) o;

        if (age != persion.age) return false;
        return name != null ? name.equals(persion.name) : persion.name == null;
    }

    /**
     * 获取对象的hashCode,必须和equals一起重写
     * @return
     */
    @Override
    public int hashCode() {
        int result = name != null ? name.hashCode() : 0;
        result = 31 * result + age;
        return result;
    }

    /**
     * 重写toString,返回对象的内容,如果不重写,默认对象的地址
     * @return
     */
    @Override
    public String toString() {
        return "Persion{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
package com.zhy.coll;

import java.util.HashSet;

public class TestPersion {
    public static void main(String[] args) {
        //使用HashSet存储String类型的数据
        //排除重复元素规则:首先比较两个值的hashCode是否相同,其次比较两个值的内容是否相同
        //如果两种情况都相同,HashSet会判定为这两个值是同一个元素,只会存储一个
        //如果hashCode相同,内容不相同,那么会以链表的形式存储在一个hashCode下面
        HashSet<String> set1 = new HashSet<>();
        String str1 = new String("abc");
        String str2 = new String("abc");
        String str3 = new String("重地");
        String str4 = new String("通话");
        System.out.println("str1的hashCode:" + str1.hashCode());
        System.out.println("str2的hashCode:" + str2.hashCode());
        System.out.println("str3的hashCode:" + str3.hashCode());
        System.out.println("str4的hashCode:" + str4.hashCode());
        System.out.println("str1 和 str2是否是同一个元素:" + (str1.hashCode() == str2.hashCode() && str1.equals(str2)));
        System.out.println("str3 和 str4是否是同一个元素:" + (str3.hashCode() == str4.hashCode() && str3.equals(str4)));

        set1.add(str1);
        set1.add(str2);
        set1.add(str3);
        set1.add(str4);
        System.out.println("初始化String类型的Set集合:" + set1);
        System.out.println("========================================================");

        //使用HashSet存储自定义类型Persion的数据,为了保证Set集合不重复存储的特性,自定义类型必须重写hashCode和equals方法
        //比较规则:
        // 根据name和age获取唯一的hashCode值,然后在比较两个对象的名称+年龄是否相同
        // 二者都相同,代表同一个对象,不重复存储
        HashSet<Persion> set2 = new HashSet<>();
        Persion p1 = new Persion("张三",18);
        Persion p2 = new Persion("张三",18);
        Persion p3 = new Persion("李思",28);
        System.out.println("p1的hashCode:" + p1.hashCode());
        System.out.println("p2的hashCode:" + p2.hashCode());
        System.out.println("p3的hashCode:" + p3.hashCode());
        System.out.println("p1 和 p2是否是同一个元素:" + (p1.hashCode() == p2.hashCode() && p1.equals(p2)));

        set2.add(p1);
        set2.add(p2);
        set2.add(p3);
        System.out.println("初始化Persion类型的Set集合:" + set2);
    }
}

 输出结果:

1.4 LinkedHashSet集合

1.4.1 概述

        java.util.LinkedHashSet:在Java中,LinkedHashSet是一种集合类,它是HashSet的子类。它继承了HashSet的特性,同时还保持了元素的插入顺序。与HashSet不同的是,LinkedHashSet使用链表来维护集合中元素的顺序。

1.4.2 特点

        底层是一个哈希表(数组+链表/红黑树)+链表:多了一条链表(记录元素的存储顺序),保证元素有序。

1.4.3 练习

源代码:

package com.zhy.coll;

import java.util.Iterator;
import java.util.LinkedHashSet;

public class TestLinkedHashSet {
    public static void main(String[] args) {
        //创建集合,存储Integer类型的数据
        LinkedHashSet<Integer> linkedHashSet = new LinkedHashSet<Integer>();

        //往集合中添加数据
        linkedHashSet.add(10);
        linkedHashSet.add(20);
        linkedHashSet.add(30);
        linkedHashSet.add(40);
        linkedHashSet.add(20);

        //遍历集合,迭代器或者增强for
        System.out.print("使用迭代器遍历集合:");
        Iterator<Integer> iterator = linkedHashSet.iterator();
        while (iterator.hasNext()){
            Integer integer = iterator.next();
            System.out.print(integer + " ");
        }
    }
}

输出结果:      

        查看集合的数据,不仅遍历的顺序和添加的顺序一致,还过滤掉了重复数据。

 

1.5 TreeSet集合

1.5.1 概述

        java.util.TreeSet:在Java中,TreeSet是一个实现了Set接口的有序集合。它是通过红黑树数据结构实现的,可以保证元素按照自然排序或者通过Comparator进行排序。TreeSet不允许重复元素,并且可以高效地进行插入、删除和查找操作。由于TreeSet是有序的,因此它提供了一些额外的方法,如获取最小元素、获取最大元素、获取小于等于某个值的最大元素等。

1.5.2 练习

源代码: 

package com.zhy.coll;

import java.util.TreeSet;

public class TestTreeSet {
    public static void main(String[] args) {
        TreeSet<Integer> treeSet = new TreeSet<>();
        treeSet.add(12);
        treeSet.add(98);
        treeSet.add(10);
        System.out.println("初始化treeSet集合:" + treeSet);

        Integer first = treeSet.first();
        System.out.println("获取集合中的第一个元素:" + first);

        Integer integer = treeSet.pollLast();
        System.out.println("移除集合中的最后一个元素:" + integer);

        System.out.print("使用增强for遍历集合:");
        for (Integer i : treeSet){
            System.out.print(i + " ");
        }
    }
}

输出结果: 

1.6 HashSet、LinkedHashSet、TreeSet 的异同点

        HashSet、LinkedHashSet和TreeSet是Java中集合框架中Set集合的三个实现类,它们之间有一些异同点。

数据结构:

  • HashSet是基于哈希表实现的集合,它使用哈希函数来确定元素的存储位置。
  • LinkedHashSet是HashSet的子类,它在哈希表的基础上使用链表来维护元素的插入顺序。
  • TreeSet是基于红黑树实现的集合,它能够自动将元素按照自然顺序或自定义的比较器顺序进行排序。

 插入顺序:

  • HashSet不保证元素的插入顺序,元素在集合中的位置是根据哈希函数计算得到的。
  • LinkedHashSet保持元素的插入顺序,即元素按照插入的顺序进行迭代。
  • TreeSet会根据元素的排序规则对元素进行排序,并且在遍历时按照排序后的顺序进行迭代。

排序: 

  • HashSet和LinkedHashSet不对元素进行排序,元素的顺序是根据哈希函数计算得到的。
  • TreeSet会根据元素的自然顺序或自定义的比较器顺序对元素进行排序。

性能: 

  • HashSet的性能通常比较好,它提供了O(1)的常数时间复杂度的插入、删除和查找操作。
  • LinkedHashSet的插入、删除和查找操作的性能稍微低于HashSet,因为它还需要维护插入顺序。
  • TreeSet提供了O(log n)的时间复杂度的插入、删除和查找操作,它的性能较HashSet和LinkedHashSet要低。

        总而言之,HashSet适用于需要快速插入、删除和查找操作的场景;LinkedHashSet适用于需要保持插入顺序的场景;TreeSet适用于需要对元素进行排序的场景。

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

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

相关文章

北京兼职挣外快,不知道怎么交税?

1.将甲方给的合同打印两份&#xff0c;都签字画押 2.微信搜索对应 区的税务进行预约 3.地址一般直接搜那个去的税务局&#xff0c;可以搜到我们预约对应的地方 4.预约完成&#xff0c;携带身份证原件&#xff0c;身份证复印件&#xff0c;打印出来的合同一份&#xff0c;去了大…

C/C++ - 内存管理(C++)

堆栈 C中的栈和堆是用于存储变量和对象​​的两个主要内存区域。栈是一种自动分配和释放内存的区域&#xff0c;用于存储局部变量和函数调用的上下文。栈上的内存分配和释放是自动进行的&#xff0c;无需手动管理。堆是动态分配内存的区域&#xff0c;用于存储动态创建的对象和…

【Linux】Linux下多线程

需要云服务器等云产品来学习Linux的同学可以移步/–>腾讯云<–/官网&#xff0c;轻量型云服务器低至112元/年&#xff0c;优惠多多。&#xff08;联系我有折扣哦&#xff09; 文章目录 1. 前置&#xff1a;进程地址空间和页表1.1 如何看待进程地址空间和页表1.2 虚拟地址…

Python算法题集_和为K的子数组

本文为Python算法题集之一的代码示例 题目560&#xff1a;和为K的子数组 说明&#xff1a;给你一个整数数组 nums 和一个整数 k &#xff0c;请你统计并返回 该数组中和为 k 的子数组的个数 。 子数组是数组中元素的连续非空序列。 示例 1&#xff1a; 输入&#xff1a;nu…

AS自治系统中的路由协议---RIP、OSPF、BGP

一、AS --- 自治系统 将网络分块管理 --- 由单一的机构或组织所管理 的一系列IP网络及其设备的集合 AS的管理&#xff1a;为了方便对AS进行管理&#xff0c;我们给AS设计了一个编号称为AS 号 --- 16位二进制构成 --- 0 - 65535 ---- 目前也存在拓展版的AS 号 --- 32位二进制构…

计网Lesson12 - UDP客户服务器模型和UDP协议

文章目录 丢个图在这&#xff0c;实在不是很明白在讲啥&#xff0c;等学完网编的我归来狠狠拿下它

GitHub 上传文件夹到远程仓库、再次上传修改文件、如何使用lfs上传大文件、github报错一些问题

按照大家的做法&#xff0c;把自己遇到的问题及解决方案写出来&#xff08;注意&#xff1a;Error里面有些方法有时候我用可以成功&#xff0c;有时候我用也不能成功&#xff0c;写出来仅供参考&#xff0c;实在不行重头再clone&#xff0c;add&#xff0c;commit&#xff0c;p…

Java强训day9(选择题编程题)

选择题 class Person {String name "No name";public Person(String nm) {name nm;} } class Employee extends Person {String empID "0000";public Employee(String id) {super(" ");//要调用父类的有参构造方法否则报错empID id;} } pu…

STM32 串口协议简明教程

前言 本文旨在介绍STM32单片机串口协议的使用。 主要是为了个人复习&#xff0c;一段时间没用&#xff0c;就容易忘记。因此在文章中也不会出现串口的原理等讲解。 本文的重点是利用CubeMX实现一个最基本的串口模板&#xff0c;从而能够在往后的各个项目中得到运用。 本文使用…

老龄化对投资意味着什么?

1月15日&#xff0c;国务院办公厅印发《关于发展银发经济增进老年人福祉的意见》从4个方面提出26项举措&#xff0c;为我国首个以“银发经济”命名的政策文件。 近期&#xff0c;国信证券分析师王开发布题为《银发经济再思考&#xff1a;老龄化对投资的影响》的报告&#xff0…

Java8-Stream 流基本应用-groupBy进行分组

groupBy进行分组 Testpublic void testStreamGroupBy(){List<UserInfoModel> resultnew ArrayList<>();for (int i 0; i < 10; i) {UserInfoModel usernew UserInfoModel();user.setUserId(i"");user.setUserName("kangshihang");result.a…

探索设计模式的魅力:深入了解适配器模式-优雅地解决接口不匹配问题

设计模式专栏&#xff1a;http://t.csdnimg.cn/nolNS 目录 一、引言 1. 概述 2. 为什么需要适配器模式 3. 本文的目的和结构 二、简价 1. 适配器模式的定义和特点 定义 特点 2. 适配器模式的作用和适用场景 作用 适用场景 3. 适配器模式与其他设计模式的比较 三、适配…

代码增强LLM

大模型时代的语言模型&#xff08;LLM&#xff09;不仅在尺寸上变得更大了&#xff0c;而且训练数据也同时包含了自然语言和形式语言&#xff08;代码&#xff09;。作为人类和计算机之间的媒介&#xff0c;代码可以将高级目标转换为可执行的中间步骤&#xff0c;具有语法标准、…

Java 与 JavaScript的区别

Java 与 JavaScript的区别 Java 与 JavaScript&#xff1a;概述Java的特点JavaScript 的起源JavaScript 的特点Java 与 JavaScript&#xff0c;哪个更好&#xff1f;JavaScript 与 Java 相似吗&#xff1f;Java 与 JavaScript 的区别JavaScript 在服务器端的运行方式是怎样的&a…

线程锁多线程的复习

线程 实现方式3种乐观锁&悲观锁线程池线程池总结 进程:是正在运行的程序 线程:是进程中的单个顺序控制流,是一条执行路径 实现方式3种 1.Thread //步骤一:定义一个继承Thread的类 //步骤二:再定义的类中重写run()方法 //步骤三:创建定义类对象 //步骤四:启动线程 class M…

【数据分析】numpy基础第一天

文章目录 前言本文代码&#xff1a;使用jupyter notebook打开本文的代码操作示例步骤1.打开Anaconda Powershell Prompt步骤2.复制代码文件地址步骤3.在Anaconda Powershell Prompt中打开jupyter notebook步骤3.5.解决一个可能的问题步骤4.在浏览器中查看ipynb文件步骤5.运行代…

85.网游逆向分析与插件开发-物品使用-物品使用的逆向分析与C++代码的封装

内容参考于&#xff1a;易道云信息技术研究院VIP课 上一个内容&#xff1a;项目需求与需求拆解-CSDN博客 码云地址&#xff08;ui显示角色数据 分支&#xff09;&#xff1a;https://gitee.com/dye_your_fingers/sro_-ex.git 码云版本号&#xff1a;453dd83d54140d2e1ee65c9…

量化交易学习3(量化择时策略)

1 什么是量化择时 量化择时策略&#xff0c;简单来说&#xff0c;就是采用数量化分析方法&#xff0c;利用单个或多个技术指标的组合&#xff0c;来对交易标的股票或股票指数进行低买高卖的操作&#xff0c;期望获得超越简单买入持有策略的收益风险表现。 量化择时策略的核心…

网络防御安全知识(第三版)

配置黑洞路由 --- 黑洞路由即空接口路由&#xff0c;在NAT地址池中的地址&#xff0c;建议配置达到这个地址指 向空接口的路由&#xff0c;不然&#xff0c;在特定环境下会出现环路。&#xff08;主要针对地址池中的地址和出接口地址 不再同一个网段中的场景。&#xff09; …

二手交易|校园二手交易小程序|基于微信小程序的闲置物品交易平台设计与实现(源码+数据库+文档)

校园二手交易小程序目录 目录 基于微信小程序的闲置物品交易平台设计与实现 一、前言 二、系统功能设计 三、系统实现 1、用户信息管理 2、商品信息管理 3、公告信息管理 4、论坛信息管理 四、数据库设计 1、实体ER图 五、核心代码 六、论文参考 七、最新计算机毕…