Java中的Set

java常用集合之Set 目录Set集合的基础知识Set集合的实现类一.HashSet二.TreeSet 特点:1.无序性:set集合是无序的2.不重复:set集合是不可以重复的遍历方法:foreach,迭代器扩容: 初始容量16,负载因子0.75,扩容增量1倍Set和List一样属于接口,无法直接创建实例化对象,需要实现类来set接口。关系图HashSet实现Set接口,底层由HashMap来实现,为哈希表结构,新增元素相当于HashMap的key,value默认为一个固定的Object。当有元素插入的时候,会计算元素的hashC 阅读详情
Set接口中的方法基本上与Collection的API一致

Set系列集合

  1. 无序:存取顺序不一致
  2. 不重复:可以去除重复
  3. 无索引:没有带索引的方法,所以不能使用普通的for循环遍历,也不能通过索引来获取元素

遍历方法:
-------------迭代器
-------------增强for
-------------Lambda表达式
代码实现(同时展现了Set的三个特性):

package com.zzu.mySet;

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

public class A01_SetDemo1 {
    public static void main(String[] args) {
        /*
            利用Set系列的集合 添加字符串 并使用多种方式遍历
            迭代器
            增强for
            Lambda表达式
         */

        //1.创建一个Set集合的对象
        Set<String> s = new HashSet<>();

        //2.添加元素
        //Set不重复
        //如果元素是第一次添加 添加成功 返回true
        //如果元素是第二次添加 添加失败 返回false
        boolean r1 = s.add("jh");
        boolean r2 = s.add("jh");
        s.add("yy");
        s.add("jj");

        System.out.println(r1);//true
        System.out.println(r2);//false

        //3.打印集合
        //Set无序
        System.out.println(s);//[yy, jj, jh]

		//Set无索引
        //迭代器遍历
        Iterator<String> it = s.iterator();
        while(it.hasNext()){
            String str = it.next();
            System.out.print(str+" ");
        }//yy jj jh

        //增强for
        for (String str : s) {
            System.out.print(str+" ");
        }//yy jj jh

        //Lambda表达式
        s.forEach(str-> System.out.print(str+" "));//yy jj jh

    }
}

Set集合的实现类

HashSet:无序、不重复、无索引
LinkedHashSet:有序、不重复、无索引
TreeSet:可排序、不重复、无索引

1. HashSet

HashSet 底层原理

  1. HashSet集合底层采取哈希表存储数据
  2. 哈希表是一种对于增删改查数据性能都较好的结构

哈希表组成

  1. JDK8之前:数组+链表
  2. JDK8开始:数组+链表+红黑树

哈希值

  1. 根据hashCode方法算出来的int类型的整数
  2. 该方法定义在Object类中,所有对象都可以调用,默认使用地址值进行计算
  3. 一般情况下,会重写hashCode方法,利用其内部的属性值计算哈希值

对象的哈希值特点

  1. 如果没有重写hashCode方法,不同的对象计算出哈希值是不同的
  2. 如果已经重写hashCode方法,不同的对象只要属性值相同,计算出的哈希值就是一样的
  3. 在小部分情况下,不同属性值或者不同的地址值计算出来的哈希值也有可能一样(哈希碰撞)

对于自定义类需要重写hashCode和equlas方法,对于String和Integer,java在底层已经写过了(上面对三种遍历方式讲解的同时已经演示了基本对象String、Integer的添加入Set的不重复性)。

这里代码演示自定义类:

package com.zzu.mySet;

import java.util.Objects;

public class Student {
    private String name;
    private int age;

    public Student() {
    }

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

    /**
     * 获取
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取
     * @return age
     */
    public int getAge() {
        return age;
    }

    /**
     * 设置
     * @param age
     */
    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return age == student.age && Objects.equals(name, student.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }

    public String toString() {
        return "Student{name = " + name + ", age = " + age + "}";
    }
}

package com.zzu.mySet;

public class A02_HashSetDemo1 {
    public static void main(String[] args) {
    /*
        哈希值:
        对象的整数表现形式
        1.如果没有重写hashCode方法,不同的对象计算出哈希值是不同的
        2.如果已经重写hashCode方法,不同的对象只要属性值相同,计算出的哈希值就是一样的
        3.在小部分情况下,不同属性值或者不同的地址值计算出来的哈希值也有可能一样(哈希碰撞)
     */

        //1.创建对象
        Student s1 = new Student("jh",19);
        Student s2 = new Student("jh",19);

        //2.如果没有重写hashCode方法,不同的对象计算出哈希值是不同的
        //  如果已经重写hashCode方法,不同的对象只要属性值相同,计算出的哈希值就是一样的
        //  这里已经重写
        System.out.println(s1.hashCode());//106070
        System.out.println(s2.hashCode());//106070

        //在小部分情况下,不同属性值或者不同的地址值计算出来的哈希值也有可能一样
        //哈希碰撞  这里碰巧有两个例子
        System.out.println("abc".hashCode());//96354
        System.out.println("acD".hashCode());//96354

    }
}

HashSet底层

(1).原理分析

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

(2).上述底层原理可引出三个问题答案,这里简单说明,读者通过底层原理理解参悟

1.HashSet为什么存和取的顺序不一样
数据可能以链表方式存储,但是每个链表之间没有联系,并且可能含有红黑树,各个结构之间没有联系,下面LinkedHashSet区别就是数据是否有联系。

2.HashSet为什么没有索引
两种数据结构的存在,索引已经没有太大意义。

3.HashSet是利用什么机制保证数据去重的
重写hashCode和equals方法

(3).小练习
import java.util.Objects;

/*
类Student 重写其equals(),toString()方法 满足:
    (1).比学号、姓名、性别
    (2).System.out.println(new Student())输出信息:"学号:,姓名:(性别)"
    (3).数组存放,实现头插、学号序输出、不重复的输入输出
 */
public class Student {
    private String id;
    private String name;
    private String sex;

    public Student() {
    }

    public Student(String id, String name, String sex) {
        this.id = id;
        this.name = name;
        this.sex = sex;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    //重写之后的equals方法 比较的就是对象内部的属性值
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return Objects.equals(id, student.id) && Objects.equals(name, student.name) && Objects.equals(sex, student.sex);
    }

    //重写hashCode方法
    @Override
    public int hashCode() {
        return Objects.hash(id, name, sex);
    }

    //重写之后的toString方法 打印的是属性值
    @Override
    public String toString() {
        return  "学号:" + id  + ", 姓名:" + name + "("+sex+")";
    }
}
import java.util.*;

public class Test {
    public static void main(String[] args) {

        //测试toString equals方法
        Student s1 = new Student("202107","jh","m");
        Student s2 = new Student("202107","yy","f");
        //重写之后的toString() 打印的是内容
        System.out.println("s1.toString():"+s1.toString());
        System.out.println("s1.toString():"+s2.toString());
        //重写之后的equals方法 比较的是内容
        System.out.println("s1.equals(s2):"+s1.equals(s2));

        //1.创建一个链式集合
        LinkedList<Student> list = new LinkedList<>();

        //2.数组生成7个学生信息
        String[][] arrStu = {{"202101","张三","m"},{"202105","李四","m"},{"202101","张三","m"},
                {"202101","张三","m"},{"202103","王小","f"},{"202102","王小","f"},{"202105","李四","m"}};

        //3.生成学生对象 并且放入集合中
        for (int i = 0; i < arrStu.length; i++) {
            Student stu = new Student(arrStu[i][0],arrStu[i][1],arrStu[i][2]);
            list.add(stu);
        }

        //4.头部插入对象 并输出list对象信息
        Student s = new Student("202104","小七","f");
        list.add(0,s);
        list.forEach(str-> System.out.println(str));

        //5.学号序输出list对象信息
        list.sort((a,b)->a.getId().compareTo(b.getId()));
        System.out.println("--------idSort--------");
        list.forEach(str-> System.out.println(str));

        //6.创建一个set集合 接收数据 重写hashCode方法保证键值唯一
        Set<Student> set = new HashSet<>(list);
        System.out.println("----------Set---------");
        set.forEach(str-> System.out.println(str));
        //添加数据  返回值看是否添加成功
        Student stu = new Student("202101","张三","m");
        boolean result = set.add(stu);
        System.out.println("添加数据:"+result);
        //打印最终结果
        System.out.println("--------endSet--------");
        set.forEach(str-> System.out.println(str));
    }

}

