Java Collections.emptyList() 而不是空检查?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6546875/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-16 07:39:34  来源:igfitidea点击:

Collections.emptyList() instead of null check?

javacollectionsnullempty-list

提问by Philip Kamenarsky

If I have a rarely used collection in some class which may be instantiated many times, I may sometimes resort to the following "idiom" in order to save unnecessary object creations:

如果我在某个类中有一个很少使用的集合,它可能会被多次实例化,我有时可能会诉诸以下“习惯用法”以节省不必要的对象创建:

List<Object> list = null;

void add(Object object) {
    if (list == null)
        list = new ArrayList<Object>();

    list.add(object);
}

// somewhere else
if (list != null)
    for (Object object : list)
         ;

Now I was wondering if I couldn't eliminate those null checks using Collections.emptyList(), however then I would have to alter the if check in add()like so:

现在我想知道我是否不能使用 消除那些空检查Collections.emptyList(),但是我将不得不add()像这样更改 if 检查:

if (list == Collections.<Object>emptyList())
    list = new ArrayList<Object>();

Is there a better way to handle this other than just allocating a new empty collection every time?

除了每次都分配一个新的空集合之外,有没有更好的方法来处理这个问题?

EDIT:just to be clear, I would liketo use Collections.emptyList(), but the above check in add() is really really ugly... I was wondering if there's a better way to do it or even a whole other way of handling this.

编辑:为了清楚起见,我使用 Collections.emptyList(),但上面的 add() 检查真的很难看......我想知道是否有更好的方法来做到这一点,甚至是其他方式处理这个。

采纳答案by aioobe

in order to save unnecessary object creations

为了节省不必要的对象创建

That's a really bad idea which will litter your code with == nullchecks and other handling of corner cases (and presumably end up in null pointer exceptions anyway)!

这是一个非常糟糕的主意,它会在您的代码中进行== null检查和其他极端情况的处理(并且大概最终会出现空指针异常)!

Now I was wondering if I couldn't eliminate those null checks using Collections.emptyList()

现在我想知道我是否不能使用消除那些空检查 Collections.emptyList()

No, not really. emptyList()returns an empty list. You coulddo

不,不是真的。emptyList()返回一个空列表。你可以

if (list.equals(Collections.<Object>emptyList()))

but that will still throw a NullPointerException if list == null, so it's still not what you're after.

但这仍然会抛出 NullPointerException if list == null,所以它仍然不是你想要的。

My recommendation: Always initialize the list to new ArrayList<Object>, or, if you for instance want to return an empty list from a method, use Collections.emptyList()instead. (This returns the same instance every time, so no unnecessary object creation there either.)

我的建议:始终将列表初始化为new ArrayList<Object>,或者,例如,如果您想从方法返回一个空列表,请Collections.emptyList()改用。(这每次都返回相同的实例,因此也没有不必要的对象创建。)

And then use .isEmpty()to check if a collection is empty or not.

然后用于.isEmpty()检查集合是否为空。

回答by Thomas

If you only use the list for iterations, you could just use: for (Object object : list)which wouldn't do anything for empty lists, i.e. not a single iteration.

如果你只使用列表进行迭代,你可以使用:for (Object object : list)这不会对空列表做任何事情,即不是一次迭代。

Otherwise just check list.isEmpty().

否则只是检查list.isEmpty()

回答by Peter Lawrey

emptyList() doesn't allocate an object each time.

emptyList() 不会每次都分配一个对象。

I would create less of the object which contains the List so you can create the list every time.

我会创建较少的包含列表的对象,以便您每次都可以创建列表。

What you can do is

你能做的是

private List<Object> list = Collections.emptyList();

private List<Object> listForWrite() {
    return list.isEmpty() ? list = new ArrayList<Object>() : list;
}


void add(Object object) {
    listForWrite().add(object);
}


// avoid creating an Iterator every time.
for (int i = 0, size = list.size(); i < size; i++) {
     ;
}

回答by Tapas Bose

You can create a utility class with static methods, like:

您可以使用静态方法创建实用程序类,例如:

public class ListUtil {

/**
 * Checks if {@link List} is null or empty.
 *
 * @param <E> the generic type
 * @param list the list
 * @return true, if is null or empty
 */
public static <E> boolean isNullOrEmpty(List<E> list) {
    return list == null || list.size() == 0;
}

/**
 * Checks if {@link List} is not null and empty.
 *
 * @param <E> the generic type
 * @param list the list
 * @return true, if is not null and empty
 */
public static <E> boolean isNotNullAndEmpty(List<E> list) {
    return list != null && list.size() != 0;
}

}

}

回答by Nick Campion

I find it easiest to follow this convention:

