返回空列表时的良好编程习惯

时间:2018-03-13 04:22:16

标签: java

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,因为它更具可读性和显性。什么是更好的approch 1或2?

问题是如果列表为空,我应该返回相同的列表或显式创建新的空列表并返回

3 个答案:

答案 0 :(得分:1)

Collections.emptyList()返回Collections的一个常量成员,因此不需要花费太多时间(可以通过JIT优化)和内存。

另一方面,getListfromSomewhereElse的返回可能会锁定从其他代码返回的空列表。您可以获得任何列表类,并且可能需要一些内存。一般来说这不是问题,因为这个方法也是由你自己的团队派生,审查和测试的,但谁知道外部库中会发生什么?

例如,getListfromSomewhereElse可以将非常大的文件读入内存,然后从中删除所有元素。因此,空列表将容纳数千个元素容量,除非您/他们知道其结构并消除过多的容量。方法1将通过使用已存在的常量列表来简单地克服这一点。

作为旁注,如果您处理java 8流样式中的列表元素,您自然会获得带有.collect(Collectors.toList())步骤的新列表。但是JDK开发人员在这种情况下不强制使用emptyList。

因此,除非您确定在getListfromSomewhereElse中,否则最好返回Collections.emptyList()(或新的ArrayList()或您通过方法契约返回的任何列表类型。)

答案 1 :(得分:0)

我更喜欢

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()无法修改。根据{{​​1}}的结果,getListFromSomewhereElse的客户可能会感到困惑,有时可能会修改它获得的列表,而在某些其他情况下,它会抛出doSomething。 E.g。

UnsupportedOperationException

将抛出UnsupportedOperationException

,而

List<String> list = someClass.doSomething(null);
list.add("A");

可能会有效,具体取决于List<String> list = someClass.doSomething("B"); list.add("A");

的结果

答案 2 :(得分:0)

很少需要做(伪代码):

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,那么可能需要感激地处理空值,但在许多情况下,完全适合记录输入不能为空,并让它抛出一个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