[英]Streams and Collectors.toMap() - two approaches?
在以下兩個代碼片段中 - 哪個更可取。
接近-1
public Map<String, List<MyObj>> approach1(
Iterable<? extends String> keys) {
return StreamSupport.stream(keys.spliterator(), false)
.map(dt -> new AbstractMap.SimpleEntry<>(dt, load(dt)))
.collect(toMap(Map.Entry::getKey, Map.Entry::getValue, (a, b) -> a, HashMap::new));
}
方法 - 2
public Map<String, List<MyObj>> approach2(
Iterable<? extends String> keys) {
return StreamSupport.stream(keys.spliterator(), false)
.collect(toMap(dt -> dt, k -> load(dt), (a, b) -> a, HashMap::new));
}
在approach1中,顯式創建一個映射條目,然后使用getKey
和getValue
將其映射到toMap
中,這是否有任何優勢或更直接的approach2同樣好。
后續問題:如果可迭代keys
中的條目或未排序,合並函數(a, b) -> a
是否對keys
中的相同條目以不同的順序給出相同的結果。
根據您提供的代碼,兩種方法都會產生相同的結果。
后續問題:如果 Iterable keys
中的條目未排序,則合並函數 ( a, b) -> a
可能會根據處理條目的順序給出不同的結果。 這是因為 merge 函數用於解決當兩個元素映射到同一個key
時的沖突,並且順序可能會影響哪個元素保留在map
中,如果對keys
進行排序,則 merge 函數將給出相同的結果
如果 Iterable keys 中的條目或未排序,合並函數
(a, b) -> a
是否為 keys 中的相同條目但以不同的順序給出相同的結果。
它與排序無關。
mergeFunction的行為是否確定取決於源是否有序(有序只是意味着可預測的迭代順序,元素可能無論如何都不會排序)。 如果是這樣,從給定的Iterable
生成的Spliterator
將具有特征Spliterator.ORDERED
。
這將決定生成的 Stream 是有序的還是無序的。
例如, HashSet
沒有特定的迭代順序,與ArrayList
、 ArrayDeque
等集合相反,保證迭代的確定順序。
注意: Stream API 提供的某些方法可以更改管道的順序。 操作unordered()
將放寬排序約束(如果流已排序),而sorted()
將強制排序。
根據toMap()
的文檔:
mergeFunction - 合並函數,用於解決與相同鍵關聯的值之間的沖突,如提供給
Map.merge(Object, Object, BiFunction)
因此,在有序流中, mergeFunction (a, b) -> a
將保留從流中較早出現的流元素生成的值。 但是,如果流是無序的,則 Collector 可以按任何順序使用元素,並且無法預測哪個值將最終出現在生成的 Map 中。
關於兩個流之間的區別的問題,第一個片段中的 map() 操作是多余的,因為它只會創建不必要的中間Map.Entry
實例。 看起來您添加此操作只是為了能夠在收集器中應用方法引用,這是不合理的。 對象的創建不是免費的,對於代碼的讀者來說,為什么需要這種中間轉換可能並不明顯。
另外,請注意,在兩個代碼段中的 Collector 中指定mapFactory HashMap::new
是沒有意義的,因為默認情況下會以HashMap
的形式實現Map
接口的通用目的,或者將來可能會推薦替代的東西. 因此,如果您願意將HashMap
作為流執行的結果,則可以省略mapFactory 。 四參數版本的toMap
期望mapFactory的用例是當您需要TreeMap
、 EnumMap
或任何其他特殊用途的實現時。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.