set集合

2023-12-27 16:08:58

Set集合

Set集合的介绍

  • 概述:Set 是一个接口,与 List 类似,都需要通过实现类来对其进行操作

  • Set 集合的特点

    • 不包含重复的元素

    • 没有带索引的方法,所以不能使用普通 for 循环遍历

demo:Set集合的使用
在这里插入图片描述

哈希值

哈希值:是 JDK 根据对象的 地址 或者 字符串 或者 数值 计算出来的 int 类型的数值

Object 对象中就有一个方法可以获取对象的哈希值:public int hashCode()

  • 对象的哈希值特点

    • 同一个对象多次调用 hashCode() 方法,得到的返回值是相同的

    • 默认情况下,不同对象的哈希值是不同的

    • 但是可以通过重写 hashCode() 方法来实现不同对象的哈希值相同

demo 测试不同类的哈希值
在这里插入图片描述

HashSet

  • HashSet 集合特点

    • 底层数据结构是哈希表

    • 对集合的迭代顺序不做任何保证,也就是说不能保证存储和读取的顺序一直

    • 没有带有索引为参数的方法,也就是说不能使用普通的 for 循环对其进行遍历

    • 由于是 set 集合,所以不包含重复的元素

demo —双色球(Set)版

package com.itxiaosi.demo01;

import java.util.HashSet;
import java.util.Random;
import java.util.Set;
import java.util.TreeSet;

/**
 * @Classname : demo04
 * @Description : TODO 双色球 (Set版)
 * @Author : lin_refuel@qq.com
 */
public class demo04 {
    public static void main(String[] args) {
        //随机值产生对象
        Random ran = new Random();
        // 蓝色球1-16
        int blue = ran.nextInt(16)+1;
        // 红色球 6个 1-33之间的数
        // Set<Integer> red = new HashSet<>();
        Set<Integer> red = new TreeSet<>();//TreeSet是默认排序的
        //循环放入集合
        while(red.size()<6){
            int red01 = ran.nextInt(33)+1;
            red.add(red01);//Set集合不能存在重复值
        }
        System.out.println("红球" + red);
        System.out.println("篮球" + blue);
    }
}

重写Hashcode和equals

  • 去重原理

    先对比 hashCode 如果相同的话,在对比 equals 的内容,这两个方法经常需要在子类中进行重写

    demo:创建一个学生类,重新Hashcode和equals

package com.itxiaosi.demo01;

import java.util.Objects;

/**
 * @Classname : Student
 * @Description : TODO 学生类对象
 * @Author : lin_refuel@qq.com
 */
public class Student {
    //学生两个基本属性
    private String name; //姓名
    private int age; //年龄

    //两个构造方法

    public Student() {
    }

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

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

    
    //重写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 age == student.age && Objects.equals(name, student.name);
    }
   //重写 hasCode
    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
}

demo:测试去重复的学生类对象

package com.itxiaosi.demo01;

import java.util.HashSet;

/**
 * @Classname : demo05
 * @Description : TODO HashSet 存储不同学生对象,重写Hashcode和equals
 * @Author : lin_refuel@qq.com
 */
public class demo05 {
    public static void main(String[] args) {
          //一个空的HashSet
        HashSet<Student> stuHAS = new HashSet<>();
        //调用add添加成员
        stuHAS.add(new Student("黄固",22));
        stuHAS.add(new Student("欧阳锋",23));
        stuHAS.add(new Student("段智兴",25));
        stuHAS.add(new Student("洪七公",27));
        stuHAS.add(new Student("黄固",22));
        //遍历stuHAS
        for (Student stuHA : stuHAS) {
            System.out.println(stuHA);
        }
    }
}

LinkedHashSet的使用

  • LinkedHashSet 集合特点

    • LinkedHashSet 是哈希表和链表实现的 Set 接口,具有可预测的迭代顺序

    • 有链表保证元素有序,也就是说元素的存储和读取顺序是一致的

    • 由哈希表保证元素的唯一性,也就是说没有重复的元素

demo

package com.itxiaosi.demo01;

import java.util.LinkedHashSet;

/**
 * @Classname : demo06
 * @Description : TODO LinkedHashSet的使用
 * @Author : lin_refuel@qq.com
 */
public class demo06 {
    public static void main(String[] args) {
        //定义一个空的LinkedHashSet
        LinkedHashSet<String> set = new LinkedHashSet<>();
        //添加元素
        set.add("黄固");
        set.add("欧阳锋");
        set.add("段智兴");
        set.add("洪七公");
        set.add("王重阳");
        //通过迭代器进行遍历
        for (String s : set) {
            System.out.println(s);
        }
    }
}

