ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

java-检查是否只有2个对象的特定属性相等

2019-11-22 02:03:33  阅读:228  来源: 互联网

标签:guava java functional-programming


假设我有一个Person类(假设可以设置所有属性,也可以为null):

public class Person {
  private String firstName;
  private String secondName;
  private Address address;

  public String getFirstName() { return firstName; }
  public String getSecondName() { return secondName; }
  public String getAddress() { return address; }
}

如果我有两个Person实例,并且想检查两个实例是否具有相同的firstName和secondName,那么我不能简单地调用equals(),因为这还将检查地址是否相等(以及与此相关的任何其他属性).

我将不得不编写这样的函数:

boolean areNamesEqual(Person person1, Person person2) {
  if(person1 == null || person2 == null) {
    return person1 == person2;
  }
  if(person1.getFirstName() != null ? !person1.getFirstName().equals(person2.getFirstName()) : person2.getFirstName() != null) {
    return false;
  }
  if(person1.getSecondName() != null ? !person1.getSecondName().equals(person2.getSecondName()) : person2.getSecondName() != null) {
    return false;
  }
  return true;
}

有没有更干净的方式表达这一点?感觉到Java在表达这个简单的想法方面已经走了很多圈.我已经开始研究Google Guava,并且看到可以使用Objects.equal()来改进问题:

boolean areNamesEqual(Person person1, Person person2) {
  if(person1 == null || person2 == null) {
    return person1 == person2;
  }
  if(Objects.equal(person1.getFirstName(), person2.getFirstName())) {
    return false;
  }
  if(Objects.equal(person1.getSecondName(), person2.getSecondName())) {
    return false;
  }
  return true;
}

但是我仍然必须检查Person对象本身是否为null,并分别编写两次getFirstName()和getSecondName().感觉必须有更好的表达方式.

像这样的代码将是理想的:

(person1, person2).arePropertiesEqual(firstName, secondName)

有了这个,我不需要在任何地方检查是否为空,也不必提前返回,也不必多次写入firstName或secondName.

有任何想法吗?

解决方法:

使用Java(至少在Java 8和lambda之前)和Guava,由于Java不是一种功能语言,您将步入正轨.有关更多意见,请参见Guava Wiki中的Caveats section in Functional Explained.

实际上,您可以执行此操作,但是要付出更多代码的代价,因此您应该真正评估是否需要它.就像是:

private <T> boolean arePropertiesEqual(T t1, T t2, Function<T, ?>... functions) {
    if (t1 == null || t2 == null) {
        return t1 == t2; // Shortcut
    }
    for (Function<T, ?> function : functions) {
        if (!Objects.equal(function.apply(t1), function.apply(t2))) {
            return false;
        }
    }
    return true;
}

private static class PersonFirstNameFunction 
        implements Function<Person, String> {
    @Override
    public String apply(Person input) {
        return input.getFirstName();
    }
}

private static class PersonLastNameFunction
        implements Function<Person, String> {
    @Override
    public String apply(Person input) {
        return input.getLastName();
    }
}

private void someMethod(Person p1, Person p2) {
    boolean b = arePropertiesEqual(p1, p2, 
            new PersonFirstNameFunction(), new PersonLastNameFunction());
}

注意:我既没有编译也没有运行上面的代码,由于使用通用数组(在varargs中),它可能至少有警告.

Java 8已经缩短了,看起来像:

private <T> boolean arePropertiesEqual(T t1, T t2, Function<T, ?>... functions) {
    if (t1 == null || t2 == null) {
        return t1 == t2; // Shortcut
    }
    for (Function<T, ?> function : functions) {
        if (!Objects.equals(function.apply(t1), function.apply(t2))) {
            return false;
        }
    }
    return true;
}

private void someMethod(Person p1, Person p2) {
    boolean b = arePropertiesEqual(p1, p2,
            Person::getFirstName, Person::getLastName);
}

请注意,这里使用的是java.util.Objects和java.util.functions.Function,而不是Guava.

现在,这真的比命令代码“更好”吗?

标签:guava,java,functional-programming
来源: https://codeday.me/bug/20191122/2056335.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有