[英]Good programming practice while returning empty list
List<String> doSomething(String input){
if(input == null){
return Collections.emptyList();
}
List<String> lst = getListfromSomewhereElse(input)
if(lst.isEmpty(){
return Collections.emptyList(); //Approach 1
// return lst; //Return same empty list
}
// do some more processing on lst
return lst;
}
我更喜欢方法1,因为它更具可读性和明确性。 什么是更好的方法1或2?
问题是列表是否为空,我应该返回相同的列表还是显式创建新的空列表并返回
Collections.emptyList()返回Collections的一个常量成员,因此不花费过多时间(可以通过JIT优化)和内存。
另一方面,getListfromSomewhereElse的返回可能会锁定从其他代码返回的空列表。 可能您可以获得任何列表类,并且可能会占用一些内存。 通常这不是问题,因为此方法也由您自己的团队派生,审查和测试,但是谁知道外部库中发生了什么?
例如,getListfromSomewhereElse可以将很大的文件读入内存,然后从其中删除所有元素。 因此,空列表将容纳数千个元素,除非您/他们知道其结构并摆脱了过多的能力。 方法1将通过使用已经存在的常量列表简单地克服这一问题。
附带说明一下,如果您以Java 8流样式处理列表元素,则自然可以通过.collect(Collectors.toList())步骤获得新列表。 但是在这种情况下,JDK开发人员不会强制emptyList。
因此,除非您确定在getListfromSomewhereElse中,否则最好返回Collections.emptyList()(或新的ArrayList()或通过方法协定返回的任何列表类型)。
我会比较喜欢
List<String> doSomething(String input) {
List<String> list = new ArrayList<String>();
if (input != null) {
List<String> listFromSomewhereElse = getListfromSomewhereElse(input);
list.addAll(listFromSomewhereElse);
}
return list;
}
请记住, Collections.emptyList()
是不可修改的。 取决于getListFromSomewhereElse
的结果, getListFromSomewhereElse
doSomething
的客户端可能会感到困惑,因为它有时可以修改其获取的列表,而在某些其他情况下,它将引发UnsupportedOperationException
。 例如
List<String> list = someClass.doSomething(null);
list.add("A");
将抛出UnsupportedOperationException
而
List<String> list = someClass.doSomething("B");
list.add("A");
可能会根据getListFromSomewhereElse
的结果工作
很少要做(伪代码):
if(input list is empty) {
return an empty list
} else {
map each entry in input list to output list
}
...因为将输入列表映射到输出列表的每种主流方式都会为空输入“自动”生成一个空列表。 例如:
List<String> input = Collections.emptyList();
List<String> output = new ArrayList<>();
for(String entry : input) {
output.add(entry.toLowerCase());
}
return output;
...将返回一个空列表。 将空列表视为特殊情况会浪费代码,而导致表达力较低。
同样,使用Stream
的现代Java方法具有相同的功能:
List<String> output = input.stream()
.map( s -> s.toLowerCase())
.collect(Collectors.toList());
...将在output
创建一个空列表,对空输入不进行任何“特殊”处理。
Collections.emptyList()
返回一个专门实现不可变的空列表的类。 它有一个非常简单的实现,例如,它的size()
仅return 0;
。
但这意味着您的呼叫者将无法修改返回的列表-仅当该列表为空时。 尽管不变性是一件好事,但有时返回不可变列表却有时不返回不可变列表是不一致的,这可能会导致您发现较晚的错误。 如果要强制执行不变性,请始终通过将响应包装在Collections.unmodifiableList()
中或使用诸如Guava之类的库中的不变列表来实现不变性。
您还将测试输入是否为空。 考虑是否有必要。 谁将调用该方法? 如果只有您,那就不要这样做! 如果您知道不打算这样做,则无需检查代码。
如果它是其他程序员的公共API,则可能需要感恩地处理null,但是在很多情况下,完全可以证明输入一定不能为null,如果发生输入,则让它抛出NullPointerException
(或者您可以强制执行通过Objects.requireNonNull(input)
启动方法,可以提早实现。
结论:我的建议是:
List<String> doSomething(String input){
Objects.requireNonNull(input); // or omit this and let an
// exception happen further down
return doMoreProcessingOn(getListfromSomewhereElse(input));
}
最好是doMoreProcessingOn()
产生一个新的List,而不是修改input
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.