我发现遵循这个约定最容易:

  1. If the point of my methods is to return a Collection, the method never returns null. Null is ambiguous. Instead I return Collection.emptyXXX()or ImmutableXXX.of()if using Guava.

  2. If I have an object which is maintaining an internal list as a member, instantiate it in the constructor. I try not to do lazy instantiation unless I can prove its a significant gain because lazy code, in my opinion, tends to be more difficult to debug when issues arise.

  1. 如果我的方法的重点是返回一个集合,则该方法永远不会返回 null。Null 是不明确的。相反,我返回Collection.emptyXXX()ImmutableXXX.of()使用番石榴。

  2. 如果我有一个将内部列表作为成员维护的对象,请在构造函数中实例化它。我尽量不做懒惰的实例化,除非我能证明它有很大的好处,因为在我看来,懒惰的代码出现问题时往往更难调试。

I really see immutable or unmodifiable empty collections being a part of a contract external to objects. If you are using the collection internally, I can only really see using immutable collections if you have a good reason (concurrency, consistency, immutability of the object)

我真的认为不可变或不可修改的空集合是对象外部合同的一部分。如果您在内部使用集合,我只能在有充分理由(对象的并发性、一致性、不变性)的情况下才真正看到使用不可变集合

回答by Aaron

Here is what I use for a helper method in some of my code. Really works nicely in reducing the ton of null checks I'd normally have to place before iterating over lists. If you want a list that wouldn't be immutable then you can return a new list object instead of Collections.emptyList

这是我在一些代码中用于辅助方法的内容。确实可以很好地减少我通常在遍历列表之前必须进行的大量空检查。如果你想要一个不可变的列表,那么你可以返回一个新的列表对象而不是 Collections.emptyList

/**
 * Helper method to return an empty list if provided one is null.
 *
 * @param list the list
 * @return the provided list or an empty one if it was null
 */
private static <T> List<T> emptyIfNull(List<T> list) {
    if (list == null) {
        return Collections.emptyList();
    }
    return list;
}

You then just use the helper method like so:

然后,您只需使用辅助方法,如下所示:

for (Object object : emptyIfNull(existingList)) { ... }

If the list object is null, then the helper method will return the static empty list and the contents of your loop will be skipped. This is a nice way to avoid having to create null checks wrapping any list iterations.

如果列表对象为空,则辅助方法将返回静态空列表并跳过循环的内容。这是一种避免必须创建空检查来包装任何列表迭代的好方法。

I've made the internals of the list be of type Object just for the example, but you'd obviously change this to be whatever makes the most sense for your usage.

仅作为示例,我已将列表的内部结构设为 Object 类型,但您显然会将其更改为对您的使用最有意义的内容。

回答by Johnny

The suggested answers are absolutely correct, just small tip - in Java 8 you can use the new Optional classto handle the case where the list instance is null, in a more functional approach.

建议的答案是绝对正确的,只是小技巧 - 在 Java 8 中,您可以使用新的Optional 类以更实用的方法处理列表实例为空的情况。

For example, something like this:

例如,这样的事情:

public static List<String> addElement(List<String> list, String toAdd) {
       List<String> newList = Optional.ofNullable(list).orElse(new ArrayList<>());
       newList.add(toAdd);
       return newList;
}

Following a tip in the comments, it's better to replace new ArrayList<>()with Collections.emptyList()in order to prevent the creation of a new instance of an empty ArrayList

继在评论小费,这是更好地更换new ArrayList<>()Collections.emptyList()为了防止一个空的ArrayList的新实例的创建

public static List<String> addElement(List<String> list, String toAdd) {
   List<String> newList = Optional.ofNullable(list).orElse(Collections.emptyList());
   newList.add(toAdd);
   return newList;
}

回答by Adam Wise

Here's a variation on using optional as @Stas suggested, but also using the isEmpty immutable collection as originally requested in the question:

这是使用 @Stas 建议的 optional 的变体,但也使用问题中最初要求的 isEmpty 不可变集合:

public static List<String> addElement(List<String> list, String toAdd) {
   List<String> newList = Optional.ofNullable(list).orElse(Collections.emptyList());
   newList.add(toAdd);
   return newList;
}

This approach is also the closest thing I can find to the nice ability in Javascript to use an empty array if the collection is null.

如果集合为空,这种方法也是我能找到的最接近 Javascript 中使用空数组的能力的最接近的方法。

For example:

例如:

// no need to indent everything inside a null check of myObjects
for (MyObj myObj : Optional.ofNullable(myObjects).orElse(Collections.emptyList())){
    // do stuff with myObj
}

回答by jastka4

There is an emptyIfNullmethod in package org.apache.commons.collections4;. It returns an empty list if the one provided is null.

中有一个emptyIfNull方法package org.apache.commons.collections4;。如果提供的列表为空,它将返回一个空列表。

List<Object> list = CollectionUtils.emptyIfNull(list);