簡體   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