检查集合为空或非空的最佳方法及null条件

5

我们使用像ArrayList、HashMap等许多集合。

我们经常需要检查条件,例如列表是否为null。

有多种方法可以检查我们的集合是否为null。

不同的方式。

1. if(list==null)
2. if(list.size()==0)
3. if(list.isEmpty())

有时我们需要检查列表是否为空,通常我们会通过以下方式进行检查

1. if(list!=null)
2. if(list.size()>0)
3. if(!list.isEmpty()) 

哪种情况最好?或者我们需要把它们结合起来考虑程序执行的性能吗?
11个回答

9
最佳组合应该是:
if(list!=null && !list.isEmpty()){

        //Yeah ,do something
}

一种是针对null的检查,另一种是检查是否存在任何内容


6
在一个糟糕的世界里,这是最好的检查方式。在一个良好的世界里,确保清单一开始就不会为空。 - Sean Patrick Floyd
正如一些人指出的那样,对于集合来说返回null是一个不好的主意;然而,你并不总是控制所提供给你的数据,比如第三方库和Web服务端点。当然,你可以要求数据,但这并不总是最用户友好的选项。当你无法控制输入数据时,你只有两个选择,验证数据是否存在并在否则抛出错误,或者按照本答案中所述检查数据。 - user1209809

6
1. if(list!=null)

请确保永远不会发生这种情况!!

阅读《Effective Java第二版》by Joshua Bloch
条款43: 返回空数组或集合,而不是null

[...] 总之,从返回数组或集合的方法中返回null没有任何理由,应该返回一个空的数组或集合。从C编程语言中继承下来的null-return习惯用法,在C语言中,数组长度与实际数组是分开返回的。在C中,如果返回长度为零,则分配数组没有优势。

简而言之,让您的方法返回Collections.emptyList()而不是null,这样您就少了一件要担心的事情。

2. if(list.size()>0)
3. if(!list.isEmpty()) 

这要看情况。对于像ArrayList这样简单的集合,它们是等价的。但如果你的Collection实际上是数据库查询的实时视图呢?调用size()可能是一个非常昂贵的操作,而isEmpty()始终是O(1)的。我建议使用isEmpty()。

还可以参见Jon Skeet在这里的回答:https://dev59.com/Fmgu5IYBdhLWcg3wrY4m#11152624


3
Java8中,你可以使用Optional来正确处理空值情况。例如,函数filterList可以正确处理animalsNullanimalWithNullElements两个列表:
List<String> animalsNull = null;

List<String> animalWithNullElements = new ArrayList<String>();
        animalWithNullElements.add(0, null);
        animalWithNullElements.add(1, "Guybrush Threepwood");
        animalWithNullElements.add(2, null);

private static List<String> filterList(List<String> animals) {
        return Optional.ofNullable(animals)
               .orElseGet(Collections::emptyList)
               .stream()
               .filter(Objects::nonNull)
               .collect(Collectors.toList());
    }

看起来不错,但使用 Optional 和 Collection 感觉有点奇怪。我已经阅读了几个关于这种做法不好的来源。你认为呢? - Rafael
嗨@Rafael,你能否发布源代码? - Johnny
你可以在这里找到一个有趣的讨论 -> https://dev59.com/ymAg5IYBdhLWcg3wjrgZ - Rafael
谢谢,这是一个不错的帖子,但是它提到了 Optional 的另一种用法。请注意,在你粘贴的链接中,Optional 不是集合内部的元素。而在我的代码示例中,Optional 是列表本身。 - Johnny
你说得对。我错过了来源。这里有一个不同的来源,它谈到使用可选项作为集合包装器并不好 -> http://dolszewski.com/java/java-8-optional-use-cases/ - Rafael
这个也是一个不同的情况。在你提到的文章中,他们讨论了使用一种Optional<List<...>>类型作为返回值,而我并没有建议这样做。 - Johnny

