java--Set集合

1.Set集合

在集合中没有重复元素,通过equals()方法进行判断

2.HashSet
  • 保证元素唯一性的原理:
    当使用add 方法时,会先调用hashCode()方法获得一个哈希值,通过为每个对象分配哈希值,如果没有哈希值相同的对象,则存进集合,当哈希值相同时,就对对象中的属性通过equals比较,如果对象相同则不存储,如果对象不同则存储
    (1)底层由哈希表实现
    (2)实现了Set接口
    (3)存取顺序不一致
HashSet<String> hashSet = new HashSet<>();
hashSet.add("a");
hashSet.add("a");//不会添加重复元素
hashSet.add("b");
hashSet.add("c");
hashSet.add("d");
System.out.print(hashSet); //存取的顺序不一致

在这里插入图片描述
存储自定义引用数据类型时
如果想达到不重复的效果,必须要重写equals和hashCode方法,在Idea中可以使用快捷键自动生成:右键->Generate->equals()和hashCode()方法可以自动生成

HashSet<Student> hashSet = new HashSet<>();
        hashSet.add(new Student("张三",23));
        hashSet.add(new Student("张三",23));
        hashSet.add(new Student("李四",24));
        hashSet.add(new Student("张三",23));
        hashSet.add(new Student("李四",24));
        for (Student student:hashSet) {
            System.out.println(student.getName() + " " + student.getAge());
        }
    }
}
class Student {
    private String name;
    private int age;
    public Student(String name,int age) {
        this.name = name;
        this.age = age;
    }
    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return age == student.age &&
                Objects.equals(name, student.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
}
  • LinkedHashSet
    (1)元素不重复
    (2)Set实现类中唯一保证存取顺序一致的集合
LinkedHashSet<String> linkedHashSet = new LinkedHashSet<>();
    linkedHashSet.add("a");
    linkedHashSet.add("a");
    linkedHashSet.add("b");
    linkedHashSet.add("c");
    linkedHashSet.add("d");
    linkedHashSet.add("b");
    System.out.println(linkedHashSet);
}

在这里插入图片描述


查看hashCode()源码

public static int hashCode(Object a[]) {
    if (a == null)
        return 0;

    int result = 1;

    for (Object element : a)
        result = 31 * result + (element == null ? 0 : element.hashCode());

    return result;
}

采用数值31相乘的原因:
(1)31为质数,当属性不同时,产生相同的哈希值的几率较小
(2)31数值不算不太大,在正常情况下不会超出int 的范围,31也不算太小,当属性值不同时,会尽可能的去避免产生相同的哈希值
(3)31为2的5次方减1,计算机运算过程不会相对复杂


当对数据的存放顺序没有要求时,使用HashSet,因为其效率更高

3.TreeSet

(1)保证元素不重复
(2)可以给元素进行排序
当存储字符串时由于String 类中重写了compareTo()方法,在存储时会自动按照字典顺序进行存储

TreeSet<String> treeSet = new TreeSet<>();
treeSet.add("b");
treeSet.add("d");
treeSet.add("a");
treeSet.add("b");
treeSet.add("f");
treeSet.add("e");
treeSet.add("c");
System.out.println(treeSet);

在这里插入图片描述
当存储自定义对象时,必须实现comparable接口根据需求重写compareTo(),然后才能在TreeSet中存储元素

  • TreeSet根据compareTo()方法进行存储,用二叉树实现
    (1)compare To()返回值为0时,则不存储
    (2)compareTo()方法返回值为正数时存储在右边
    (3)compareTo()方法返回值为负数时存储在左边
TreeSet<Student> treeSet = new TreeSet<>();
        treeSet.add(new Student("张三",23));
        treeSet.add(new Student("李四",24));
        treeSet.add(new Student("王五",16));
        for (Student s:treeSet
             ) {
            System.out.println(s.getName() + " " + s.getAge());
        }
    }
}
class Student implements Comparable<Student>{
    private String name;
    private int age;
    public Student(String name,int age) {
        this.name = name;
        this.age = age;
    }
    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    @Override
    public int compareTo(Student o) {
        int num = this.age - o.age;
        return num == 0 ? this.name.compareTo(o.name):num;
    }
}

在这里插入图片描述
比较器实现比较原理
如果我们在存储字符串时,希望根据字符串的长度去存储,也需要定义类实现comparable接口根据需求重写compareTo()方法。

TreeSet<String> treeSet = new TreeSet<>(new Compare());
        treeSet.add("aaaaaa");
        treeSet.add("d");
        treeSet.add("aop");
        treeSet.add("app");
        treeSet.add("uidd");
        treeSet.add("fnjri");
        System.out.println(treeSet);
    }
}
class Compare implements Comparator<String>{
    @Override
    public int compare(String s, String s1) {
        int num = s.length() - s1.length();
        return num == 0 ? s.compareTo(s1):num;
    }
}

在这里插入图片描述
查看Comparator的API
在这里插入图片描述但是会默认继承Objects类,此类中重写了equals()方法,所以在我们自定义时不用再次重写

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值