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

所属分类: 软件编程 / java 阅读数: 98
收藏 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基于反射机制实现全部注解获取的方法,结合实例形式分析了java反射机制获取注解的具体实现方法与操作注意事项,需要的朋友可以参考下
收藏 0 赞 0 分享

Java 信号量Semaphore的实现

这篇文章主要介绍了Java 信号量Semaphore的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
收藏 0 赞 0 分享

eclipse+maven+spring mvc项目基本搭建过程

这篇文章主要介绍了eclipse+maven+spring mvc项目基本搭建过程,本文图文并茂给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
收藏 0 赞 0 分享

Spring boot集成swagger2生成接口文档的全过程

这篇文章主要给大家介绍了关于Spring boot集成swagger2生成接口文档的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用Spring boot具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
收藏 0 赞 0 分享

Java冒泡排序法和选择排序法的实现

这篇文章主要介绍了Java冒泡排序法和选择排序法的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
收藏 0 赞 0 分享

Spring Cloud Alibaba教程之Sentinel的使用

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

Josephus环的四种解法(约瑟夫环)基于java详解

这篇文章主要介绍了Josephus环的四种解法(约瑟夫环)基于java详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
收藏 0 赞 0 分享

Java继承Thread类创建线程类示例

这篇文章主要介绍了Java继承Thread类创建线程类,结合实例形式分析了java线程操作相关使用技巧与注意事项,需要的朋友可以参考下
收藏 0 赞 0 分享

Java使用Callable和Future创建线程操作示例

这篇文章主要介绍了Java使用Callable和Future创建线程操作,结合实例形式分析了java使用Callable接口和Future类创建线程的相关操作技巧与注意事项,需要的朋友可以参考下
收藏 0 赞 0 分享

springBoot使用JdbcTemplate代码实例

这篇文章主要介绍了springBoot使用JdbcTemplate代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
收藏 0 赞 0 分享
查看更多