s1.toString():学号:202107, 姓名:jh(m)
s1.toString():学号:202107, 姓名:yy(f)
s1.equals(s2):false
学号:202104, 姓名:小七(f)
学号:202101, 姓名:张三(m)
学号:202105, 姓名:李四(m)
学号:202101, 姓名:张三(m)
学号:202101, 姓名:张三(m)
学号:202103, 姓名:王小(f)
学号:202102, 姓名:王小(f)
学号:202105, 姓名:李四(m)
--------idSort--------
学号:202101, 姓名:张三(m)
学号:202101, 姓名:张三(m)
学号:202101, 姓名:张三(m)
学号:202102, 姓名:王小(f)
学号:202103, 姓名:王小(f)
学号:202104, 姓名:小七(f)
学号:202105, 姓名:李四(m)
学号:202105, 姓名:李四(m)
----------Set---------
学号:202101, 姓名:张三(m)
学号:202105, 姓名:李四(m)
学号:202104, 姓名:小七(f)
学号:202102, 姓名:王小(f)
学号:202103, 姓名:王小(f)
添加数据:false
--------endSet--------
学号:202101, 姓名:张三(m)
学号:202105, 姓名:李四(m)
学号:202104, 姓名:小七(f)
学号:202102, 姓名:王小(f)
学号:202103, 姓名:王小(f)

2.LinkedHashSet(直接继承HashSet)

(1).LinkedHashSet集合的特点和原理

  1. 有序、不重复、无索引
  2. 底层基于哈希表,使用双链表记录添加顺序

在以后使用中,默认使用HashSet(效率高),如果要求去重且存取有序,才使用LinkedHashSet。

(2).LinkedHashSet底层原理

阿玮百万PPT:在这里插入图片描述
这里双链表是上一次加入的元素与这一次加入的元素进行的链接,互相存储内存值。也正是这种链接使得LinkedHashSet有序。

package com.zzu.mySet;

import java.util.Objects;

public class Student {
    private String name;
    private int age;

    public Student() {
    }

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

    /**
     * 获取
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取
     * @return age
     */
    public int getAge() {
        return age;
    }

    /**
     * 设置
     * @param age
     */
    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return age == student.age && Objects.equals(name, student.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }

    public String toString() {
        return "Student{name = " + name + ", age = " + age + "}";
    }
}
package com.zzu.mySet;

import java.util.LinkedHashSet;

public class A03_LinkedHashSetDemo {
    public static void main(String[] args) {
        //1.创建几个学生对象
        Student s1 = new Student("jh",19);
        Student s2 = new Student("yy",20);
        Student s3 = new Student("jj",20);
        Student s4 = new Student("jh",19);

        //2.创建集合的对象
        LinkedHashSet<Student> lhs = new LinkedHashSet<>();

        //3.添加元素
        System.out.println(lhs.add(s2));//true
        System.out.println(lhs.add(s1));//true
        System.out.println(lhs.add(s3));//true
        System.out.println(lhs.add(s4));//false 已经重写hashCode equals 不重复

        //4.打印集合(有序)
        System.out.println(lhs);//[Student{name = yy, age = 20}, Student{name = jh, age = 19}, Student{name = jj, age = 20}]
    }
}

3.TreeSet

(1).TreeSet的特点

  1. 不重复、无索引、可排序
  2. 可排序:按照元素的默认规则(从小到大)排序
  3. TreeSet集合底层是基于红黑树的数据结构实现排序的,增删查改性能都较好

(2).TreeSet集合默认的规则

  1. 对于数值类型:Integer,Double,默认按从小到大的顺序进行排序
  2. 对于字符、字符串类型:按照字符在ASCLL码表中的数字升序进行排序

(3).排序

<1>.默认规则排序
package com.zzu.mySet;

import java.util.Iterator;
import java.util.TreeSet;
import java.util.function.Consumer;

public class A04_TreeSetDemo1 {
    public static void main(String[] args) {
        /*
            需求:利用TreeSet存储整数并排序(小数、字符、字符串道理一样)
         */
        //1.创建对象
        TreeSet<Integer> ts = new TreeSet<>();

        //2.添加元素
        ts.add(3);
        ts.add(2);
        ts.add(4);
        ts.add(1);
        ts.add(5);

        //3.打印集合(有序)
        System.out.println(ts);//[1, 2, 3, 4, 5]

        //4.遍历集合(三种遍历)
        //迭代器
        Iterator<Integer> it = ts.iterator();
        while(it.hasNext()){
            int i = it.next();
            System.out.print(i+" ");
        }
        System.out.println("\n-------------------");

        //增强for
        for(int i:ts){
            System.out.print(i+" ");
        }
        System.out.println("\n-------------------");

        //Lambda
        ts.forEach(new Consumer<Integer>() {
            @Override
            public void accept(Integer i) {
                System.out.print(i+" ");
            }
        });
        System.out.println();
        //即
        ts.forEach(i-> System.out.print(i+" "));
    }
}

