清洁责任–摆脱均等,compareTo和toString

您是否看过Java中Object类的javadoc? 大概。 您倾向于时不时地到达那里,然后沿着继承树进行挖掘。 您可能已经注意到的一件事是,每个类都必须继承许多方法。 实现自己而不是坚持使用原始方法的最喜欢的方法可能是.toString()、. equals()和.hashCode()( Per-ÅkeMinborg在本文中很好地描述了为什么应该始终实现这两种方法) )。

但是这些方法显然还不够。 许多人从标准库(如ComparableSerializable)中混合使用其他接口。 但这真的很明智吗? 为什么每个人都想如此严重地自己实现这些方法? 好吧,如果您打算将它们存储在HashMap之类的文件中并希望控制哈希冲突,那么实现自己的.equals()和.hashCode()方法可能会很有意义,但是compareTo()和toString()呢?

在本文中,我将介绍一种在Speedment开源项目中使用的软件设计方法,其中将对对象进行操作的方法实现为存储在变量中的功能引用,而不是覆盖内置在方法中的Java。 这有几个优点。 您的POJO将更短,更简洁,可以重复使用通用操作而无需继承,并且可以灵活地在不同配置之间进行切换。

原始码

让我们从下面的示例开始。 我们有一个典型的Java类,名为Person。 在我们的应用程序中,我们希望按Set的顺序打印每个人的名字,其后跟姓氏(以防两个人共享相同的名字)。

人.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);
    }
}
输出量
run:
Adam Johnsson
Adam Samuelsson
Ben Carlsson
Cecilia Adams
BUILD SUCCESSFUL (total time: 0 seconds)

Person在此处实现了几种方法来控制流的输出。 hashCode()和equals()方法确保不能将重复的人添加到集合中。 sorted操作使用compareTo()方法产生所需的顺序。 重写的toString()方法最终控制了在调用System.out.println()时应如何打印每个Person。 您认识这种结构吗? 您几乎可以在几乎所有的Java项目中找到它。

替代代码

除了将所有功能都放入Person类之外,我们还可以尝试使其尽可能保持清洁,并使用功能性引用来处理这些修饰。 我们使用equals,hashCode,compareTo和toString删除所有样板,而是引入两个静态变量COMPARATOR和TO_STRING。

人.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);
    }
}
输出量
run:
Adam Johnsson
Adam Samuelsson
Ben Carlsson
Cecilia Adams
BUILD SUCCESSFUL (total time: 0 seconds)

这种方法的好处是,我们现在可以在不更改Person类的情况下替换打印的顺序和格式。 这将使代码更易于维护,更易于重用,而不是说编写起来更快。

翻译自: https://www.javacodegeeks.com/2016/02/cleaner-responsibilities-get-rid-equals-compareto-tostring.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值