使用TreeSet 实现 自定义对象去重 且排序

项目里有一个取数据的算法,返回List<Vo>这样的集合,返回的集合要求没有重复的对象且按发布时间做排序。
第一时间想到TreeSet这个数据结构。

一、对自定义对象去重

重写自定义对象的equals 和 hashCode方法

SUN官方的文档中规定

如果重定义equals方法,就必须重定义hashCode方法,以便用户可以将对象插入到散列(哈希)表中

那么 SUN 公司是出于什么考虑做了这个规定呢?
在集合框架中的HashSet,HashTable和HashMap
都使用哈希表的形式存储数据,而hashCode计算出来的哈希码便是它们的身份证。

哈希码的存在便可以:

  • 1.快速定位对象,提高哈希表集合的性能。
  • 2.只有当哈希表中对象的索引即hashCode和对象的属性即equals同时相等时,才能够判断两个对象相等。
  • 3.从上面可以看出,哈希码主要是为哈希表服务的,其实如果不需要使用哈希表,也可以不重写hashCode。
  • 4.但是SUN公司应该是出于对程序扩展性的考虑(万一以后需要将对象放入哈希表集合中),才会规定重写equals的同时需要重写hashCode,以避免后续开发不必要的麻烦。

重写equals的注意事项

Java语言规范要求equals需要具有如下的特性:

自反性:对于任何非空引用 x,x.equals()应该返回true。
对称性:对于任何引用 x 和 y,当且仅当y.equals(x)返回true,x.equals(y)也应该返回true。
传递性:对于任何引用 x、y 和 z,如果x.equals(y)返回true,y.equals(z)
也应返回同样的结果。
一致性:如果 x 和 y 引用的对象没有发生变化,反复调用x.equals(y)
应该返回同样的结果。
对于任意非空引用 x,x.equals(null) 应该返回false。

更多详细的说明请参考
Java 重写 equals 与 hashCode 的注意事项

这里我需要以主键文章ID为准来去重,对TopicVO对象复写hashCode和 equals方法:

@Override
public int hashCode()
{
    return topicId.hashCode();
}

 @Override
  public boolean equals(Object obj) {
         if(obj instanceof TopicVo) {
             TopicVo vo = (TopicVo) obj;
               return (vo.getTopicId().equals(this.getTopicId()));
        }
         return super.equals(obj);
  }

二、对自定义对象排序

复写 compareTo方法,复写规则如下:

1.返回 1 那么当前的值会排在 被比较者 后面。
2.返回 0 那么当前的值【不会被加入到 TreeSet 中】,因为当前的值【被认为 是跟现有的某一个值相等】。
3.返回 -1 会被添加到 被比较者 的前边。

代码:

   @Override
public int compareTo(Object obj) {
    // TODO Auto-generated method stub
    TopicVo o = (TopicVo) obj;
    // 按照时间进行降序排列
    if (this.getAuditAt().before(o.getAuditAt())) {
        return 1;
    }
    if (this.getAuditAt().equals(o.getAuditAt()) && this.getTopicId().equals(o.getTopicId())) {
        return 0;
    }
    return -1;
}

这里注意返回0的情况,有可能两条记录有同样的时间数据,因为要加上唯一标识TopicId也相等才能说明是同一条记录,不然有可能会丢失数据。

使用时直接把自定义对象TopicVo丢进去 TreeSet<TopicVo> 里就可以实现自动排序和去重了,这样子程序只需要专注于按照业务规则取数据就行了

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容