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的资料请关注我们其它相关文章!

(0)

相关推荐

  • java中的equals()和toString()方法实例详解

    java中的equals()和toString()方法 , 这里写个小例子帮助大家学习理解此部分知识. /* 所有对象的父类Object Object中的方法: equals() 对象是否相同的比较方法 toString()对象的字符串表现形式 */ class Person { String name; int age; Person(String name, int age) { this.name = name; this.age = age; } } class ObjectDemo {

  • 详解java中保持compareTo和equals同步

    详解java中保持compareTo和equals同步 摘要 : 介绍重写equlas()和comparable接口,两者进行不相同的判断.从而使两者的对应的list.indexOf()与 Collections.binarySearch()得到的不一样. 在Java中我们常使用Comparable接口来实现排序,其中compareTo是实现该接口方法.我们知道compareTo返回0表示两个对象相等,返回正数表示大于,返回负数表示小于.同时我们也知道equals也可以判断两个对象是否相等,那么

  • 浅谈java中BigDecimal的equals与compareTo的区别

    这两天在处理支付金额校验的时候出现了点问题,有个金额比较我用了BigDecimal的equals方法来比较两个金额是否相等,结果导致金额比较出现错误(比如3.0与3.00的比较等). [注:以下所讲都是以sun jdk 1.4.2版本为例,其他版本实现未必一致,请忽略] 首先看一下BigDecimal的equals方法: public boolean equals(Object x){ if (!(x instanceof BigDecimal)) return false; BigDecima

  • Java中比较运算符compareTo()、equals()与==的区别及应用总结

    前言 比较运算符用于判断两个数据的大小,例如:大于.等于.不等于.比较的结果是一个布尔值( true 或 false ). Java 中常用的比较运算符如下表所示: 本文主要给大家介绍了关于Java比较运算符compareTo().equals()与==区别及应用的相关内容,下面话不多说了,来一起看看详细的介绍吧 1.== 和 equals的区别: ==主要是两个变量值的比较,返回值为true 或者是false.对于普通变量,如:int a=10; int  b= 10; a==b,返回为 tr

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

    我们都曾在POJO中重写过equals(),compareTo()和toString()方法.但是另有其他能做到职责分离的更好的方法并带来更简洁的代码.阅读这篇文章来一探究竟吧! 更简明的职责--摆脱equals.compareTo和toString方法 你曾经查看过java文档中的Object类吗?也许吧.每当你向上追溯继承树的时候都会止步于这个类.你会注意到,该类有几个方法是每一个类都必须继承的.而你最喜欢重写的方法可能就是toString(), .equals() and .hashCod

  • java中重写equals()方法的同时要重写hashcode()方法(详解)

    object对象中的 public boolean equals(Object obj),对于任何非空引用值 x 和 y,当且仅当 x 和 y 引用同一个对象时,此方法才返回 true: 注意:当此方法被重写时,通常有必要重写 hashCode 方法,以维护 hashCode 方法的常规协定,该协定声明相等对象必须具有相等的哈希码.如下: (1) 当obj1.equals(obj2)为true时,obj1.hashCode() == obj2.hashCode()必须为true (2) 当obj

  • 详解Java中“==”与equals()的区别

    Java中"=="与equals()的区别 对于关系操作符"==",<Java编程思想>中是这样描述的:"关系操作符生成的是一个boolean结果,它们计算的是操作数的值之间的关系".这里的操作数的"值"值得我们注意.对于8种基本数据类型(boolean,byte,char,short,int,float,double,long),它们的变量直接存储的就是"值".所以,我们用"==&q

  • java中重写equals和重写hashCode()

    java中重写equals和重写hashCode() 记得在刚上初一的时候,第一堂数学课学的是集合,那时候我知道了集合是不允许重复元素存在的. hashCode 方法用于散列集合的查找,equals 方法用于判断两个对象是否相等. 为什么重写了 equals 方法,还要重写 hashCode 方法? 因为如果只重写了 equals 方法,两个对象 equals 返回了true,但是如果没有重写 hashCode 方法,集合还是会插入元素.这样集合中就出现了重复元素了. 接下来详细分析,以 Has

  • java集合——Java中的equals和hashCode方法详解

    Java中的equals方法和hashCode方法是Object中的,所以每个对象都是有这两个方法的,有时候我们需要实现特定需求,可能要重写这两个方法,今天就来介绍一些这两个方法的作用. equals()和hashCode()方法是用来在同一类中做比较用的,尤其是在容器里如set存放同一类对象时用来判断放入的对象是否重复. 这里我们首先要明白一个问题: equals()相等的两个对象,hashcode()一定相等,equals()不相等的两个对象,却并不能证明他们的hashcode()不相等.换

  • java 中String.equals和==的比较

     java 中String.equals和==的比较 初学java有段时间了,但是昨晚忽然就被"asd"==getpara("password")搞得不开心了:确实JAVA很多东西和以前接触过的语言完全不一样,比如最简单的new String("asd") !=new String ("asd"). 1 一个最简单的程序: public class A { public static void main(String args

  • 浅谈java中==以及equals方法的用法

    equals 方法是 java.lang.Object 类的方法. 有两种用法说明: (1)对于字符串变量来说,使用"=="和"equals()"方法比较字符串时,其比较方法不同. "=="比较两个变量本身的值,即两个对象在内存中的首地址. "equals()"比较字符串中所包含的内容是否相同. 比如: String s1,s2,s3 = "abc", s4 ="abc" ; s1 =

  • 重写Java中的equals方法介绍

    Java中,只有8种基本类型不是对象,例如:4种整形类型(byte, short, int,long),2种浮点类型(flout, double),boolean, char不是对象,其他的所有类型,不论是对象数组,列表等都扩展了Object类.了解学习Object中方法的设计原理和实现方式有助于更好的学习理解java语言.下面,我们首先学习一下Object中的equals方法. 判断两个对象相等时,JVM首先查找两个对象的hashCode, 如果两者hashCode不同,则返回false;如果

  • 如何区分JAVA中的equals与==

    java中的数据类型,可分为两类: 1.基本数据类型,也称原始数据类型. byte,short,char,int,long,float,double,boolean  他们之间的比较,应用双等号(==),比较的是他们的值. 基本数据类型比较 == 和 Equals 两者都是比较值:equals()与==都是java中用于进行比较的,返回boolean值,不同的是equals()是Object类中定义的一个方法,==是一个比较运算符.下面是equals()在Object中的源码: public b

随机推荐