TreeSet的使用

  • TreeSet 集合特点

    • 有序元素,这里的顺序不是值存储和读取的顺序,而是按照一定的规则进行排序,具体排序方式取决于实例化对象时的构造方法

      1. TreeSet():根据元素的自然顺序进行排序

      2. TreeSet(Comparator comparator):根据指定的比较器进行排序

    • 没有带索引的方法,所以不能使用普通 for 循环遍历

    • 由于是 Set 集合,所以不存在重复的元素

TreeSet的使用

TreeSet是自带排序的,默认是从小到大进行排序

package com.itxiaosi.demo01;

import java.util.TreeSet;

/**
 * @Classname : demo07
 * @Description : TODO Tree集合的自然规则
 * @Author : lin_refuel@qq.com
 */
public class demo07 {
    public static void main(String[] args) {
        //Tree集合
        TreeSet<Integer> tree = new TreeSet<>();
        //添加元素,打乱顺序
        tree.add(3);
        tree.add(31);
        tree.add(6);
        tree.add(5);
        tree.add(1);
        tree.add(33);
        System.out.println(tree);//[1, 3, 5, 6, 31, 33]
    }
}

TreeSet排序学生类对像

通过接口的方式进行实现

定义一个学生类,作为Comparable接口的实现类,重写接口里面的方法CompareTo

package com.itxiaosi.demo02;

/**
 * @Classname : Student
 * @Description : TODO 学生类
 * @Author : lin_refuel@qq.com
 */
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;
    }

    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;
    }

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

    @Override
    public int compareTo(Student o) {
        //return 0; // TODO 返回值为0默认两个对像是相同的,不会进行添加
        //return 1;//TODO 返回值为正数,顺序进行排序
        //return -1;//TODO 返回值为负数,逆序进行排序
        // TODO 按照年龄进行排序
        int res = this.getAge() - o.getAge();//两个人的年龄差,年龄从小往大进行排序
        //TODO 如果年龄相同,比较名字是否相同,compareTo是比较字符串大小的
        return res == 0?this.getName().compareTo(o.getName()):res;
    }
}

比较器的设置

TreeSet集合是自己调用比较器的,当存储的是对象时无法直接比较,需要对象里面重写比较器

package com.itxiaosi.demo02;

import java.util.TreeSet;

/**
 * @Classname : demo02
 * @Description : TODO TreeSet集合存储学生类对像,设置比较器排序方式
 * @Author : lin_refuel@qq.com
 */
public class demo02 {
    public static void main(String[] args) {
        TreeSet<Student> StuSet = new TreeSet<>();//学生类TreeSet集合
        //添加学生信息
        StuSet.add(new Student("Andy",17));
        StuSet.add(new Student("rocky",14));
        StuSet.add(new Student("lucy",15));
        StuSet.add(new Student("Licinius",16));
        StuSet.add(new Student("messi",17));

        // 通过迭代器进行遍历
        for (Student student : StuSet) {
            System.out.println(student);
        }
    }
}
匿名内部的方式进行比较学生类对象

学生类对象

package com.itxiaosi.demo02;

/**
 * @Classname : Student02
 * @Description : TODO 学生类对象02
 * @Author : lin_refuel@qq.com
 */
public class Student02 {
    //定义两个学生的属性
    private String name;
    private int age;

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

    public Student02() {
    }

    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;
    }

    @Override
    public String toString() {
        return "Student02{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

匿名内部类实现

package com.itxiaosi.demo02;

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

/**
 * @Classname : demo01
 * @Description : TODO TreeSet比较学生类对象的第二种方式
 * @Author : lin_refuel@qq.com
 */
public class demo01 {
    public static void main(String[] args) {
        //学生类集合
        TreeSet<Student> StuSet = new TreeSet<>(new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                //按照年龄方式进行比较
                int res = o2.getAge() - o1.getAge();//从大往小排序
                return res == 0?o1.getName().compareTo(o2.getName()):res;
            }
        });
        // 添加成员
        StuSet.add(new Student("小白",17));
        StuSet.add(new Student("卢卡",17));
        StuSet.add(new Student("小蓝",18));
        StuSet.add(new Student("小红",15));
        StuSet.add(new Student("小白",16));
        //迭代器进行遍历
        Iterator<Student> it = StuSet.iterator();
        while(it.hasNext())
            System.out.println(it.next());
    }
}

文章来源:https://blog.csdn.net/2301_81153022/article/details/135201614
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。