繁体   English   中英

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

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM