2015-09-18 32 views
7

在Java 7中,最後一個列表中沒有空元素,如果我想獲得一個列表的最後一個不爲空元素,我寫的是這樣的:獲得通過使用Java 8

public CustomObject getLastObject(List<CustomObject> list) { 
    for (int index = list.size() - 1; index > 0; index--) { 
     if (list.get(index) != null) { 
      return list.get(index); 
     } 
    } 
    // handling of case when all elements are null 
    // or list is empty 
    ... 
} 

我想寫一個通過使用lambda表達式或Java 8的另一特點。例如,如果我想先不要空元素我可以這樣寫短代碼:

public void someMethod(List<CustomObject> list) { 
    ..... 
    CustomObject object = getFirstObject(list).orElseGet(/*handle this case*/); 
    ..... 
} 

public Optional<CustomObject> getFirstObject(List<CustomObject> list) { 
    return list.stream().filter(object -> object != null).findFirst(); 
} 

也許有人知道如何解決這個問題呢?

+0

它不是**總是**使用lambdas的好主意。鑑於@Tunaki的答案,使用非lambda方式的讀者會更清楚。 – lschuetze

+1

相關:[「如何在Java 8中以相反順序從列表中獲取有序流」](http://stackoverflow.com/q/29403614/2711488)和[「獲取流的最後一個元素的最有效方法「](http://stackoverflow.com/q/27547519/2711488) – Holger

+0

@lschuetze,我只是學習lambdas的可能性,我想知道如何使用新功能來決定簡單的問題 – ZhenyaM

回答

10

一個可能的解決辦法是遍歷以相反的順序列表,並保持第一個非空元素:

public Optional<CustomObject> getLastObject(List<CustomObject> list) { 
    return IntStream.range(0, list.size()).mapToObj(i -> list.get(list.size() - i - 1)) 
              .filter(Objects::nonNull) 
              .findFirst(); 
} 

注意,還有就是流API中沒有findLast方法,因爲流不一定有序或有限。

另一種解決方案是迭代列表並通過僅保留當前元素來減少它。這有效地將Stream減少到最後一個元素。

public Optional<CustomObject> getLastObject(List<CustomObject> list) { 
    return list.stream().filter(Objects::nonNull).reduce((a, b) -> b); 
} 
+0

非常感謝,這是正確的。 – ZhenyaM

+2

@assylias ['Collection.stream()'](https://docs.oracle.com/javase/8/docs/api/java/util/Collection.html#stream--)返回的流是連續的(每Javadoc) – Tunaki

+1

這就是爲什麼我鏈接到其他問題,以表明,例如使用'reduce'來獲取最後一個元素[是一個既定的解決方案](http://stackoverflow.com/a/27547525/2711488)。它甚至可以並行執行。約簡函數必須是關聯的,但不需要是可交換的。 – Holger