Set集合

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

@toc

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

目录
相关文章
|
19天前
|
存储 NoSQL 关系型数据库
Redis 集合(Set)
10月更文挑战第17天
33 5
|
20天前
|
算法 Java 数据处理
从HashSet到TreeSet,Java集合框架中的Set接口及其实现类以其“不重复性”要求,彻底改变了处理唯一性数据的方式。
从HashSet到TreeSet,Java集合框架中的Set接口及其实现类以其“不重复性”要求,彻底改变了处理唯一性数据的方式。HashSet基于哈希表实现,提供高效的元素操作;TreeSet则通过红黑树实现元素的自然排序,适合需要有序访问的场景。本文通过示例代码详细介绍了两者的特性和应用场景。
34 6
|
20天前
|
存储 Java 数据处理
Java Set接口凭借其独特的“不重复”特性,在集合框架中占据重要地位
【10月更文挑战第16天】Java Set接口凭借其独特的“不重复”特性,在集合框架中占据重要地位。本文通过快速去重和高效查找两个案例,展示了Set如何简化数据处理流程,提升代码效率。使用HashSet可轻松实现数据去重,而contains方法则提供了快速查找的功能,彰显了Set在处理大量数据时的优势。
31 2
|
22天前
|
存储 算法 Java
Java Set因其“无重复”特性在集合框架中独树一帜
【10月更文挑战第14天】Java Set因其“无重复”特性在集合框架中独树一帜。本文深入解析Set接口及其主要实现类(如HashSet、TreeSet)如何通过特定的数据结构(哈希表、红黑树)确保元素唯一性,并提供最佳实践建议,包括选择合适的Set实现类和正确实现自定义对象的`hashCode()`与`equals()`方法。
27 3
|
5天前
|
存储 Java
判断一个元素是否在 Java 中的 Set 集合中
【10月更文挑战第30天】使用`contains()`方法可以方便快捷地判断一个元素是否在Java中的`Set`集合中,但对于自定义对象,需要注意重写`equals()`方法以确保正确的判断结果,同时根据具体的性能需求选择合适的`Set`实现类。
|
5天前
|
存储 Java 开发者
在 Java 中,如何遍历一个 Set 集合?
【10月更文挑战第30天】开发者可以根据具体的需求和代码风格选择合适的遍历方式。增强for循环简洁直观,适用于大多数简单的遍历场景;迭代器则更加灵活,可在遍历过程中进行更多复杂的操作;而Lambda表达式和`forEach`方法则提供了一种更简洁的函数式编程风格的遍历方式。
|
5天前
|
Java 开发者
|
20天前
|
存储 Java 数据处理
Set 是 Java 集合框架中的一个接口,不包含重复元素且不保证元素顺序。
【10月更文挑战第16天】Java Set:无序之美,不重复之魅!Set 是 Java 集合框架中的一个接口,不包含重复元素且不保证元素顺序。通过 hashCode() 和 equals() 方法实现唯一性,适用于需要唯一性约束的数据处理。示例代码展示了如何使用 HashSet 添加和遍历元素,体现了 Set 的高效性和简洁性。
23 4
|
22天前
|
存储 Java 数据处理
Set 是 Java 集合框架中的一个接口,不包含重复元素且不保证元素顺序。
Java Set:无序之美,不重复之魅!Set 是 Java 集合框架中的一个接口,不包含重复元素且不保证元素顺序。它通过 hashCode() 和 equals() 方法确保元素唯一性,适用于需要唯一性约束的数据处理。示例代码展示了如何使用 HashSet 实现这一特性。
23 5
|
23天前
|
Java 开发者
在Java的集合世界里,Set以其独特的特性脱颖而出,它通过“哈希魔法”和“红黑树防御”两大绝技
【10月更文挑战第13天】在Java的集合世界里,Set以其独特的特性脱颖而出。它通过“哈希魔法”和“红黑树防御”两大绝技,有效抵御重复元素的侵扰,确保集合的纯洁性和有序性。无论是“人海战术”还是“偷梁换柱”,Set都能从容应对,成为开发者手中不可或缺的利器。
30 6