Set集合

1、Set集合

  Set接口也是Collection的子接口,Set接口没有提供额外的方法。Set集合支持的遍历方式也和Collection集合一样,使用foreach和Iterator遍历。

  Set集合不允许包含相同的元素,如果试图把两个相同的元素加入同一个Set集合,则添加操作失败,操作失败并不会报错,只是添加不成功而已。Set接口的常用实现类有:HashSetLinkedHashSetTreeSet

1.1 HashSet和LinkedHashSet

  HashSet是Set接口的典型实现类,大多数时候使用Set集合时都会使用这个实现类。

  HashSet和LinkedHashSet按Hash算法来存储集合中的元素,因此具有很好的存取和查找性能HashSet和LinkedHashSet集合判断两个元素相等的标准是两个对象通过hashCode方法比较,并且两个对象的equals方法返回值也相等。

  LinkedHashSet是HashSet的子类,它在HashSet的基础上,在结点中增加两个属性(before和after)以维护结点的前后添加顺序。LinkedHashSet插入性能略低于HashSet,但在迭代访问Set中的全部元素时有很好的性能。

  示例代码:

  HashSet添加元素的示例代码:

public class HashSetTest {
    public static void main(String[] args) {
        HashSet<String> set = new HashSet<>();
        set.add("张三");
        set.add("李四");
        set.add("王五");
        set.add("张三");//尝试添加重复元素

        System.out.println("元素个数:"+set.size());
        for (Object obj : set) {
            System.out.println(obj);
        }

    }
}

image-20221004160236033

  LinkedHashSet添加元素的示例代码:

public class LinkedHashSetTest {
    public static void main(String[] args) {
        LinkedHashSet<String> set = new LinkedHashSet<>();
        set.add("张三");
        set.add("李四");
        set.add("王五");
        set.add("张三");//尝试添加重复元素

        System.out.println("元素个数:"+set.size());
        for (Object obj : set) {
            System.out.println(obj);
        }

    }
}

image-20221004160520890

  从上面代码的结果中可以看出,HashSet不保证元素的添加顺序,但是LinkedHashSet可以保证元素的添加顺序。无论是HashSet还是LinkedHashSet都不允许添加重复元素

1.2 案例:员工信息管理

  案例需求:定义一个Employee类,该类包含name、birthday,要求name和恶birthday相等的为同一个员工,其中birthday为MyDate类,包含年、月、日三个属性。尝试重写Employee类的hashCode方法和equals方法。

  MyDate类代码:

import java.util.Objects;

public class MyDate {
    private int year;
    private int month;
    private int day;

    public MyDate(int year, int month, int day) {
        this.year = year;
        this.month = month;
        this.day = day;
    }

    @Override
    public String toString() {
        return "MyDate{" +
                "year=" + year +
                ", month=" + month +
                ", day=" + day +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        MyDate myDate = (MyDate) o;
        return year == myDate.year &&
                month == myDate.month &&
                day == myDate.day;
    }

    @Override
    public int hashCode() {
        return Objects.hash(year, month, day);
    }
}

  Employee类示例代码:

import java.util.Objects;

public class Employee {
    private String name;//姓名
    private MyDate birthday;//生日

    public Employee(String name, MyDate birthday) {
        this.name = name;
        this.birthday = birthday;
    }

    //重写equals方法-判断姓名和生日是否相等
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Employee employee = (Employee) o;
        return Objects.equals(name, employee.name) &&
                Objects.equals(birthday, employee.birthday);
    }

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

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

  测试类示例代码:

import java.util.HashSet;

public class TestEmployee {
    public static void main(String[] args) {
        HashSet<Object> set = new HashSet<>();

        set.add(new Employee("张三",new MyDate(1990,1,1)));
        //重复元素无法添加,因为MyDate和Employee重写了hashCode和equals方法
        set.add(new Employee("张三",new MyDate(1990,1,1)));
        set.add(new Employee("李四",new MyDate(1992,2,2)));

        for (Object o : set) {
            System.out.println(o);
        }
    }
}

  代码运行结果:

image-20221004161058327

1.3 TreeSet

  SortedSet是Set接口的一个子接口,支持排序类Set集合,TreeSet是SortedSet接口的实现类,即TreeSet可以确保集合元素处于排序状态。

  对象的排序要么是对象本身支持自然排序,即实现java.lang.Compareable接口,要么在创建set集合对象时提供定值排序接口java.util.Comparator的实现类对象。

