集合。emptylist()而不是null检查?

时间:2022-02-08 19:45:29

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()来消除这些null检查,但是如果添加(),我将不得不修改if check ():

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 like to 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(),但是上面的check in add()是非常丑陋的……我想知道是否有更好的方法来做这件事,甚至是另一种处理方式。

7 个解决方案

#1


16  

in order to save unnecessary object creations

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

That's a really bad idea which will litter your code with == null checks 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()

现在,我想知道是否可以使用collection. emptylist()消除那些null检查

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

不,不是真的。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.

但是如果list == null,那么它仍然会抛出NullPointerException,因此它仍然不是您要处理的内容。

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,或者,如果您想要从方法返回空列表,请使用Collections.emptyList()。(每次都返回相同的实例,因此也不需要创建不必要的对象。)

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

然后使用. isempty()检查集合是否为空。

#2


6  

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

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

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

#3


1  

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++) {
     ;
}

#4


1  

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

下面是我在一些代码中使用的辅助方法。在对列表进行迭代之前,可以很好地减少我通常需要放置的大量null检查。如果您想要一个不不可变的列表,那么您可以返回一个新的列表对象,而不是集合。

/**
 * 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.

如果列表对象为空,则helper方法将返回静态空列表,并跳过您的循环内容。这是避免创建任何列表迭代的空检查的好方法。

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.

我已经将列表的内部设置为类型对象,但您显然会将其更改为对您的使用最有意义的内容。

#5


0  

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()。

#6


0  

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

}

}

#7


0  

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.

    如果我的方法的要点是返回一个集合,那么这个方法永远不会返回null。零是模棱两可的。相反,我返回Collection.emptyXXX()或ImmutableXXX.of(),如果使用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.

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

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)

我确实看到了不可变或不可修改的空集合是对象外部契约的一部分。如果您在内部使用这个集合,那么如果您有很好的理由(并发性、一致性、对象的不可变性),那么我只能看到使用不可变集合。

#1


16  

in order to save unnecessary object creations

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

That's a really bad idea which will litter your code with == null checks 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()

现在,我想知道是否可以使用collection. emptylist()消除那些null检查

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

不,不是真的。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.

但是如果list == null,那么它仍然会抛出NullPointerException,因此它仍然不是您要处理的内容。

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,或者,如果您想要从方法返回空列表,请使用Collections.emptyList()。(每次都返回相同的实例,因此也不需要创建不必要的对象。)

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

然后使用. isempty()检查集合是否为空。

#2


6  

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

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

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

#3


1  

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++) {
     ;
}

#4


1  

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

下面是我在一些代码中使用的辅助方法。在对列表进行迭代之前,可以很好地减少我通常需要放置的大量null检查。如果您想要一个不不可变的列表,那么您可以返回一个新的列表对象,而不是集合。

/**
 * 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.

如果列表对象为空,则helper方法将返回静态空列表,并跳过您的循环内容。这是避免创建任何列表迭代的空检查的好方法。

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.

我已经将列表的内部设置为类型对象,但您显然会将其更改为对您的使用最有意义的内容。

#5


0  

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()。

#6


0  

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

}

}

#7


0  

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.

    如果我的方法的要点是返回一个集合,那么这个方法永远不会返回null。零是模棱两可的。相反,我返回Collection.emptyXXX()或ImmutableXXX.of(),如果使用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.

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

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)

我确实看到了不可变或不可修改的空集合是对象外部契约的一部分。如果您在内部使用这个集合,那么如果您有很好的理由(并发性、一致性、对象的不可变性),那么我只能看到使用不可变集合。