Set接口下的 HashSet, LinkedHashSet, TreeSet

HashSet, LinkedHashSet, TreeSet都属于Set, Set实现了Collection接口。

set的两大特性:>1.无序性:无序性!= 随机性。真正的无序性,指的是存储顺序与添加顺序无关

>2.不可重复性:当向Set中添加进相同的元素的时候,后面的这个不能添加进去。

    Set判断两个对象相同不是使用==运算符,而是根据equals方法。也就是说,只要两个对象用equals方法比较返回true,Set就不会接受这两个对象。

HashSet  LinkedHashSet  存储元素时 ,会调用该对象的hashCode()方法得到HashCode值 然后根据哈希值来决定该对象在set中的存储位置。所以他们两个判断两个元素相等的标准是两个对象通过equals方法比较相等,并且两个对象的hashCode()方法返回值相等

     注意,如果要把一个对象放入HashSet或者linkedhashset中,重写该对象对应类的equals方法,也应该重写其hashCode()方法其规则是如果两个对象通过equals方法比较返回true时,其 hashCode也应该相同。另外,对象中用作equals比较标准的属性,都应该用来计算 hashCode的值

而 TreeSet 底层的数据结构是二叉树,但存储位置相对添加顺序也是无序的。

所以说set是用来存储无序的,不可重复的元素。


Hashset , LinkedHashSet,  TreeSet 都是线程不同步 线程不安全的

HashSet:1. 无序的,不保证数据写入的顺序。

         2. 集合中可以存入null 但是只能存入一个null

LinkedHashMap:是HashMap的子类,可以按照添加进Map的顺序实现遍历;

                它的底层也是根据hashcode()的哈希值来进行存储的是无序的, 但是它本身还会生成一张链表来维护写入的顺序,做到按顺序输出。

                它也可以存入null 但是也只能存入一个。

                相对于Hashset ;它是用于频繁的遍历,较少的添加、插入操作。

                HashSet适用于 添加 插入 删除等操作。

TreeSet: 由于treeset要进行排序所以不能存入null 如果存入会报空指针异常如果实现了Comparator接口,通过适当的写法,时可以避免出现空指针异常,能够存null

(可以按照添加进集合中的元素的指定属性进行排序)

>要求TreeSet添加进的元素必须是同一个类的!

        >两种排序方式:

        自然排序:①要求添加进TreeSet中的元素所在的类implements Comparable接口

                 ②重写compareTo(Object obj),在此方法内指明按照元素的哪个属性进行排序

                 ③向TreeSet中添加元素即可。若不实现此接口,会报运行时异常

     定制排序:①创建一个实现Comparator接口的实现类的对象。在实现类中重写Comparator的compare(Object o1,Object o2)方法

                 ②在此compare()方法中指明按照元素所在类的哪个属性进行排序

                 ③将此实现Comparator接口的实现类的对象作为形参传递给TreeSet的构造器中

                 ④向TreeSet中添加元素即可。若不实现此接口,会报运行时异常

        >要求重写的compareTo()或者compare()方法与equals()和hashCode()方法保持一致。


 初学者可以这样理解,hashCode方法实际上返回的就是对象存储的物理地址(实际可能并不是)。   这样一来,当集合要添加新的元素时,先调用这个元素的hashCode方法,就一下子能定位到它应该放置的物理位置上。 如果这个位置上没有元素,它就可以直接存储在这个位置上,不用再进行任何比较了;如果这个位置上已经有元素了, 就调用它的equals方法与新元素进行比较,相同的话就不存了,不相同就散列其它的地址。 所以这里存在一个冲突解决的问题。这样一来实际调用equals方法的次数就大大降低了,几乎只需要一两次。   所以,Java对于eqauls方法和hashCode方法是这样规定的:

1、如果两个对象相同,那么它们的hashCode值一定要相同;

2、如果两个对象的hashCode相同,它们并不一定相同    

上面说的对象相同指的是用eqauls方法比较。你当然可以不按要求去做了,但你会发现,相同的对象可以出现在Set集合中。同时,增加新元素的效率会大大下降。

hashcode这个方法是用来鉴定2个对象是否相等的。 那你会说,不是还有equals这个方法吗? 不错,这2个方法都是用来判断2个对象是否相等的。但是他们是有区别的。 一般来讲,equals这个方法是给用户调用的,如果你想判断2个对象是否相等,你可以重写equals方法,然后在代码中调用,就可以判断他们是否相等 了。简单来讲,equals方法主要是用来判断从表面上看或者从内容上看,2个对象是不是相等。

举个例子,有个学生类,属性只有姓名和性别,那么我们可以 认为只要姓名和性别相等,那么就说这2个对象是相等的。

hashcode方法一般用户不会去调用,比如在hashmap中,由于key是不可以重复的,他在判断key是不是重复的时候就判断了hashcode 这个方法,而且也用到了equals方法。这里不可以重复是说equals和hashcode只要有一个不等就可以了!所以简单来讲,hashcode相 当于是一个对象的编码,就好像文件中的md5,他和equals不同就在于他返回的是int型的,比较起来不直观。我们一般在覆盖equals的同时也要 覆盖hashcode,让他们的逻辑一致。

举个例子,还是刚刚的例子,如果姓名和性别相等就算2个对象相等的话,那么hashcode的方法也要返回姓名 的hashcode值加上性别的hashcode值,这样从逻辑上,他们就一致了。 要从物理上判断2个对象是否相等,用==就可以了。

 




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值