[1, 2, 3, 4, 5]
1 2 3 4 5 
-------------------
1 2 3 4 5 
-------------------
1 2 3 4 5 
1 2 3 4 5 
<2>.自定义对象排序

先了解一下红黑树的添加节点的基本规则,这里大家没基础应该先了解一下红黑树。
在这里插入图片描述

在这里插入图片描述
两种排序使用规则:默认使用第一种,如果第一种不能满足当前需求,就使用第二种。

1.TreeSet的第一种排序

排序规则/自然排序:javabean类实现Comparable接口制定比较规则,这里通过自定义类中compareTo方法的重写,运用比较对红黑树存储数据进行更新。

public int compareTo(E e)
返回值:

  1. 负数:认为要添加的元素是小的,存左边
  2. 正数:认为要添加的元素是大的,存右边
  3. 0:认为要添加的元素已经存在,舍弃
package com.zzu.mySet;

import java.util.TreeSet;

public class A05_TreeSetDemo2 {
    public static void main(String[] args) {
        /*
            需求:创建TreeSet集合,并添加3个学生对象
            学生对象属性:
                姓名、年龄
                要求按照学生年龄排序
                同年龄按照姓名字母排列(暂不考虑中文)
                同姓名,同年龄认为是一个人

            方式一:
                默认的排序规则/自然排序
                Student实现Comparable接口,重写里面的抽象方法,制定比较规则
         */

        //1.创建三个学生对象
        Student s1 = new Student("jh",19);
        Student s2 = new Student("yy",20);
        Student s3 = new Student("jj",19);

        //2.创建集合对象
        TreeSet<Student> ts = new TreeSet<>();

        //3.添加元素
        ts.add(s1);
        ts.add(s2);
        ts.add(s3);

        //4.打印集合
        System.out.println(ts);
    }
}

public class Student implements Comparable<Student> {
    private String name;
    private int age;

    public Student() {
    }

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

    /**
     * 获取
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取
     * @return age
     */
    public int getAge() {
        return age;
    }

    /**
     * 设置
     * @param age
     */
    public void setAge(int age) {
        this.age = age;
    }

    public String toString() {
        return "Student{name = " + name + ", age = " + age + "}";
    }

    @Override
    //this:表示当前要添加的元素
    //o:表示已经在红黑树存在的元素

    //返回值:
    //1. 负数:认为要添加的元素是小的,存左边
    //2. 正数:认为要添加的元素是大的,存右边
    //3. 0:认为要添加的元素已经存在,舍弃
    public int compareTo(Student o) {
        //这里打印this和o直观地看到排序的过程
        System.out.println("-------------");
        System.out.println("this:" + this);
        System.out.println("o:" + o);
        //指定排序的规则
        //这里先看年龄再看姓名
        //年龄相同则比较姓名
        //都相同则舍弃
        int age = this.age-o.age;
        if(age!=0) return age;
        else return this.name.compareTo(o.name);
    }
}

-------------
this:Student{name = jh, age = 19}
o:Student{name = jh, age = 19}
-------------
this:Student{name = yy, age = 20}
o:Student{name = jh, age = 19}
-------------
this:Student{name = jj, age = 19}
o:Student{name = jh, age = 19}
-------------
this:Student{name = jj, age = 19}
o:Student{name = yy, age = 20}
[Student{name = jh, age = 19}, Student{name = jj, age = 19}, Student{name = yy, age = 20}]
2.TreeSet的第二种排序

比较器排序:创建TreeSet对象的时候,传递比较器Comparator制定规则

package com.zzu.mySet;

import java.util.Comparator;
import java.util.TreeSet;

