如何使用 Optional 進行排序?
兩者mainProducts或productSublist在下面的代碼中可能null。結果串列productSubList應按日期排序。
List<ProductSubList> productSubList = Optional.of(mainProducts)
.map(MainProducts::getProductSubList)
.ifPresent(list -> list.stream().sorted(Comparator.comparing(ProductSubList::getProductDate))
.collect(Collectors.toList()));
上面顯示的代碼會產生編譯錯誤:
必需型別: ProductSubList ;提供:無效
部分答案似乎太長了,有沒有辦法讓它更短?
if (Optional.of(mainProducts).map(MainProducts::getProductSubList).isPresent()) {
productSublist = mainProducts.getProductSubList().stream()
.sorted(Comparator.comparing(ProductSubList::getProductDate))
.collect(Collectors.toList());
}
資源:如何避免在方法鏈接中檢查空值?
uj5u.com熱心網友回復:
似乎你正在尋找這樣的東西:
List<ProductSubList> productSubList = Optional.ofNullable(mainProducts)
.map(MainProducts::getProductSubList)
.map(list -> list.stream()
.sorted(Comparator.comparing(ProductSubList::getProductDate))
.collect(Collectors.toList()))
.orElse(Collections.emptyList());
uj5u.com熱心網友回復:
避免使用 Optional 替換空檢查
Optional 的設計初衷不是為了執行空值檢查,而且從一開始就沒有任何錯誤的隱式空值檢查。是的,如果有大量的空檢查,代碼很快就會變得不可讀,但這與其說是語言提供的工具的問題,不如說是設計問題。
對于遭受空值檢查的代碼,最好的補救措施是首先減少可空欄位的數量。在某些情況下,它很容易實作,特別是如果我們在這種情況下談論陣列集合,只需默認分配一個空集合。這個建議可以在很多地方找到,例如,參見Joshua Bloch的經典著作“Effective Java”中的“回傳空集合或陣列,而不是空值”項。
關于用法Optional.ofNullable(),這里參考了 Java 和 OpenJDK 開發人員 Stuart Marks 的回答:
Optional 的主要用途如下:
Optional旨在為庫方法回傳型別提供有限的機制,其中明確需要表示“無結果”,并且使用 null 極有可能導致錯誤。一個典型的代碼異味是,它不是使用方法鏈接來處理
Optional從某個方法回傳的代碼,而是創建一個可以Optional為空的東西,以便鏈接方法并避免條件。
話雖如此,如果您遵循建議避免保留可為空的集合并完全使用Optional空檢查,則可以以非常簡單易讀的方式撰寫代碼。
假設您的域類看起來像這樣(Lombok 的@Getter注釋用于簡潔):
@Getter
public static class ProductSubList {
private LocalDateTime productDate;
}
@Getter
public static class MainProducts {
private List<ProductSubList> productSubList = new ArrayList<>(); // or Collection.emptyList() if the class is mean only to carry the data and doesn't expose methods to modify the list
}
這將給出以下代碼:
if (mainProducts == null) return Collections.emptyList();
return mainProducts.getProductSubList().stream()
.sorted(Comparator.comparing(ProductSubList::getProductDate))
.toList();
幾乎不言自明。如果可以修改您正在使用的類,那將是最好的選擇。
如果由于某種原因,您無法修改MainProducts 和/或您提供了簡化版本并且有更多可以為空的移動部件,這里還有一些選項。
Stream.ofNullable()
您可以使用 Java 9 Stream.ofNullable():
List<ProductSubList> productSubList = Stream.ofNullable(mainProducts)
.flatMap(mainProd -> Stream.ofNullable(mainProd.getProductSubList()))
.flatMap(Collection::stream)
.sorted(Comparator.comparing(ProductSubList::getProductDate))
.toList();
請注意,它不是靈丹妙藥,我并不是說“Stream.ofNullable()到處插電”。過度使用Stream.ofNullable()可能會造成混亂,因為它可能看起來比實際嵌套的級別更多。
Stream.mapMulti()
我們可以使用 Java 16 減少流操作的數量并以更易讀的方式重新排列代碼Stream.mapMulti():
List<ProductSubList> productSubList1 = Stream.ofNullable(mainProducts)
.<ProductSubList>mapMulti((mainProd, consumer) -> {
List<ProductSubList> prodSubLists = mainProd.getProductSubList();
if (prodSubLists != null) prodSubLists.forEach(consumer);
})
.sorted(Comparator.comparing(ProductSubList::getProductDate))
.toList();
就我個人而言,我認為上面的版本已經足夠好了,但是如果你對流中的空檢查不滿意,并且希望看到花哨的單行,那么可以重寫它:
List<ProductSubList> productSubList2 = Stream.ofNullable(mainProducts)
.<ProductSubList>mapMulti((mainProd, consumer) ->
Objects.requireNonNullElse(
mainProd.getProductSubList(), List.<ProductSubList>of()
).forEach(consumer)
)
.sorted(Comparator.comparing(ProductSubList::getProductDate))
.toList();
另見:
- Optional.ofNullable() 是否應該用于空檢查?
- 用于可選
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/530234.html
