前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Set集合

Set集合

作者头像
别团等shy哥发育
发布2023-02-25 11:10:16
5840
发布2023-02-25 11:10:16
举报
文章被收录于专栏:全栈开发那些事

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添加元素的示例代码:

代码语言:javascript
复制
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
image-20221004160236033

  LinkedHashSet添加元素的示例代码:

代码语言:javascript
复制
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
image-20221004160520890

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

1.2 案例:员工信息管理

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

  MyDate类代码:

代码语言:javascript
复制
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类示例代码:

代码语言:javascript
复制
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 +
                '}';
    }
}

  测试类示例代码:

代码语言:javascript
复制
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
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自然排序接口的示例代码:

代码语言:javascript
复制
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
image-20221004162151940

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

代码语言:javascript
复制
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 + '\'' +
                '}';
    }
}

  测试类示例代码:

代码语言:javascript
复制
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
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类示例代码:

代码语言:javascript
复制
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 + '\'' +
                '}';
    }
}

  测试类示例代码:

代码语言:javascript
复制
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
image-20221004163008578

1.4 案例:企业面试题

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

示例代码:

代码语言:javascript
复制
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
image-20221004164522410
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-10-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Set集合
  • 1、Set集合
    • 1.1 HashSet和LinkedHashSet
      • 1.2 案例:员工信息管理
        • 1.3 TreeSet
          • 1.3.1 自然排序
          • 1.3.2 定制排序
        • 1.4 案例:企业面试题
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档