public class A06_TreeSetDemo3 {
    public static void main(String[] args) {
        /*
            需求:请自行选择比较器排序和自然排序两种方式
            要求:存入无个字符串,"a","jh","yy","yjj","jzqh"
            按照长度排序:如果一样长则按照首字母排序

            这里String类中底层有写好的函数进行ASCLL码比较,很显然第一种方式无法实现要求
            采取第二种排序方式:比较器排序
         */

        //1.创建集合
        //o1:表示当前要添加的元素
        //o2:表示已经在红黑树存在的元素
        //返回值规则跟第一种方式是一样的
/*        TreeSet<String> ts = new TreeSet<>(new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                //按照长度排序
                int i = o1.length()-o2.length();
                //如果一样长度则按照首字母排序
                return i==0?o1.compareTo(o2):i;
            }
        });*/
        TreeSet<String> ts = new TreeSet<>((o1, o2)-> {
                //按照长度排序
                int i = o1.length()-o2.length();
                //如果一样长度则按照首字母排序
                return i==0?o1.compareTo(o2):i;
        });

        //2.添加元素
        ts.add("a");
        ts.add("yy");
        ts.add("jh");
        ts.add("jzqh");
        ts.add("yjj");

        //3.打印集合
        System.out.println(ts);//[a, jh, yy, yjj, jzqh]
    }
}

<3>.小练习
package com.zzu.mySet;

import java.util.TreeSet;

public class A07_TreeSetDemo4 {
    public static void main(String[] args) {
        /*
            需求:创建五个学生对象
            属性:(姓名、年龄、语文成绩、数学成绩、英语成绩)
                按照总分从高到低输出到控制台
                如果总分一样 按照语文成绩排
                如果语文成绩一样 按照数学成绩排
                如果数学成绩一样 按照英语成绩排
                如果英文成绩一样 按照年龄大小排
                如果年龄一样 按照姓名的字母顺序排
                如果都一样 认为是同一个学生 不存

                第一种:默认排序/自然排序
                第二种:比较器排序

                默认情况下,用第一种排序方式,如果第一种不能满足当前的需求,采取第二种方式

         */

        //1.创建学生对象
        Student2 s1 = new Student2("zhangsan",23,90,99,50);
        Student2 s2 = new Student2("lisi",24,90,90,50);
        Student2 s3 = new Student2("wangwu",25,80,99,50);
        Student2 s4 = new Student2("zhaoliu",26,66,76,86);
        Student2 s5 = new Student2("qianqi",27,77,78,87);

        //2.创建集合
        TreeSet<Student2> ts = new TreeSet<>();

        //3.添加元素
        ts.add(s1);
        ts.add(s2);
        ts.add(s3);
        ts.add(s4);
        ts.add(s5);

        //4.遍历集合
        for (Student2 stu : ts) {
            System.out.println(stu);
        }


    }
}

package com.zzu.mySet;

public class Student2 implements Comparable<Student2>{
    //姓名
    private String name;
    //年龄
    private int age;
    //语文成绩
    private int chinese;
    //数学成绩
    private int math;
    //英语成绩
    private int english;


    public Student2() {
    }

    public Student2(String name, int age, int chinese, int math, int english) {
        this.name = name;
        this.age = age;
        this.chinese = chinese;
        this.math = math;
        this.english = english;
    }

    /**
     * 获取
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取
     * @return age
     */
    public int getAge() {
        return age;
    }

    /**
     * 设置
     * @param age
     */
    public void setAge(int age) {
        this.age = age;
    }

    /**
     * 获取
     * @return chinese
     */
    public int getChinese() {
        return chinese;
    }

    /**
     * 设置
     * @param chinese
     */
    public void setChinese(int chinese) {
        this.chinese = chinese;
    }

    /**
     * 获取
     * @return math
     */
    public int getMath() {
        return math;
    }

    /**
     * 设置
     * @param math
     */
    public void setMath(int math) {
        this.math = math;
    }

    /**
     * 获取
     * @return english
     */
    public int getEnglish() {
        return english;
    }

    /**
     * 设置
     * @param english
     */
    public void setEnglish(int english) {
        this.english = english;
    }

    public String toString() {
        return "Student2{name = " + name + ", age = " + age + ", chinese = " + chinese + ", math = " + math + ", english = " + english + "}";
    }

