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

294

当两个字符串中的任意一个或两个都可能为 null 时,我想比较它们是否相等。

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

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

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

最好的方式是如何检查包括 null 在内的所有可能的值?


可能是A better way to compare Strings which could be null的重复问题。 - jimr
2
请注意,您将方法称为“compare”有点令人困惑,因为它在字符串中具有不同的含义。您应该将其称为“equals”。 - Florian F
12个回答

500
自从Java 7以来,您可以使用静态方法java.util.Objects.equals(Object, Object)在不关心两个对象是否为null的情况下执行相等检查。
如果两个对象都为null,它将返回true;如果一个为null而另一个不是,则它将返回false。否则,它将返回调用第一个对象上的equals方法并将第二个对象作为参数的结果。

1
这种方法将类型检查推迟到程序运行时。它有两个后果:在运行时速度会变慢,而且IDE不会让你知道如果你意外地尝试比较不同类型的数据。 - averasko
14
当您使用Object.equals(Object)时,没有编译时类型检查。 Objects.equals(Object, Object)的工作方式与普通的equals非常相似,并且通过IDE的类型推断/检查,这些规则是启发式规则,也适用于Objects.equals(Object, Object)(例如,IntelliJ IDEA 2016.2对于普通的equals和来自Objects的equals都具有相同的检查)。 - Mark Rotteveel
4
我喜欢这种方法。现在的事情不需要包含一些ApacheCommons库。 - Torsten Ojaperv
1
@SimonBaars 这不是在空对象上运行函数,而是传递两个参数的静态方法,这两个参数可以是 null 或者一个对象的引用。 - Mark Rotteveel
11
我认为这应该是被采纳的答案。我不想在每个应用程序中都重新发明轮子。 - Neuron
显示剩余6条评论

223

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

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

3
为什么不把String类型改为Object类型,使其更加通用?这样做后,如果您升级到Java 7,就能得到相同的结果。 - Tom
5
你所提供的方法在哪个Java类中? - Volodymyr Levytskyi
51
嘿!你不应该有一个返回true/false的比较方法。等于(Equals)与比较(Compare)是不同的概念。比较应该用于排序。你应该返回小于零(<0)、等于零(==0)或大于零(>0)来表示哪个比另一个低/高。 - coya
28
我建议使用Objects.equals(Object, Object),就像Mark Rotteveel在他的回答中指出的那样(请给他点赞)。 - Neuron
1
@hyperpallium,String.equals 内部首先做的事情是引用比较,就像 if(this == other) return true;。由于 Stringfinal 的,即使是最简单的 JVM 也能够内联该代码,更不用说现代常见的实现了。因此,如果字符串是相同的(相等且已经被池化),早期的引用比较并没有什么帮助,在所有其他情况下,它都没有任何帮助,除了两个字符串都是 null 的情况,也许会有一些帮助。 - Holger
显示剩余6条评论

55
对于这些情况,最好使用Apache Commons StringUtils#equals,它已经处理了空字符串。 代码示例:
public boolean compare(String s1, String s2) {
    return StringUtils.equals(s1, s2);
}
如果您不想添加该库,只需复制 StringUtils.equals 方法的源代码,并在需要时应用它。

3
自Java7起,java.util.Objects是最佳选择,请参见其他答案。 - tkruse

29

对于那些使用Android系统的人,无法使用API 19的Objects.equals(str1, str2)方法的话,可以使用以下代码:

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

它是null安全的。在Android上,由于字符串池的存在,几乎所有相同的字符串都可以使用"=="运算符进行比较,因此很少需要使用更昂贵的string.equals()方法,而长度检查则是一种快速过滤大部分不匹配的方法。

源代码:

/**
 * 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;
}

9

使用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方法:

public static boolean compare(String first, String second) { return(Objects.isNull(first) ? Objects.isNull(second) : first.equals(second)); }

(该方法用于比较两个字符串是否相等)

7

从版本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)

这些提供了安全的空值字符串比较。


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

该方法比较两个字符串是否相等,区分大小写。如果两个字符串相等,则返回true;否则返回false。
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

StringUtils.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

4
您可以使用以下方式使用java.util.Objects
public static boolean compare(String str1, String str2) {
    return Objects.equals(str1, str2);
}

1
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);
}

这是你想要的吗?


5
如果两个字符串都为 null,则该情况返回 false,这可能不是期望的结果。 - JScoobyCed

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

    return str1.equals(str2);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接