Java中的Set

本文介绍了Java中的Set概念和特性,包括Set的基本方法,并详细讲述了基于红黑树实现的TreeSet以及基于哈希表实现的HashSet。TreeSet提供有序操作如first()、last()等,而HashSet则不支持此类操作。使用TreeSet需实现Comparable或提供Comparator,HashSet则需重写hashCode()和equals()方法。

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

Set的概念和特性以及常用方法

Set可以被认为是一个集合,集合内部是同类型的元素,他们之间没有先后顺序,但是不允许重复!!!
Set中常用的方法有以下几个:

返回值方法
booleanadd( ) 向集合中添加元素
clear( ) 去掉集合中所有的元素
booleancontains( ) 判断集合中是否包含某一个元素
booleanisEmpty( ) 判断集合是否为空
Iteratoriterator( ) 主要用于递归集合,返回一个Iterator()对象
booleanremove(E e) 从集合中去掉特定的对象
intsize( ) 返回集合的大小

在Java中Set是一个继承自Collection接口,它主要有以下两个实现类:

TreeSet

TreeSet是基于平衡二叉搜索树(红黑树)实现的Set,因为二叉搜索树中序遍历为有序的(不明白可以看前一篇博客:二叉搜索树的思想,以及增删查改的实现)会多出来这么几种方法:

返回值方法
Efirst() 返回集合中序遍历第一个
Elast() 返回集合中序遍历最后一个
EpollFirst() 删除集合中序遍历第一个并返回
EpollLast() 删除集合中序遍历最后一个并返回
Efloor(E e) 返回比传入元素小的所有元素中最大的一个,包含相等(因为传入的元素可能不在集合中,也可能在集合中,这个方法若传入元素在集合中则返回传入元素,如不在则返回比传入元素小的所有元素中最大的一个)
Elower(E e) 返回比传入元素小的所有元素中最大的一个
Eceiling(E e) 返回比传入元素大的所有元素中最小的一个(包含传入元素和上面floor()一起理解)
Ehigher(E e) 返回比传入元素大的所有元素中最小的一个(不包含传入元素)

下面通过代码演示一下上述方法:

    public static void main(String[] args) {
        TreeSet<Integer> set = new TreeSet<>();
        set.add(1);
        set.add(9);
        set.add(5);
        set.add(3);
        set.add(10);
        set.add(2);


        System.out.println("first " + set.first());
        System.out.println("last " + set.last());

        //比key小的里面最大的一个
        System.out.println("lower " + set.lower(3));
        //比key小的里面最大的一个(包括key)
        System.out.println("floor " + set.floor(3));

        //比key大的里面最小的(包括key)
        System.out.println("ceiling " + set.ceiling(3));
        //比key大的里面最小的
        System.out.println("higher " + set.higher(3));

        System.out.println("contains " + set.contains(3));
        System.out.println("remove(4) " + set.remove(4));
        System.out.println("remove(3) " + set.remove(3));
        System.out.println("size " + set.size());
        System.out.println("是否为空 " + set.isEmpty());
        set.clear();
        System.out.println("是否为空 " + set.isEmpty());
    }

运行结果:
在这里插入图片描述
需要注意的是,因为在将元素插入搜索树的过程中会比较带插入元素和集合中元素大小,所以当TreeSet中要存入自己实现的类为元素时,该类必须实现Comparab接口或者在创建Set时传入一个该类的Comparator比较器,对于Comparable和Comparator不熟悉的同学建议去看这篇博客:Java中的Comparable和Comparator到底该怎么用看完就全明白了

HashSet

HashSet是基于哈希表实现的,因为哈希表内部元素是无序的,所以HashSet不像TreeSet,HashSet没有和元素顺序有关的方法,像上面提到的first(),last(),lower()等。
下面演示一下:

import java.util.HashSet;
import java.util.Set;

public class HashSetDemo {
    public static void main(String[] args) {
        Set<Integer> set = new HashSet<>();
        set.add(1);
        set.add(3);
        set.add(9);
        set.add(2);
        set.add(5);
        set.add(4);
        set.add(10);
        set.add(8);

        System.out.println("remove(9) " + set.remove(9));
        System.out.println("contains(8) " + set.contains(8));
        System.out.println("isEmpty() " + set.isEmpty());
        System.out.println("size() " + set.size());
        set.clear();
        System.out.println("isEmpty() " + set.isEmpty());
    }

运行结果:
在这里插入图片描述
和TreeSet对元素要求不同,因为哈希表需要根据元素得到哈希值然后,根据这个哈希值去计算该元素在哈希表中的下标,所以当我们要在HashSet中存入自己实现的类为元素时,需要实现hashCode() 和 equals() 方法(为什么还要实现equals方法? 因为要保证相同的元素的哈希值相同,程序又不知道哪两个元素相同,所以需要实现equals方法)。
举个例子,下面是我自己实现的Person类,当我们需要创建一个 “Set< Person > set = new HashSet()”时:

import java.util.Objects;

public class Person {
    public String name;
    public int age;

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

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

	//实现equals()方法
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return age == person.age &&
                Objects.equals(name, person.name);
    }
	//实现hashCode()方法
    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
}

Set两种实现类的比较

Set底层结构TreeSetHashSet
底层结构红黑树哈希桶
插入/删除/查找 时间复杂度O(logN)O(1)
是否有序关于Key有序理论上无序
线程安全不安全不安全
插入/删除/查找 区别按照红黑树的特性进行插入和删除1.先计算Key哈希地址 2. 然后进行插入和删除
比较与重写TreeSet中的元素必须实现Comparable或者在构建Set时传入元素专属Comparator,否则抛出ClassCastException异常自定义类型需要重写equals和hashCode方法
应用场景需要Key有序的场景Key是否有序不关心,需要更高的时间性能
评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

南山不太冷

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值