Java中类集中的HashSet、TreeSet

本文深入解析Java中的Set接口,包括HashSet和TreeSet的特性与使用方法,探讨元素重复判断及自定义类排序策略,覆盖Comparable接口与Comparator接口的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.Set接口

  Set接口与List接口最大的区别就是Set不允许存放重复元素,Set接口并没有对Collection接口进行扩充,而List对Collection进行了扩充。因此,在Set接口中没有get()、set()方法。
  在Set子接口中有两个常用子类:HashSet(无序存储)、TreeSet(有序存储)
在这里插入图片描述

1.1 HashSet类

产生版本:JDK1.2
包:java.util.HashSet
定义:HashSet<E> hashSet = new HashSet<>(); Set<String> hashSet = new HashSet<>();

import java.util.HashSet;
public class Test {
    public static void main(String[] args) {
       HashSet<String> hashSet = new HashSet<>();
       hashSet.add("hello");
       hashSet.add("world");
       hashSet.add("A");
       hashSet.add("C");
       hashSet.add("D");
       hashSet.add("y");
       //1.允许存放空值
       hashSet.add(null);
       //2.添加重复元素
       hashSet.add("A");
        //3.输出集合的长度
       System.out.println(hashSet.size());
       //输出集合
        System.out.println(hashSet);
        //4.集合中是否包含a
       System.out.println(hashSet.contains("a"));
       //5.删除A
        System.out.println(hashSet.remove("A"));
        System.out.println(hashSet);
    }
}

运行结果:
7
[null, A, world, C, D, y, hello]
false
true
[null, world, C, D, y, hello]
HashSet不允许元素重复、 无序存储(根据哈希码保存)、可以存放空值、底层基于哈希表

1.2 TreeSet类

import java.util.TreeSet;
public class Test{
    public static void main(String[] args) {
        TreeSet<Integer> treeSet = new TreeSet<>();
        treeSet.add(1);
        treeSet.add(2);
        treeSet.add(9);
        treeSet.add(6);
        treeSet.add(4);
        //1.添加重复元素
        treeSet.add(2);
        //2.输出集合的长度
        System.out.println(treeSet.size());
        //3.集合中是否包含pig
        System.out.println(treeSet.contains(2));
        System.out.println(treeSet);

        //4.删除pig
        System.out.println(treeSet.remove(2));
        System.out.println(treeSet);
    }
}

TreeSet不可以存放重复元素、按升序存放、不允许存放null(否则会有空指针异常)、底层基于红黑树

1.3 TreeSet排序

TreeSet对于自定义的类不支持排序,那么有什么排序方式呢?
第一种方式:实现可比较接口Comparable覆写compareTo方法
第一种方式:Treeset构造方法传入比较器接口实现类的对象

1.3.1 实现Comparable接口

import java.util.Set;
import java.util.TreeSet;
class Person implements Comparable<Person>{
    private String name;
    private int age;

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

    @Override
    public int compareTo(Person o) {
        //升序
        return this.age - o.age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
public class Test {
    public static void main(String[] args) {
        Person per1 = new Person("王五",19);
        Person per2 = new Person("张三",88);
        Person per3 = new Person("李四",2);
        Set<Person> set = new TreeSet<>();
        set.add(per1);
        set.add(per2);
        set.add(per3);
        for(Person person:set){
            System.out.println(person);
        }
    }
}

运行结果:
Person{name=‘李四’, age=2}
Person{name=‘王五’, age=19}
Person{name=‘张三’, age=88}

1.3.2 构造方法传入比较器接口实现类的对象

import java.util.Comparator;
import java.util.Set;
import java.util.TreeSet;
class Person {
    private String name;
    private int age;

    public Person(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 "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
public class Test {
    public static void main(String[] args) {
        Person per1 = new Person("王五",19);
        Person per2 = new Person("张三",88);
        Person per3 = new Person("李四",2);
        //匿名内部类
        Set<Person> set = new TreeSet<>(new Comparator<Person>() {
            @Override
            public int compare(Person o1, Person o2) {
                return o1.getAge()-o2.getAge();
            }
        });
        set.add(per1);
        set.add(per2);
        set.add(per3);
        for(Person person:set){
            System.out.println(person);
        }
    }
}

运行结果:
Person{name=‘李四’, age=2}
Person{name=‘王五’, age=19}
Person{name=‘张三’, age=88}

1.3.3 排序总结

关于TreeSet排序总结:

  • 实现Comparable接口 -----内部排序
  • 通过构造方法传入Comparator接口对象----外部排序
  • 如果这两种方式都在,优先使用Comparator外部排序接口

1.4 重复元素判断

用TreeSet子类进行数据保存的时候,重复元素的判断依靠的是ComParable接口完成的,但是这并不是全部Set接口判断重复元素的方式,因为如果使用的是HashSet子类,由于其跟Copmarable没有任何关系,所以它判断重复元素的方式依靠的是Object类中的两个方法:

hash码:public native int hashCode();
对象比较:public poolean equals(Object obj);

在Java中进行对象比较的步骤:
通过一个对象的唯一编码找到一个对象的信息,当编码匹配之后载调用equals方法进行内容的比较

import java.util.Comparator;
import java.util.Objects;
import java.util.Set;
import java.util.TreeSet;
import java.util.HashSet;
import java.util.Set;

class Person {
    private String name;
    private Integer age;

    public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
    //覆写equals和hashcode方法时,比较内容参与的属性也要参与hashcode计算
    @Override
    public boolean equals(Object o) {
        //1.如果要比较的两个对象的地址相等直接返回true
        if(this == o){
            return true;
        }
        //2.判断要比较的对象是不是Person类的实例 如果不是 直接返回false
        if(o instanceof Person){
            //如果要判断的对象是Person类的实例 向上转型比较属性
            Person per = (Person)o;
            return this.name.equals(per.name)&&
                    this.age==per.age;
        }
        return false;
    }

    @Override
    public int hashCode() {
        int h = this.age.hashCode();
        h = h*31+this.name.hashCode();
        return h;
    }
}
public class Test {
    public static void main(String[] args) {
        Person per1 = new Person("王五",19);
        Person per2 = new Person("张三",88);
        Person per3 = new Person("李四",2);
        Person per4 = new Person("李四",2);
        //匿名内部类
        Set<Person> set = new HashSet<>();
        set.add(per1);
        set.add(per2);
        set.add(per3);
        set.add(per4);
        System.out.println(set.size());
        System.out.println(set);
    }
}

运行结果:
3
[Person{name=‘李四’, age=2}, Person{name=‘王五’, age=19}, Person{name=‘张三’, age=88}]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值