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
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:
我发现遵循这一惯例是最容易的:
-
If the point of my methods is to return a Collection, the method never returns null. Null is ambiguous. Instead I return
Collection.emptyXXX()
orImmutableXXX.of()
if using Guava.如果我的方法的要点是返回一个集合,那么这个方法永远不会返回null。零是模棱两可的。相反,我返回Collection.emptyXXX()或ImmutableXXX.of(),如果使用Guava。
-
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
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:
我发现遵循这一惯例是最容易的:
-
If the point of my methods is to return a Collection, the method never returns null. Null is ambiguous. Instead I return
Collection.emptyXXX()
orImmutableXXX.of()
if using Guava.如果我的方法的要点是返回一个集合,那么这个方法永远不会返回null。零是模棱两可的。相反,我返回Collection.emptyXXX()或ImmutableXXX.of(),如果使用Guava。
-
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)
我确实看到了不可变或不可修改的空集合是对象外部契约的一部分。如果您在内部使用这个集合,那么如果您有很好的理由(并发性、一致性、对象的不可变性),那么我只能看到使用不可变集合。