Java Set

目录

Set概念

HashSet类

HashSet 内部存储机制

equals 和 hashCode

LinkedHashSet

TreeSet

总结


Set概念

Set集合类似于一个罐子,程序可以依次把多个对象"丢进"Set集合,而Set集合通常不能记住元素的添加顺序。也就是说Set集合中的对象不按特定的方式排序,只是简单地把对象加入集合。Set集合中不能包含重复的对象,并且最多只允许包含一个null元素。

Set实现了Collection接口,它主要有两个常用的实现类:HashSet 类和 TreeSet

概念: 是一个不允许出现重复元素并且无序(访问顺序和插入顺序不一致)的集合(可以null)

Set没有添加额外的方法

Set主要包含三种存放数据类型的变量,分别是HashSetLinkedHashTreeSet

HashSet

特点:

1.不能保证元素的排列顺序,顺序可能与添加顺序不同,顺序也有可能发生变化

2.HashSet不是同步的,如果多个线程同时访问或修改一个HashSet,则必须通过代码来保证其同步

3.集合元素值可以是null

HashSet是Set接口的典型实现,大多数时候使用Set集合时就是使用这个实现类。HashSet是按照Hash算法来存储集合中的元素。因此具有很好的存取和查找性能。

HashSet 集合的元素值可以是null

HashSet是Set接口的经典实现,大多数时候使用Set集合时使用这个实现类。

HashSet按Hash算法来存储集合中的元素,因此具有很好的存取和查找性能。底层数据结构是哈希表

HashSet不能保证元素的排列顺序,顺序可能与添加顺序不同,顺序也可能发生变化

HashSet不是线程安全的,如果多个线程尝试同时修改HashSet,则最终结果是不确定的。必须在多线程访问时显式同步对HashSet的并发访问

HashSet 内部存储机制

当向HashSet集合中存入一个元素时,HashSet会调用该对象的hashCode方法来得到该对象的hashCode值,然后根据该hashCode值决定该对象在HashSet中的存储位置。如果两个元素通过equals 方法比较为true,但它们的hashCode方法返回的值为false,HashSet将会把它们存储在不同位置,依然可以添加成功。

所以,HashSet集合判断两个元素的标准时两个对象通过equals比较相等,并且两个对象的hashCode方法的返回值也相等。

总结: 元素的哈希值时通过hashcode方法来获取的,HashSet首先判断两个元素的哈希值,如果哈希值一样,接着会比较equals方法,如果equals为true,HashSet就视为同一个元素。如果,为false就不是同一个元素。

实现原理: 数组Node<K,V>[]+链表(jdk1.7) 数组+链表/红黑树(jdk1.8)

1、根据hashCode()方法计算出hash值,在进行一定运算,算出元素在数组中的存储位置---分组 2、如果此位置为null,就把此对象放进去

3、如果此位置已经有值,那会判断当前对象和此位置对象的hash值是否相同 如果相同,则继续判断equals方法 如果equals相同,则不存储 如果equals不相同,则以链表的方式存储 如果不相同,直接存储,以链表的方式 jdk1.8以后,如果链表上的对象超过8个,就以红黑树的方式存储,提高查询效率

    如果自定义类集合需要不重复
    我们就要重写自定义类的hashCode() equals()
 public static void main(String[] args) {
    HashSet<String> sites = new HashSet<String>();
        sites.add("Google");
        sites.add("Baidu");
        sites.add("Taobao");
        sites.add("Zhihu");
        sites.add("Baidu");  // 重复的元素不会被添加
        System.out.println(sites);
    }

equals 和 hashCode

Person类

public class Person {
    private String name;
    private int age;
    
    public Person(String name, int age) {
        super();
        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 TestHashSet {
    public static void main(String[] args) {
        HashSet<Integer> set=new HashSet<Integer>();
        set.add(12);
        set.add(23);
        set.add(23);
        System.out.println(set);//输出结果为: [23,12]
        System.out.println(set.contains(12));//判断是否含有12
        set.remove(23);//移除23
        set.clear();//清除所有元素        
        System.out.println(set);
​
        Iterator<Integer> it=set.iterator();        
        while(it.hasNext()) {   //无法获取单个元素//可以遍历
            System.out.println(it.next());
        }
        
        
        set.remove(12);
        set.add(20);            //在Set不能修改元素,只能先添再删,或者先删再添
        System.out.println(set);
        
        
        System.out.println("通话".hashCode());
        System.out.println("重地".hashCode());//hashCode相等
        
        HashSet<Person> pSet=new HashSet<Person>();
        Person p1=new Person("zhangsan",21);
        Person p2=new Person("lisi",21);
        Person p3=new Person("lisi",16);
        System.out.println(p1.hashCode());
        System.out.println(p2.hashCode());
        System.out.println(p3.hashCode());
        
        
        pSet.add(p1);
        pSet.add(p2);
        pSet.add(p3);
        System.out.println(pSet);
        //输出为[Person [name=lisi, age=16], Person [name=zhangsan, age=21], Person [name=lisi, age=21]]
        
    }
​
}

LinkedHashSet

LinkedHashSet 是Set集合的一个实现,具有Set集合不重复的特点,同时具有可预测的迭代顺序(插入顺序)。维护着一个运行于所有条目的双重链接列表。此链接列表定义了迭代顺序,保证访问顺序和插入顺序一致

LinkedHashSet是一个非线程安全的集合。

TreeSet

TreeSet 是一个有序的集合,它的作用是提供有序的Set集合。它继承于AbstractSet抽象类,实现了NavigableSet<E>, Cloneable, java.io.Serializable接口。

底层实现: 红黑树

使用元素的自然顺序对元素进行排序,或者根据创建set时提供的Comparator 进行排序,具体取决于使用的构造方法。

根据Comparable接口中compareTo方法来判断元素是否重复,不是equals()。但是一个类中同时有这两个方法时,相等的逻辑要一致。

总结

看到array,就要想到角标。

看到link,就要想到first,last。

看到hash,就要想到hashCode,equals.

看到tree,就要想到两个接口。Comparable,Comparator。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Illus1ion

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

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

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

打赏作者

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

抵扣说明:

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

余额充值