2
我们经常会检查条件,比如列表是否为空。
首先,一个null的集合和一个空的集合是不同的事情。如果你需要测试一个集合是否为null,则需要使用不同的测试来测试集合是否为空。
其次,如果一个集合既可以是null也可以是空(并且它们在应用程序设计中“意味着”相同的东西),那么你的设计存在问题。你最有可能表示……你试图表示的内容……一种方式,而不是两种方式都有/没有。
第三,通常最好使用空集合而不是null,因为你可以统一处理空和非空集合。相比之下,null始终需要作为特殊情况处理。(如果你忘记处理null情况,那么就有可能出现NullPointerExceptions。)
话虽如此……
哪个条件最好?还是需要考虑这些条件的组合以及程序执行的性能?
如果你真的需要处理null的情况,那么你只能测试null。
对于isEmpty()和size()==0的比较:
这两个谓词应该给出相同的答案(除非你有无限的惰性集合...),但在某些情况下,isEmpty()在理论上可能更快。
后者取决于集合类型的实现:具体来说,取决于size()方法是否需要计算集合元素。(我认为标准集合类中没有任何一个类具有这个属性,但这并不意味着你找不到一些具有这个属性的类...)
因此,最优谓词很可能是:
 c != null && !c.isEmpty()

或者

 !c.isEmpty()

根据你是否需要考虑 null 值来做出决策。显然的推论是,如果你不使用 null 表示空集合,那么你的应用程序很可能会更加高效...同时更加简单和稳健。 (如果您需要不可变的空集合对象,可以免费从 Collections 类定义的方法/静态方法中获取它们。)


2

这取决于你想要做什么。如果你想确保一个列表存在并且有一些元素,那么你将使用

if (list != null && !list.isEmpty())

如果我可以给出一些建议,在返回集合时,默认情况下返回一个空集合。这样你就可以避免空值。


1

Apache的commons-collections包中有一个有用的实用类叫做CollectionUtils。使用它后,代码将如下所示:

if(CollectionUtils.isEmpty(collection))

它看起来很好,底层具有相同的调用:

public static boolean isEmpty(Collection coll) { return coll == null || coll.isEmpty(); }


0
你可以使用以下两个谓词来完成它:
public static final Predicate<String> NULL_OR_EMPTY = (in) -> null == in || "".equals(in);

public static final Predicate<List<String>> STRING_LIST_NULL_OR_EMPTY = (strList) ->  strList.stream().filter(NULL_OR_EMPTY).collect(Collectors.toList()).size() > 0;

0

null 表示 list 被初始化为 null。 null 的列表 sizeisEmpty 将抛出 NullPointerException。但是,非空的 list 可以为空或 size==0。

(list!=null) != (list.size()==0)

size==0和isEmpty是等价的。

(list.size()==0) ==  list.isEmpty()

0

处理这个问题有多种方法:

1:如果代码确保集合不会为null,可以通过在构造函数中初始化或作为字段初始化来实现,那么调用者就不需要在任何地方理想地检查null。只需进行isEmpty检查即可:

private List<Integer> numbers = new ArrayList<Integer>(); //or in constructor

// 调用者可以安全地使用

if(numbers.isEmpty)

2:或者编写一个实用方法来进行nullempty检查,不需要size检查,因为它已经在isEmpty调用内部发生。在代码中其他地方使用此实用程序方法。

public static boolean empty(Collection<?> col) {
   return col == null || col.isEmpty();
}

0

这取决于你的程序结构。例如,我有一个叫做ArrayUtils的帮助类,在其中有一个像这样的API:

public static <E> boolean isEmpty(final Collection<E> collection)
{
    return collection == null || collection.isEmpty();
}

当我知道可能会得到一个null列表时,我使用这个,但当我绝对确定它不是null时,我只使用if (collection.isEmpty)。这也提高了代码的可读性。

collection.size() > 1是多余的,因为你可以使用其他API。


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