簡體   English   中英

用流映射的Java 8列表

[英]Java 8 list to map with stream

我有一個List<Item>集合。 我需要將其轉換為Map<Integer, Item>映射的鍵必須是集合中項的索引。 我無法弄清楚如何使用流來做到這一點。 就像是:

items.stream().collect(Collectors.toMap(...));

有幫助嗎?

由於這個問題被確定為可能重復,我需要補充一點,我的具體問題是 - 如何獲取列表中項目的位置並將其作為鍵值

您可以使用IntStream創建索引Stream ,然后將它們轉換為Map

Map<Integer,Item> map = 
    IntStream.range(0,items.size())
             .boxed()
             .collect(Collectors.toMap (i -> i, i -> items.get(i)));

另一個完整性的解決方案是使用自定義收集器:

public static <T> Collector<T, ?, Map<Integer, T>> toMap() {
    return Collector.of(HashMap::new, (map, t) -> map.put(map.size(), t), 
            (m1, m2) -> {
                int s = m1.size();
                m2.forEach((k, v) -> m1.put(k+s, v));
                return m1;
            });
}

用法:

Map<Integer, Item> map = items.stream().collect(toMap());

此解決方案是並行友好的,不依賴於源(您可以使用沒有隨機訪問的列表或Files.lines()或其他)。

不要覺得你必須在流中做任何事情 我會這樣做:

AtomicInteger index = new AtomicInteger();
items.stream().collect(Collectors.toMap(i -> index.getAndIncrement(), i -> i));

只要您不對流進行並行化,這將起作用,並且它避免了潛在的昂貴和/或有問題(在重復的情況下) get()indexOf()操作。

(你不能使用常規的int變量來代替AtomicInteger因為從lambda表達式外部使用的變量必須是有效的。注意,當無爭議時(如本例所示), AtomicInteger非常快,不會造成性能問題。但如果它讓你擔心,你可以使用非線程安全的計數器。)

這是更新的答案,沒有評論中提到的問題。

Map<Integer,Item> outputMap = IntStream.range(0,inputList.size()).boxed().collect(Collectors.toMap(Function.identity(), i->inputList.get(i)));

使用第三方庫(例如protonpack ,但還有其他庫),您可以使用其索引和voilazip值:

StreamUtils.zipWithIndex(items.stream())
    .collect(Collectors.toMap(Indexed::getIndex, Indexed::getValue));

雖然getIndex返回一個long ,所以你可能需要使用類似的東西來強制轉換:

i -> Integer.valueOf((int) i.getIndex())

Eran的答案通常是隨機訪問列表的最佳方法。

如果您的List不是隨機訪問,或者您有Stream而不是List ,則可以使用forEachOrdered

Stream<Item> stream = ... ;
Map<Integer, Item> map = new HashMap<>();
AtomicInteger index = new AtomicInteger();
stream.forEachOrdered(item -> map.put(index.getAndIncrement(), item));

如果流是並行的,這是安全的,即使目標地圖是線程不安全的並且作為副作用進行操作。 forEachOrdered保證按順序一次一個地處理項目。 因此,並行運行不會產生任何加速。 (如果在forEachOrdered之前管道中有昂貴的操作,可能會有一些加速。)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM