【问题标题】:Check two arguments for null in an elegant way以优雅的方式检查两个参数是否为 null
【发布时间】:2017-08-28 10:23:15
【问题描述】:

我正在迭代 两个集合,并检查两个集合是否包含 相同的元素。我不能使用 Java 8。


一年后编辑:

我在问题中创建了方法来检查两个集合是否包含相同的元素,而没有考虑我将两个 Collection 实现传递给该方法这一事实。

但 Collection 并不能确定元素的排序方式。我正在迭代这些集合。因此,Collection 的某些实现可以按随机顺序保存元素,同时包含相同的元素。


两个集合都包含可比较元素和内容 被定义为相等,如果所有元素都返回一个 x.compareTo(y) 和 0。

两个值被定义为不同,如果其中一个为空,另一个不为空。 我想找到一种优雅的方式来比较无效性并防止 对最终的 compareTo() 进行空检查。

我目前的实现:

    public static <T extends Comparable<T>> boolean isSame(@Nullable Collection<T> a, @Nullable Collection<T> b) {

    if (a == null || b == null) {
        return (a == null && b == null);
    }

    if (a.size() != b.size()) {
        return false;
    }
    Iterator<T> aIt = a.iterator();
    Iterator<T> bIt = b.iterator();
    while (aIt.hasNext()) {
        T aValue = aIt.next();
        T bValue = bIt.next();
        if (aValue == null || bValue == null) {
            if (aValue == null ^ bValue == null) {
                return false;
            }
            //both null, don't compare, continue looping...
        } else if (aValue.compareTo(bValue) != 0) {
            return false;
        }
    }
    return true;
}

如果两个值都为空,我想继续 while 循环,因为那是 定义为相等。

但我在这部分苦苦挣扎:

if (aValue == null || bValue == null) {
        if (aValue == null ^ bValue == null) {
            return false;
        }
}

问题:

是否有一种更优雅、更易读的方法来比较 null,如果两者都不为 null,则进行进一步比较,如果只有一个为 null,则返回 false,如果两个值都为 null,则继续循环?强>

【问题讨论】:

  • if (aValue == null &amp;&amp; bValue == null) continue; 这不行吗?
  • 当然可以,但是在调用 compareTo 之前,我必须至少检查 aValue 是否为 null,否则它可能会因 NPE 而崩溃
  • 天真的解决方案:为每个集合创建一个新列表,对每个列表进行排序,然后比较排序后的列表。更明智的方法:为每个集合创建一个计数映射,键是元素,值是集合中每个元素的计数(HashMap 允许以 null 作为键),然后比较两个映射是否相同条目,或者仅当它们各自的条目集相等时。

标签: java collections null iterator java-7


【解决方案1】:

以下顺序应该可以正常工作:

if(aValue == null && bValue == null) continue; // both null; continue
if(aValue == null || bValue == null) return false; // any null; return false
if(aValue.compareTo(bValue) != 0) { // both non-null; compare
    return false;
}

【讨论】:

  • 该死的,你比我早了 7 秒;)我会删除我的答案!
  • @ParkerHalo 当我在你的帖子中输入相同的内容时,你删除了;)
  • @nullpointer 是的,我明白了..让我再考虑几个小时。但我怀疑是否有更好的方法。提前致谢 - 如果没有其他方法,会将答案标记为正确。
  • @JacksOnF1re 当然。更多的想法和头脑风暴是我一直投票支持的事情。
  • @JacksOnF1re 如果可以的话,我想补充一点:在我看来,可读选项应该(几乎)总是优于短选项。当您稍后返回“旧”代码时,它将帮助必须阅读您的代码的其他人甚至您自己。
【解决方案2】:

在 Java8 中,您可以构建一个 Comparator,以创建一个额外的对象为代价替换比较序列(您需要决定是否关心它):

Comparator<T> cmp = Comparator.nullsLast(Comparator.naturalOrder());

比较器会为您处理空值比较(因为您假设两个 nulls 相等):

while (aIt.hasNext()) {
    T aValue = aIt.next();
    T bValue = bIt.next();
    if (cmp.compare(aValue, bValue) != 0) {
      return false;
    }
}

【讨论】:

  • 我认为这就是要走的路。此外,您可以将比较器对象存储到静态最终字段中,因此您不需要时不时地重新创建它。
  • 感谢您的回答!不幸的是,我不能在这里使用 Java 8!我编辑了问题。
  • @JacksOnF1re,我认为我们不应该放弃我对这个问题的回答:未来的读者可能能够使用 Java8,并且可能会发现我的回答很有帮助。所以我会把它放在这里。
  • 当然可以!我也这么认为。
猜你喜欢
  • 2012-11-04
  • 1970-01-01
  • 2020-08-11
  • 2015-06-10
  • 2013-09-11
  • 1970-01-01
  • 1970-01-01
  • 2014-11-03
  • 1970-01-01
相关资源
最近更新 更多