Java中替代equals,compareTo和toString的方法

 更新时间:2020年06月03日 15:46:44   作者:jeck猫  
这篇文章主要介绍了Java中替代equals,compareTo和toString的方法,文中代码十分详细,帮助大家更好的理解的学习,感兴趣的朋友可以了解下

我们都曾在POJO中重写过equals(),compareTo()和toString()方法。但是另有其他能做到职责分离的更好的方法并带来更简洁的代码。阅读这篇文章来一探究竟吧!

更简明的职责——摆脱equals、compareTo和toString方法

你曾经查看过java文档中的Object类吗?也许吧。每当你向上追溯继承树的时候都会止步于这个类。你会注意到,该类有几个方法是每一个类都必须继承的。而你最喜欢重写的方法可能就是toString(), .equals() and .hashCode() 这三个了。(至于为何总是应该同时重写后两个方法,请看Per-Åke Minborg写的这篇文章:https://minborgsjavapot.blogspot.com/2014/10/new-java-8-object-support-mixin-pattern.html

但是仅仅有这几个方法显然是不够的。许多人将标准库中的其他的接口如Comparable和Serializable加以组合。但是这样真的明智吗?为什么每个人都很迫切地去自己实现这些方法呢?事实上,当你准备将对象存储在一些容器中,如HashMap,并且想要控制哈希冲突的时候,实现你自己的.equals()方法和.hashCode()方法确实有它的意义,但实现compareTo()和toString()方法又是为何呢?

本篇文章中我将提出一种使用到Speedment 开源项目上的软件设计方法,这里的对象的方法被定义为存储于变量上的方法引用,而不是重写它们。这样做确有一些好处:你的POJO将会更短小简洁,通用的方法可以不需要继承而进行复用并且你可以因地制宜地使用它们。

原始的代码

首先我们来看下面的代码:这里有一个典型的Java类Person。在使用中需要从一个Set中打印出每一个person对象,并且按照姓在前和名在后的顺序排列(以防出现两个相同姓氏的人)。

// Person.java
public class Person implements Comparable<Person> { 
private final String firstname; 
private final String lastname; 
public Person(String firstname, String lastname) {  
this.firstname = firstname;  this.lastname = lastname;
 } 
 public String getFirstname() {  
 return firstname;
 } 
 public String getLastname() {  
 return lastname;
 } 
 @Override
 public int hashCode() {  
 int hash = 7;
  hash = 83 * hash + Objects.hashCode(this.firstname);
  hash = 83 * hash + Objects.hashCode(this.lastname);  return hash;
 } 
 @Override
 public boolean equals(Object obj) {  
 if (this == obj) return true;  if (obj == null) return false;  if (getClass() != obj.getClass()) return false;  final Person other = (Person) obj;  if (!Objects.equals(this.firstname, other.firstname)) {   return false;
  }  return Objects.equals(this.lastname, other.lastname);
 } 
 @Override
 public int compareTo(Person that) {  
 if (this == that) return 0;  else if (that == null) return 1;  int comparison = this.firstname.compareTo(that.firstname);  if (comparison != 0) return comparison;
  comparison = this.lastname.compareTo(that.lastname);  return comparison;
 } 
 @Override
 public String toString() {  
 return firstname + " " + lastname;
 }
}
// Main.java
public class Main { public static void main(String... args) {  final Set
  people = new HashSet<>();
  people.add(new Person("Adam", "Johnsson"));
  people.add(new Person("Adam", "Samuelsson"));
  people.add(new Person("Ben", "Carlsson"));
  people.add(new Person("Ben", "Carlsson"));
  people.add(new Person("Cecilia", "Adams"));
  people.stream()
   .sorted()
   .forEachOrdered(System.out::println);
 }
}

Output

run:
Adam Johnsson
Adam Samuelsson
Ben Carlsson
Cecilia Adams
BUILD SUCCESSFUL (total time: 0 seconds)

Person 类实现了一些方法来控制输出。 hashCode()equals() 方法确保同一个person对象不会被重复添加到set中。.compareTo() 方法用于排序方法中生成应有的顺序。而重写方法toString()是在System.out.println() 被调用的时候控制每个Person对象的输出格式。你认出这种结构了吗?几乎任何一个java工程中都会有它。

替代这些代码

相比于将所有这些方法写入Person类中,我们可以让它保持尽量的简洁,使用方法引用去处理它们。我们可以删除所有equals(),hashCode(),compareTo()和toString()的样板式代码,取而代之的是下面介绍的两个静态变量:COMPARATORTO_STRING

// Person.java
public class Person { 
private final String firstname; 
 private final String lastname; 
 public Person(String firstname, String lastname) { 
 this.firstname = firstname; this.lastname = lastname;
 }
 public String getFirstname() { 
 return firstname;
 } 
 public String getLastname() { 
 return lastname;
 } 
 public final static Comparator<Person> COMPARATOR =
 Comparator.comparing(Person::getFirstname)
 .thenComparing(Person::getLastname); public final static Function<Person, String> TO_STRING =
 p -> p.getFirstname() + " " + p.getLastname();
}
// Main.java
public class Main { 
public static void main(String... args) {  
  final Set
  people = new TreeSet<>(Person.COMPARATOR);
  people.add(new Person("Adam", "Johnsson"));
  people.add(new Person("Adam", "Samuelsson"));
  people.add(new Person("Ben", "Carlsson"));
  people.add(new Person("Ben", "Carlsson"));
  people.add(new Person("Cecilia", "Adams"));
  people.stream()
   .map(Person.TO_STRING)
   .forEachOrdered(System.out::println);
 }
}

Output

run:
Adam Johnsson
Adam Samuelsson
Ben Carlsson
Cecilia Adams
BUILD SUCCESSFUL (total time: 0 seconds)

这样实现的好处是我们可以在不用更改Person类的情况下替换排序策略或打印格式。这将使代码拥有更强的可维护性和复用性,更不用说更快的编写速度了。

译文链接:http://www.codeceo.com/article/java-equals-compareto-tostring.html
英文原文:Get Rid of Equals, CompareTo and toString

以上就是Java中替代equals,compareTo和toString的方法的详细内容,更多关于Java替代equals,compareTo和toString的资料请关注脚本之家其它相关文章!

相关文章

  • java多线程并发executorservice(任务调度)类

    java多线程并发executorservice(任务调度)类

    这篇文章主要介绍了线程并发ScheduledExecutorService类,设置 ScheduledExecutorService ,2秒后,在 1 分钟内每 10 秒钟蜂鸣一次
    2014-01-01
  • JAVA中字符串如何与整型数字相加

    JAVA中字符串如何与整型数字相加

    这篇文章主要介绍了JAVA中字符串如何与整型数字相加,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-07-07
  • Java虚拟机JVM性能优化(三):垃圾收集详解

    Java虚拟机JVM性能优化(三):垃圾收集详解

    这篇文章主要介绍了Java虚拟机JVM性能优化(三):垃圾收集详解,本文讲解了众多的JVM垃圾收集器知识点,需要的朋友可以参考下
    2014-09-09
  • Java循环调用多个timer实现定时任务

    Java循环调用多个timer实现定时任务

    这篇文章主要介绍了Java循环调用多个timer实现定时任务,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-07-07
  • 基于java中集合的概念(详解)

    基于java中集合的概念(详解)

    下面小编就为大家带来一篇基于java中集合的概念(详解)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-09-09
  • JVM中的守护线程示例详解

    JVM中的守护线程示例详解

    这篇文章主要给大家介绍了关于JVM中守护线程的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-01-01
  • Java扑克牌速算24的方法

    Java扑克牌速算24的方法

    这篇文章主要为大家详细介绍了Java扑克牌速算24的方法,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-03-03
  • spring boot配置读写分离的完整实现步骤

    spring boot配置读写分离的完整实现步骤

    数据库配置主从之后,如何在代码层面实现读写分离?所以下面这篇文章主要给大家介绍了关于spring boot配置读写分离的完整步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2018-09-09
  • Java调用Shell命令的方法

    Java调用Shell命令的方法

    这篇文章主要介绍了Java调用Shell命令的方法,实例分析了java调用shell命令的相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-07-07
  • java数学归纳法非递归求斐波那契数列的方法

    java数学归纳法非递归求斐波那契数列的方法

    这篇文章主要介绍了java数学归纳法非递归求斐波那契数列的方法,涉及java非递归算法的使用技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-07-07

最新评论