1.3.1 自然排序

  如果视图把一个对象添加到未指定定制比较器的TreeSet时,则该对象的类必须实现Comparable接口,实现compareTo(Object obj)方法。此时对于TreeSet集合而言,它判断两个对象是否相等的唯一标准是两个对象通过compareTo(Object obj)方法比较返回值为0.

  示例代码:

  元素为String类,String类实现了java.lang.Conparable自然排序接口的示例代码:

import java.util.TreeSet;

public class TreeSetTest1 {
    public static void main(String[] args) {
        TreeSet<Object> set = new TreeSet<>();

        //String它实现了java.lang.Comparable接口
        set.add("zhangsan");
        set.add("lisi");
        set.add("wangwu");
        set.add("zhangsan");

        System.out.println("元素个数:"+set.size());
        for (Object o : set) {
            System.out.println(o);
        }
    }
}

image-20221004162151940

  学生类实现了java.lang.Comparable自然排序接口的示例代码:

public class Student implements Comparable {
    private int id;
    private String name;

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

    public int getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

    @Override
    public int compareTo(Object o) {
        Student other=(Student) o;
        return this.id-other.id;
    }

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

  测试类示例代码:

public class TreeSetTest2 {
    public static void main(String[] args) {
        TreeSet<Object> set = new TreeSet<>();

        //Student实现了java.lang.Comparable接口
        set.add(new Student(3,"张三"));
        set.add(new Student(1,"李四"));
        set.add(new Student(2,"王五"));
        set.add(new Student(3,"张三凤"));

        System.out.println("元素个数:"+set.size());
        for (Object o : set) {
            System.out.println(o);
        }
    }
}

image-20221004162421706

  虽然添加到TreeSet时,不使用equals方法,但在Comparable接口的API中有如下提醒:当元素实现java.lang.Comparable接口重写compareTo方法时,也建议重写equals方法,应保证该方法与compareTo(Object obj)方法有一致的结果,如果两个对象通过equals方法比较返回true,则通过compareTo(Object obj)方法比较的返回值为0,否则结果会有点奇怪。

1.3.2 定制排序

  如果放到TreeSet中的元素的自然排序规则不符合当前业务的排序需求,或者元素的类型没有实现Comparable接口,那么在创建TreeSet时,可以单独指定一个定制比较器Comparator的实现类对象。使用定制比较器的TreeSet判断两个元素相等的标准是通过compare(Object o1,Object o2)方法比较两个元素返回了0。

  示例代码:

  Teacher类示例代码:

public class Teacher {
    private int id;
    private String name;

    public Teacher(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public int getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

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

  测试类示例代码:

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

public class TreeSetTest3 {
    public static void main(String[] args) {
        TreeSet<Object> set = new TreeSet<>(new Comparator<Object>() {
            @Override
            public int compare(Object o1, Object o2) {
                Teacher t1 = (Teacher) o1;
                Teacher t2 = (Teacher) o2;
                return t1.getId() - t2.getId();
            }
        });

        set.add(new Teacher(3,"张三"));
        set.add(new Teacher(1,"李四"));
        set.add(new Teacher(2,"王五"));
        set.add(new Teacher(3,"张三凤"));
        System.out.println("元素个数:"+set.size());
        for (Object o : set) {
            System.out.println(o);
        }
    }
}

image-20221004163008578

1.4 案例:企业面试题

  案例需求:通过键盘录入一串字符,去掉其中的重复字符,打印出不同的字符(重复的字符仅保留一份),必须保证输入顺序。例如,输入baaabbccacddd,打印结果为bacd。

示例代码:

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

public class SetExer {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);

        System.out.println("请输入一串字符:");
        String strings = input.next();

        LinkedHashSet<Object> set = new LinkedHashSet<>();
        char[] chars = strings.toCharArray();
        for (int i = 0; i < chars.length; i++) {
            set.add(chars[i]);
        }

        String result="";
        for (Object o : set) {
            result+=o;
        }
        System.out.println("result="+result);


    }
}

image-20221004164522410

posted @   别团等shy哥发育  阅读(25)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
历史上的今天:
2021-10-04 MyCat核心概念
2021-10-04 ERROR 1819 (HY000): Your password does not satisfy the current policy requirements
点击右上角即可分享
微信分享提示