用可能的空值比较Java中的两个对象

我想比较两个字符串是否相等,当其中一个或两个都可以为null时。

因此,我不能简单地调用.equals(),因为它可以包含null值。

到目前为止,我尝试过的代码:

boolean compare(String str1, String str2) {
return ((str1 == str2) || (str1 != null && str1.equals(str2)));
}

检查包括null在内的所有可能值的最佳方法是什么?

279565 次浏览
boolean compare(String str1, String str2) {
if(str1==null || str2==null) {
//return false; if you assume null not equal to null
return str1==str2;
}
return str1.equals(str2);
}

这是你想要的吗?

boolean compare(String str1, String str2) {
if (str1 == null || str2 == null)
return str1 == str2;


return str1.equals(str2);
}
boolean compare(String str1, String str2) {
return (str1==null || str2==null) ? str1 == str2 : str1.equals(str2);
}

这是Java内部代码使用的(在其他compare方法上):

public static boolean compare(String str1, String str2) {
return (str1 == null ? str2 == null : str1.equals(str2));
}

对于这些情况,最好使用Apache Commons stringutil # =,它已经处理空字符串。代码示例:

public boolean compare(String s1, String s2) {
return StringUtils.equals(s1, s2);
}

如果不想添加库,只需复制StringUtils#equals方法的源代码并在需要时应用它。

好的,那么best possible solution是什么意思呢?

如果您指的是最可读的,那么对于有经验的Java程序员来说,所有可能的解决方案都差不多。但在我看来,最有可读性的是这个

 public boolean compareStringsOrNulls(String str1, String str2) {
// Implement it how you like
}

换句话说,将实现隐藏在可以内联的简单方法中(理想情况下)。

(你也可以“外包”给第三方工具库……如果你已经在你的代码库中使用了它。)


如果你指的是最具性能,那么:

  1. 最高效的解决方案取决于平台和环境,
  2. “上下文”问题之一是null参数出现的相对(动态)频率,
  3. 可能并不在乎哪个版本更快…因为这种差异可能太小,不会对整体应用程序性能产生影响
  4. 如果这真的很重要,那么找出在你的平台上哪个版本最快的唯一方法就是尝试两个版本并衡量差异。

从Java 7开始,你可以使用静态方法java.util.Objects.equals(Object, Object)对两个对象执行相等检查,而不关心它们是否是null

如果两个对象都是null,它将返回true,如果一个对象是null,另一个对象不是,它将返回false。否则,它将返回在第一个对象上调用equals的结果,并将第二个对象作为参数。

对于那些不能使用API 19的对象的android用户。等于(str1, str2)

android.text.TextUtils.equals(str1, str2);

它是空安全的。它很少需要使用更昂贵的string.equals()方法,因为由于Android的字符串池, android上相同的字符串几乎总是与"=="操作数比较为真,长度检查是过滤大多数不匹配的快速方法。

源代码:

/**
* Returns true if a and b are equal, including if they are both null.
* <p><i>Note: In platform versions 1.1 and earlier, this method only worked  well if
* both the arguments were instances of String.</i></p>
* @param a first CharSequence to check
* @param b second CharSequence to check
* @return true if a and b are equal
*/
public static boolean equals(CharSequence a, CharSequence b) {
if (a == b) return true;
int length;
if (a != null && b != null && (length = a.length()) == b.length()) {
if (a instanceof String && b instanceof String) {
return a.equals(b);
} else {
for (int i = 0; i < length; i++) {
if (a.charAt(i) != b.charAt(i)) return false;
}
return true;
}
}
return false;
}

你可以像下面那样使用java.util.Objects

public static boolean compare(String str1, String str2) {
return Objects.equals(str1, str2);
}

从3.5版开始,Apache Commons StringUtils有以下方法:

static int  compare(String str1, String str2)
static int  compare(String str1, String str2, boolean nullIsLess)
static int  compareIgnoreCase(String str1, String str2)
static int  compareIgnoreCase(String str1, String str2, boolean nullIsLess)

它们提供了空安全的字符串比较。

使用Apache Commons StringUtils类的equals(-,-)和equalsIgnoreCase(-,-)方法比较两个字符串。

stringutil的。= (-, -):

StringUtils.equals(null, null)   = true
StringUtils.equals(null, "abc")  = false
StringUtils.equals("abc", null)  = false
StringUtils.equals("abc", "abc") = true
StringUtils.equals("abc", "ABC") = false

stringutil的。equalsIgnoreCase (-, -):

StringUtils.equalsIgnoreCase(null, null)   = true
StringUtils.equalsIgnoreCase(null, "abc")  = false
StringUtils.equalsIgnoreCase("xyz", null)  = false
StringUtils.equalsIgnoreCase("xyz", "xyz") = true
StringUtils.equalsIgnoreCase("xyz", "XYZ") = true

使用Java 8:

private static Comparator<String> nullSafeStringComparator = Comparator
.nullsFirst(String::compareToIgnoreCase);


private static Comparator<Metadata> metadataComparator = Comparator
.comparing(Metadata::getName, nullSafeStringComparator)
.thenComparing(Metadata::getValue, nullSafeStringComparator);


public int compareTo(Metadata that) {
return metadataComparator.compare(this, that);
}

或者您也可以使用Java使用下面的方法

公共静态布尔值比较(字符串第一个,字符串第二个){ 返回(Objects.isNull(第一次)?Objects.isNull(秒): first.equals(秒)); } < / p >