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

所属分类: 软件编程 / java 阅读数: 110
收藏 0 赞 0 分享

我们都曾在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实现一个简单的文件上传案例示例代码

这篇文章主要介绍了Java实现一个简单的文件上传案例,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
收藏 0 赞 0 分享

详解在spring中使用JdbcTemplate操作数据库的几种方式

这篇文章主要介绍了详解在spring中使用JdbcTemplate操作数据库的几种方式,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
收藏 0 赞 0 分享

java中的switch case语句使用详解

这篇文章主要介绍了java中的switch case语句使用详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
收藏 0 赞 0 分享

深入理解Java 线程池

这篇文章主要介绍了Java 线程池的相关资料,文中讲解非常细致,帮助大家更好的理解和学习,感兴趣的朋友可以了解下
收藏 0 赞 0 分享

详解mybatis #{}和${}的区别、传参、基本语法

这篇文章主要介绍了mybatis #{}和${}的区别、传参、基本语法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
收藏 0 赞 0 分享

MyBatis 中 ${}和 #{}的正确使用方法(千万不要乱用)

这篇文章主要介绍了MyBatis 中 ${}和 #{}的正确使用方法,本文给大家提到了MyBatis 中 ${}和 #{}的区别,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
收藏 0 赞 0 分享

详解Mybatis中的 ${} 和 #{}区别与用法

这篇文章主要介绍了Mybatis中的 ${} 和 #{}区别与用法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
收藏 0 赞 0 分享

Maven安装过程图文详解

这篇文章主要介绍了Maven安装过程,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
收藏 0 赞 0 分享

SpringBoot登录拦截配置详解(实测可用)

这篇文章主要介绍了SpringBoot登录拦截配置详解(实测可用),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
收藏 0 赞 0 分享

JAVA 内存溢出案例汇总

这篇文章主要介绍了JAVA 内存溢出案例的汇总,文中讲解非常细致,帮助各位工作学习时避免内存溢出,感兴趣的朋友可以了解下
收藏 0 赞 0 分享
查看更多