Set 简介


Set 和 List 一样,也是继承 Collection 接口, Set 不保存重复的元素,如果试图将相同对象的多个实例添加到 Set 中,那么不好意思,它会立马阻止。Set 判断两个对象是否相同,使用的是 equals() 方法,只要该方法的结果是 true,Set 就不会接收这个对象。

Set 具有和 Collection 完全一样的接口,因此没有任何额外的功能,实际上 Set 就是 Collection,只是行为不同,Set 是基于对象的值来确定归属性的。它最常用的实现类就是 HashSetTreeSet

HashSet

HashSet 是无序的,不能保证元素的排列顺序,下面是一段示例代码:

public class SetTest {

    public static void main(String[] args) {
        //创建 set 对象,参数类型为 Integer
        Set<Integer> set = new HashSet<Integer>();
        //存放 0 ~ 9 的整数
        for (int i = 0; i < 10; i++) {
            set.add(i);
        }
        for (Integer i : set) {
            System.out.println("元素" + s + "的 hashcode 值:" + s.hashCode());
        }
    }
}

打印结果是啥?大家可以猜猜结果。

先说说 HashSet 的存放规则,当向 HashSet 中存放一个元素的时候,HashSet 会调用对象的 hashcode() 方法来得到该对象的 hashcode 值,然后根据 hashcode 值来决定该对象在 HashSet 中的存储位置。上面代码的结果如下:

元素0的 hashcode 值:0
元素1的 hashcode 值:1
元素2的 hashcode 值:2
元素3的 hashcode 值:3
元素4的 hashcode 值:4
元素5的 hashcode 值:5
元素6的 hashcode 值:6
元素7的 hashcode 值:7
元素8的 hashcode 值:8
元素9的 hashcode 值:9

整数元素会根据其散列值的顺序排列,如果元素不是整数,而是字符串呢?

public static void main(String[] args) {
        //创建 set 对象,参数类型为 String
        Set<String> set = new HashSet<>();

        set.add("cat");
        set.add("tom");
        set.add("sam");

        for (String s : set) {
            System.out.println("元素" + s + "的 hashcode 值:" + s.hashCode());
        }
    }

打印结果:

元素tom的 hashcode 值:115026
元素cat的 hashcode 值:98262
元素sam的 hashcode 值:113631

很明显,结果是无序的。请牢记 HashSet 是无序集合,使用的时候就不该考虑顺序。如果想让结果有序,那么可以使用 TreeSet

TreeSet

TreeSet 将元素存储在红黑树(平衡二叉树)结构中,而 HashSet 使用的是散列函数。TreeSet 不仅能保证元素的唯一性,还能对元素按照某种规则进行排序,排序有两种:自然排序定制排序

先看看自然排序:

public static void main(String[] args) {
        //创建 set 对象,参数类型为 String
        Set<String> set = new TreeSet<>();

        set.add("cat");
        set.add("tom");
        set.add("sam");

        for (String s : set) {
            System.out.println(s);
        }
    }

打印结果:

cat
sam
tom

可以看到结果是按照字母进行自然排序的,自然排序需要使用元素的 CompareTo() 方法来得到元素之间的大小关系,然后按升序排列。 obj1.compareTo(obj2) 方法如果返回 0,则说明被比较的两个对象相等,如果返回一个正数,则表明 obj1 大于 obj2,如果是负数,则表明 obj1 小于 obj2。

下面瞅瞅定制排序:

public static void main(String[] args) {
        //创建 set 对象,传入一个 Comparator 对象
        Set<String> set = new TreeSet<>(new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                //倒序
                return o2.compareTo(o1);
            }
        });

        set.add("cat");
        set.add("tom");
        set.add("sam");

        for (String s : set) {
            System.out.println(s);
        }
    }

打印结果:

tom
sam
cat

结果如期而至,倒序排列。代码中使用 TreeSet 的有参构造器:TreeSet(Comparator<? super E> comparator),以匿名内部类的方式传入一个 Comparator 对象,并实现其中的 compare() 方法来指定排序规则。

小结

本文介绍了 Set 和其两个常见的实现类 HashSetTreeSet,Set 中元素都是唯一的,可以存放 null,但是只能存一个,HashSet 不保证元素的顺序,TreeSet 中的元素是有序的,默认是自然排序,可以根据业务进行定制排序。

欢迎关注公众号:一盐难进

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值