【Java】的Set集合

一、什么是Set集合

Set集合中的元素是无序的且不可重复, 如果试图把两个相同元素加入同一个Set集合中,则添加操作失败,add()方法返回false,且新元素不会被加入。

Set接口是Collection的子接口,Set接口没有提供额外的方法,但实现Set接口的容器类中的元素是没有有顺序的,而且不可以重复。

Set容器类:HashSet、TreeSet

继承和实现的接口

  • TreeSet实现AbstractSet类
  • 实现NavigableSet接口:使用导航方法扩展的 SortedSet,报告给定搜索目标的最接近匹配。方法lower、floor、ceiling和higher分别返回小于、小于或等于、大于或等于和大于给定元素的元素,如果没有这样的元素则返回null。可以按升序或降序访问和遍历 NavigableSet。
  • 实现Cloneable接口:向 Object.clone() 方法指示该方法可以合法地对该类的实例进行逐个字段的复制。在未实现 Cloneable 接口的实例上调用 Object 的 clone 方法会导致抛出异常 CloneNotSupportedException。
  • 实现 java.io.Serializable接口:未实现此接口的类将不会对其任何状态进行序列化或反序列化。可序列化类的所有子类型本身都是可序列化的。序列化接口没有方法或字段,仅用于识别可序列化的语义。

实例:

 public static void main(String[] args){
        Set s1=new HashSet();
        Set s2 =new HashSet();
        s1.add("1");
        s1.add("b");
        s1.add("c");
        s2.add("d");
        s2.add("a");
        s2.add("b");
        //Set和List容器类都具有Constructor(Collection c)
        //构造方法用以初始化容器类
        Set sn = new HashSet(s1);
        sn.retainAll(s2);//只保留和s1里面相同的
        Set su = new HashSet(s1);
        su.addAll(s2);
        System.out.println(sn);
        System.out.println(su);
    }

结果:

[b]
[1, a, b, c, d]

public static void main(String[] args){
        Set s = new HashSet();
        s.add("hello");
        s.add("world");
        s.add("hello");  //相同的元素不会被加入
        System.out.println(s);
    }

结果:

[world, hello]

HashSet

特点

  • 不可重复
  • 无序的,即不会记录插入的顺序
  • 可以存不同类型数据
  • 集合元素可以存null(但只能存储一个null值)

常用方法

  • add:添加元素
  • remove:删除元素
  • contains:判断是否包含某个元素
  • clear:清空
  • Iterator:使用迭代器遍历集合
  • foreach:遍历集合
    public static void main(String[] args) {
        //实例化一个HashSet集合
        Set set = new HashSet();
 
        //添加元素
        set.add(1);
        set.add("a");
        System.out.println(set);
 
        //删除元素
        set.remove(1);
        System.out.println(set);
 
        //判断是否包含某个元素
        System.out.println(set.contains(1));

        //清空集合
        set.clear();
        System.out.println(set);
        
        set.add("a");
        set.add("b");
        set.add("c");
        set.add("d");
        set.add("d");  //重复的元素不会被添加
        set.add(null);  //可以存取空值
        System.out.print(set);
 
        //使用迭代器遍历集合
        Iterator it =set.iterator();
        while (it.hasNext()){
            System.out.println(it.next());
        }
 
        //for each迭代集合
        for (Object obj:set){//把set的每一个值取出来,赋值给obj,直到循环完set的所有值
            System.out.println(obj);
        }
        System.out.println(set.size());  //获取集合的元素个数
    }

Set集合的去重原理

先看元素的HashCode()值也就是哈希值是否相同,再看equals方法返回的结果

如果哈希值不同,则说明元素不相同,将元素添加到集合中

如果哈希值相同,则继续判断equals方法
————如果equals返回true,则说明元素的哈希值与内容都相同,元素重复,不会添加到集合中
————如果equals返回false,则说明元素的哈希值相同,但内容不同,元素不重复,添加到集合中

TreeSet

特点

  • 有序(底层在添加元素的时候会自动进行排序)
  • 可以对元素进行排序(自然排序(默认)、定制排序)

为什么TreeSet的存储结构是有序的

在进行add添加元素的时候底层会进行一个逻辑判断,如果要新添加的元素在集合中存在,则该集合的元素保持;如果要添加的元素在集合中不存在,则将元素添加到集合中,并且进行自然排序:
TreeSet会调用集合元素的compareTo(Object obj)方法来比较元素之间的大小关系,然后将集合元素按升序排列

  • 如果this>obj,返回正数1
  • 如果this<obj,返回正数-1
  • 如果this=obj,返回0,则认为这两个对象相等

需要注意的是,必须放入同样类的对象,(默认会进行排序)否则可能会发生类型转换异常,我们可以使用泛型来进行限制

常用方法

  • add:添加元素
  • remove:删除元素
  • contains:判断是否包含某个元素
  • clear:清空

自然排序

public static void main(String[] args) {
        Set<Integer> set = new TreeSet<Integer>();
        //TreeSet自然排序
        set.add(5);
        set.add(2);
        set.add(4);
        set.add(3);
        System.out.println(set);   //输出结果为2 3 4 5
 
        //删除元素
        set.remove(5);
 
        //判断是否包含某个元素
        set.contains(3);
 
        //清空集合
        set.clear();
 
        //使用迭代器遍历集合
        Iterator<Integer> it = set.iterator();
        while(it.hasNext()){
            System.out.println(it.next());
        }
 
        //for each迭代集合
        for (Integer i:set){
            System.out.println(i);
        }

自定义排序

public class SetTest2 {
    public static void main(String[] args){
        Person p1 = new Person("小美",21);
        Person p2 = new Person("小虎",21);
        Person p3 = new Person("小白",25);
        Person p4 = new Person("小红",24);
        Person p5 = new Person("小紫",20);
        Person p6 = new Person("小兰",19);
        Person p7 = new Person("小马",26);

        Set<Person> personSet = new TreeSet<Person>(new Person());
        personSet.add(p1);
        personSet.add(p2);
        personSet.add(p3);
        personSet.add(p4);
        personSet.add(p5);
        personSet.add(p6);
        personSet.add(p7);

        for(Person p:personSet){
            System.out.println(p.name+"  "+p.age);
        }
    }
}

class Person implements Comparator<Person>{
    String name;
    int age;
    public Person(){}
    public Person(String name,int age){
        this.name = name;
        this.age = age;
    }
    @Override
    public int compare(Person o1, Person o2) {
        if (o1.age>o2.age){
            return 1;
        }else if(o1.age<o2.age){
            return -1;
        }else {
            return 0;
        }
    }
}

运行结果:

小兰 19
小紫 20
小美 21
小红 24
小白 25
小马 26

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值