Set集合

Set集合犹如一个罐子,程序可以将多个对象放入Set集合,Set集合通常不能记住元素的添加顺序。Set集合不允许包含相同的元素,如果尝试把两个相同元素添加进同一个Set集合中,则添加操作失败。

HashSet类:

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

HashSet的特点:

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

②HashSet不是同步的,如果多个线程同时访问一个HashSet,假设有两个或者两个以上线程同时修改了HashSet集合时,则必须通过代码来保证其同步。

③集合元素可以是null。

HashSet的hashCode和equals:

当向HashSet集合中存入一个元素时,HashSet会调用该对象的hashCode()方法来得到该对象的HashCode值,然后根据HashCode值决定该对象在HashSet中的存储位置。如果有两个元素通过equals()方法比较返回true,但它们的hashCode()方法返回值不相同,HashSet将会把它们存储在不同的位置,依然可以添加成功。小结:HashSet集合判断两个元素相等的标准是两个对象通过equals()方法比较相等,并且两个对象的HashCode()方法返回值也相等。 

如果两个对象通过equals()方法比较返回true,但这两个对象的hashCode()方法返回不同的hashCode值,那么HashSet会将这两个对象保存在不同的位置,而如果两个对象的hashCode值相等,但它们通过equals()方法比较时返回false则:两个对象的HashCode值相同,HashSet试图将它们保存在同一个位置,但是又不行(否则就只剩下一个对象),所以实际上会在这个位置用链式结构来保存多个对象,但是HashSet访问集合元素时是根据元素的hashCode值来快速定位的,如果HashSet中两个以上的元素具有相同的hashCode值,将会导致性能下降。

注:如果需要把某个类的对象保存到HashSet集合中,重写这个类的equals()方法和hashCode()方法时,应该尽量保证两个对象通过equals()方法比较返回true时,它们的hashCode()方法返回值也相等。

重写hashCode()方法的一般步骤:

①把对象内每个有意义的实例变量(即每个参与equals()方法比较标准时的实例变量)计算出一个int类型的hashCode值。

②用第一步计算出来的多个hashCode值组合计算出一个hashCode值返回。

LinkedHashSet类:

LinkedHashSet集合也是根据元素的hashCode值来决定元素的存储位置,但是它同时使用链表维护元素的次序,即元素看起来是以插入的顺序保存的。(当遍历LinkedHashSet集合里的元素时,将会按照元素的添加顺序访问集合里的元素),LinkedHashSet需要维护元素的插入顺序,因此性能略低于HashSet,但是迭代访问时却有很好的性能。

注:LinkedHashSet虽然使用链表记录集合元素的添加顺序,但LinkedHashSet依然不允许集合元素重复。

TreeSet类:

TreeSet是SortSet接口的实现类,TreeSet可以确保集合元素处于排序状态,与HashSet集合相比,TreeSet还提供了几个额外的方法:

  • Comparator comparator():如果TreeSet采用了定制排序,则该方法返回定制排序所使用的Comparator;如果TreeSet采用了自然排序,则返回null。
  • Object first():返回集合中的第一个元素。
  • Object last():返回集合中的最后一个元素。
  • Object lower(Object e):返回集合中位于指定元素之前的元素(即小于指定元素的最大元素)
  • Object higher(Object e):返回集合中位于指定元素之后的元素(即大于指定元素的最小元素)

小结:TreeSet并不是根据元素的插入顺序进行排序的,而是根据元素实际值的大小来进行排序的。HashSet集合采用hash算法来决定元素的存储位置不同,TreeSet采用红黑树的数据结构来存储集合元素,TreeSet支持两种排序方法:自然排序和定制排序。

自然排序:TreeSet调用集合元素的compareTo(Object e)方法来比较元素之间的大小关系,然后将集合元素按升序排列。

Java提供了一个Comparable接口,该接口里定义了一个compareTo(Object e)方法,该方法返回一个整数值,实现该接口的类必须实现该方法,实现了该接口的类的对象就可以比较大小,m.compareTo(n)>0,则m大于n,<0则m小于n,==0时则m=n。

 注:大部分类在实现compareTo(Object e)方法时,都需要将被比较对象强制转换成相同类型,因为只有两个相同类的实例才会比较大小,当试图把一个对象添加到TreeSet集合时,TreeSet会调用该对象的compareTo()方法与集合中的其他元素进行比较(即集合中的元素与该元素是同一个类的实例)。如果向RreeSet集合中添加的对象是程序员自定义类的对象,则可以向TreeSet中添加多种类型的对象,前提是用户自定义类实现了Compareble接口,且实现compareTo()方法没有进行强制类型转换,但是当试图取出TreeSet中的元素时,依然会出现异常。

总结:如果希望TreeSet能够正常工作,则TreeSet只能添加同一种类型的对象。当把一个对象加入TreeSet集合中时,TreeSet调用该对象的compareTo()方法与容器中的其他对象比较大小,然后根据红黑树找到它的存储位置。如果两个对象通过compareTo()方法比较相等,新对象将无法添加到TreeSet集合中。

定制排序:TreeSet的自然排序是根据集合元素的大小,TreeSet将他们以升序排列,如果需要实现定制排序,则可以通过Comparator接口的帮助,该接口里包含一个int compare(T o1,T o2)方法,该方法用于比较o1和o2的大小,如果需要实现定制排序,则需要在创建TreeSet集合对象时,提供一个Comparator对象与该TreeSet集合关联,由该Comparator对象负责集合元素的排序逻辑。

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值