    /*
    按照总分从高到低输出到控制台
    如果总分一样 按照语文成绩排
    如果语文成绩一样 按照数学成绩排
    如果数学成绩一样 按照英语成绩排
    如果英文成绩一样 按照年龄大小排
    如果年龄一样 按照姓名的字母顺序排
    如果都一样 认为是同一个学生 不存
     */
    @Override
    public int compareTo(Student2 o) {
        int sum1 = this.getChinese()+this.getMath()+this.getEnglish();
        int sum2 = o.getChinese()+o.getMath()+o.getEnglish();

        //比较两者总分
        int i = sum2 - sum1;
        //如果总分一样 按照语文成绩排
        i = i==0?o.getChinese()-this.getChinese():i;
        //如果语文成绩一样 按照数学成绩排
        i = i==0?o.getMath()-this.getMath():i;
        //如果数学成绩一样 按照英语成绩排(不需要比较了)
        //i = i==0?o.getEnglish()-this.getEnglish():i;
        //如果英文成绩一样 按照年龄大小排
        i = i==0?o.getAge()-this.getAge():i;
        //如果年龄一样 按照姓名的字母顺序排
        i = i==0?o.getName().compareTo(this.getName()):i;
        return i;
    }
}

Student2{name = qianqi, age = 27, chinese = 77, math = 78, english = 87}
Student2{name = zhangsan, age = 23, chinese = 90, math = 99, english = 50}
Student2{name = lisi, age = 24, chinese = 90, math = 90, english = 50}
Student2{name = wangwu, age = 25, chinese = 80, math = 99, english = 50}
Student2{name = zhaoliu, age = 26, chinese = 66, math = 76, english = 86}

4.使用场景

  1. 如果想对集合中的元素去重:用HashSet集合,基于哈希表的。(用的最多)
  2. 如果相应对集合中的元素去重,而且保证存取顺序:用LinkedHashSet集合,基于哈希表和双链表,效率低于HahSet。
  3. 如果想对集合中的元素进行排序:用TreeSet集合,基于红黑树。
Java中Set接口的用法详解 实现类底层结构顺序性允许null适用场景HashSet哈希表无序是高频访问、无需顺序的去重哈希表+链表维护插入顺序是按插入顺序遍历的去重集合TreeSet红黑树自然/自定义排序否需要排序或范围查询的集合通过合理选择实现类,可高效解决数据唯一性、排序及遍历需求。具体方法示例可参考Oracle官方文档或实际项目代码。 阅读详情

相关推荐

Java Set 数据结构

/ 将Map Key 转化为List。// 将Map Key 转化为List。

645

Java基础之Set

Java基础之Set

qq_45344586的博客 1万+

单细胞测序数据分析——细胞通讯 CellChat

cellchat

G2530051386的博客 1万+

Java Set集合详解

一:set集合框架体系图 二:set集合介绍 Set接口继承了Collection接口,含有许多常用的方法。 int size();返回集合的长度 boolean isEmpty();判断集合是否为空 boolean contains(Object o);是否包含某个值 boolean add(E e);添加元素 boolean remove(Object o);删除元素 Set接口的存储特点是无序不可重复,可以存放唯一一个null值,Set的常用实现类有HashSet,TreeSet。 Set集合的

qq_51751452的博客 2万+

AUTO-DL平台快速部署BEVFormer:Nuscenes数据集完整训练避坑指南

本文详细介绍了在AUTO-DL平台高效部署BEVFormer模型并利用Nuscenes数据集进行完整训练的实战指南。重点解析了平台数据管理、环境配置、数据集迁移解压、预处理及训练启动等全流程中的关键步骤与常见避坑技巧,帮助研究者和工程师快速复现这一前沿视觉感知模型,节省云端训练时间与成本。

weixin_29188043的博客 330

从零搭建ROS1导航小车(一):松灵SCOUT Mini底盘通讯配置与ROS包编译避坑指南

本文详细介绍了从零开始搭建ROS1导航小车的初始步骤,重点讲解松灵SCOUT Mini底盘的通讯配置与ROS包编译避坑指南。内容包括硬件连接、CAN通讯配置、ROS工作空间构建及编译优化等实用技巧,帮助开发者快速实现自主导航小车的通讯功能。

weixin_27014595的博客 188

java中的Set集合

上两片博客已经基本的介绍了一下java中的集合分类,list集合和泛型等知识,这篇再介绍一下单列集合中的另外一种集合,Set集合。 看到这篇但是没有看过前两篇的小伙伴可以点一下这里,看一下我之前写的博客。 java中的集合:Collection的简介,子接口List,以及两个实现类 java中的泛型:泛型的的概述,泛型的定义,泛型方法,泛型类,泛型接口,通配符等 好接下来我们进入正题: java...

Jack 2269

VM与欧姆龙PLC通讯设置实战:Fins TCP/UDP协议详解

本文详细解析了VM(VisionMaster)与欧姆龙PLC通过Fins TCP/UDP协议进行通讯的实战设置。内容涵盖网络配置、协议选择(TCP可靠性与UDP实时性)、VM端地址映射与数据点添加、以及数据接收解析流程,并提供了常见错误排查与高级调试技巧,帮助视觉与自动化工程师快速实现稳定可靠的工业通讯集成。

weixin_29172963的博客 327

《Set》Java中的Set用法(详细整理)

常见的Set类型:HashSet 特性:元素唯一,无序,可以含有空元素。 下面我们看示例: import java.util.HashSet; import java.util.Iterator; import java.util.Set; public class first { public static void main(String[] args) { Set<String> str = new HashSet<String>(); .

Zyy~的博客 3万+

保姆级教程:用Jetson Orin Nano和ROS2 Humble搞定PIXhawk 4飞控通信(含配置文件详解)

本文提供了一份详细的Jetson Orin Nano与PIXhawk 4飞控通信配置指南,涵盖硬件连接、ROS2 Humble环境搭建、MAVROS2配置及通信调试全流程。通过实战案例和配置文件详解,帮助开发者快速实现无人机上位机与飞控的稳定通信,适用于无人机开发与自动化控制场景。

weixin_33670786的博客 475

Pluto SDR新手避坑指南:从环境配置到第一个MATLAB收发程序(附完整代码)

本文为Pluto SDR新手提供全面的避坑指南,从硬件连接到MATLAB环境配置,再到第一个信号收发程序的实现。详细介绍了驱动安装、常见问题排查以及关键参数设置,帮助用户快速上手软件定义无线电(SDR)技术,并附有完整代码示例。

weixin_33168937的博客 325

Java中的Set(如果想知道Java中有关Set的知识点,那么只看这一篇就足够了!)

Java中的Set(如果想知道Java中有关Set的知识点,那么只看这一篇就足够了!)

秋刀鱼不做梦的编程日常 7566

构建高效的LLM应用测试框架

《构建高效的LLM应用测试框架》 关键词:LLM,测试框架,应用测试,效率优化,测试原理 摘要:本文将深入探讨构建高效LLM应用测试框架的必要性、方法与步骤,旨在为开发者提供一套系统化、可操作的测试解决方案,从而提升LLM

AI天才研究院 1046

java中set集合_Java中的Set集合

Set集合不允许包含相同的元素,如果试图把两个相同的元素加入同一个Set集合里面,则添加操作失败,add()方法返回false,且新元素不会被添加入。1.HashSet是Set的接口的典型实现,大多数时候使用Set集合就是使用这个实现类,HashSet按Hash算法来存储集合中的元素,因此具有很好的存取和查找性能。HashSet具有以下特点,不能保证元素的排列顺序,可能和添加的顺序不同;HashS...

weixin_39822184的博客 325

大厂硬件笔试机试题ASIC设计方向-卷3

本文提供了30道硬件工程师机试题目,涵盖数字逻辑、模拟电路、CMOS和信号处理等核心领域。选择题和判断题均配有详细解析,重点考察Verilog编程、CMOS特性、触发器设计、采样定理等知识点。题目难度适中但覆盖面广,如Verilog中阻塞/非阻塞赋值的区别、CMOS静态功耗来源、Nyquist采样定理、通用逻辑门判断等。备考建议强调掌握逻辑门设计、Verilog时序电路编写和CMOS特性理解。这些题目反映了华为等大厂硬件机试的典型考查内容,通过系统复习可有效提升机试成绩,为后续面试奠定基础。

启芯硬件的博客 542

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

java基础——java集合set详解

本文深入探讨了Java中的Set接口及其主要实现类,包括HashSet、LinkedHashSet和TreeSet。Set接口的核心特性是元素唯一性,适用于数据去重、成员检查等场景。文章详细介绍了Set的常用方法,如add、remove、contains等,并通过代码示例展示了如何使用这些方法。此外,文章还对比了不同Set实现类的特点和使用场景:HashSet适用于快速查找和插入,LinkedHashSet保持插入顺序,TreeSet则支持自动排序和范围查询。最后,文章总结了Set的三种主要遍历方式(增强型

qq_47980550的博客 4579

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

Java集合中的Set

想象一个图书管理员,他根据每本书的编号(哈希值)快速找到对应的书架。:图书管理员不仅根据编号放置书籍,还记录了书的添加顺序。:图书管理员是个整理狂,他按照书名的字母顺序排列书架。接下来,我们将逐一剖析这些实现的底层原理,并通过一个博客系统的实战 demo 来展示它们的实际应用。为了更深入地理解这些实现,我们来看看它们的简化源码(基于 OpenJDK 的实现)。就像一个俱乐部,每个成员(元素)都必须是唯一的。让我们通过一个实际的博客系统示例,展示如何使用不同。通过博客系统的实战 demo,我们看到了不同。

m0_73889530的博客 1155

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

Java Set集合

Set集合 Set接口是 Collection 的子接口。 Set集合不允许包含相同的元素。 如果添加相同的元素, add()返回返回FALSE, 新元素不会加入。 HashSet, TreeSet, EnumSet 是 Set 集合的三个实现类。 HashSet 的性能好于 TreeSet, 因为 TreeSet使用红黑树维护顺序。 LinkedHashSet比 HashSet略慢一点, 因为维护链表带来了额外开销。但是遍历会更快。 EnumSet是所有Set实现类中性能最好的。

yonggang7的专栏 3267

java中的Map和Set

常见的几种搜索比较适合静态类型的查找,一般不会对数据进行增删查改,而对现实中的查找,多数是变动的. 比如:对手机通讯录的增加联系人,删除联系人,更改联系人的联系方式.对于这中查找,上述的搜索方式明显不太适用了.而我们的Map和Set是一种适合动态查找的集合容器,有着明显的优势.所以接下来我们来了解一下搜索树。

weixin_75241711的博客 1078

Java Set 中的常用方法总结

Set是 Java 集合框架(Collection Framework)中最常用的接口之一,具有元素唯一、不允许重复的特性。无论你用HashSetTreeSet,它们都实现了Set接口,因此拥有大量共同的方法。这篇文章将全面总结Java Set 的常用方法并通过示例进行讲解,主要用于日常查询使用。1. 去重操作2. 判断是否包含某元素3. 交集、并集、差集// 并集// 交集// 差集4. 遍历(推荐方式)

经天纬地,格物致理 1413

Java中Map和Set

Java中的Map和Set,当你学会了Map其实就学会Set了

2301_81015455的博客 2051

java中set用法_java中set方法实例,java中set用法

之前给大家介绍一下set集合常用方法,下面就继续给大家介绍一下java中set方法实例,一起来了解一下吧。首先我们来了解一下set集合的特点吧!set集合不可以存储相同的元素,又因为它是一个抽象的接口,所以不可以直接实例化一个set对象,除此之外,这个接口主要继承于Collections接口,所以有一些Collection的一些常见的方法。下面是set集合常见方法:add( )-向集合中添加元素;...

weixin_39927508的博客 1955

如何在Java中将数组转换为Set

I would like to convert an array to a Set in Java. 我想将数组转换为Java中的Set。 There are some obvious ways o

xfxf996的博客 1万+

java中的set

常见的的set类型 HashSet: HashSet是采用hash表算法来实现的,其中的元素没有按顺序排列。(遍历时输出的元素的顺序是不可控的) TreeSet:采用的红黑树算法,进行排序。(遍历时输出的元素的顺序是默认是从小到大地输出) LinkedHashSet: LinkedHashSet正好介于HashSet和TreeSet之间,它也是一个hash表,但它同时维护了一个双链表来记录插入的顺序,基本方法的复杂度为O(1)。(遍历时输出元素的顺序等同新增时的顺序) 对于TreeSet如果元素是对象,

蹊源的奇思妙想的博客 6308

Java中的list和set有什么区别

Java中的list和set有什么区别 list与set方法的区别有:list可以允许重复对象和插入多个null值,而set不允许;list容器是有序的,而set容器是无序的等等。 Java中的集合共包含三大类,它们分别是Set(集),List(列表)以及Map(映射)。它们都处在java.util中并且都为接口。它们各自都有各自的实现类。Set的实现类主要有HashSet和TreeSet,List的实现类主要有ArrayList,LinkedList。接下来将为大家介绍这两大类之间的区别,具有一定的参考

sANsHiErHuA的博客 6562
上一篇: Java中的Map
下一篇: LeetCode1819: 序列中不同最大公约数的数目
天皓Oo
博客等级 码龄5年 337粉丝 61原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值