簡體   English   中英

使用Guava將兩個列表壓縮到Java 8中的不可變多圖中?

[英]Zip two lists into an immutable multimap in Java 8 with Guava?

for循環看起來像

ImmutableListMultiMap.<Key, Value>Builder builder 
    = ImmutableListMultiMap.<Key, Value>newBuilder();
for (int i = 0; i < Math.min(keys.length(), values.length()); i++) {
  builder.put(keys.at(i), values.at(i));
}

Guava / Java 8中可能的第一步是

Streams.zip(keys, values, zippingFunction)

我認為zippingFunction需要返回一個map條目,但是沒有可公開構造的列表條目。 因此,我可以編寫的“最”功能方式是使用壓縮函數返回一個Pair,我不確定它是否存在於Guava中,或者返回一個兩元素列表,這是一個可變類型,在那里沒有正確地說明正是2個元素。

如果我可以創建一個映射條目,那將是理想的:

Streams.zip(keys, values, zippingFunction)
.collect(toImmutableListMultimap(e -> e.getKey(), e.getValue())

這似乎是最好的方式,除非它不可能,並且拉入條目並從條目解壓縮仍然看起來很迂回。 有沒有辦法使這成為可能或一種可以改進的方式?

如果您的列表是隨機訪問,您可以不用壓縮:

Map<Key, Value> map = IntStream.range(0, Math.min(keys.size(), values.size()))
    .boxed()
    .collect(toImmutableListMultimap(i -> keys[i], i -> values[i]));

我認為你的程序代碼已經是最優化的解決方案(無論是內存還是速度,假設隨機訪問列表)。 通過小的修正,以便您的代碼編譯,它將是:

ImmutableListMultimap.Builder<Key, Value> builder = ImmutableListMultimap.builder();
for (int i = 0; i < Math.min(keys.size(), values.size()); i++) {
  builder.put(keys.get(i), values.get(i));
}
return builder.build();

如果你真的想要使用流來實現“功能”,那么壓縮兩個流是可行的方法,但在收集到multimap之前你仍然需要創建中間的“對”對象。 你聲稱“沒有可公開構建的列表條目”,但事實並非如此,你可以在這里使用JDK的SimpleImmutableEntry和Guava的Maps.immutableEntry (它們比更通用的Pair更合適,實際上它們不能在JDK或Guava中都可以找到。

使用Streams#zip需要傳遞流,因此最終代碼如下所示:

Streams.zip(keys.stream(), values.stream(), SimpleImmutableEntry::new)
    .collect(toImmutableListMultimap(Map.Entry::getKey, Map.Entry::getValue));

如果你願意使用其他允許更多與流相關的操作的“功能”Java庫,你可以使用jOOL及其接受可迭代參數的Seq.zip

    Seq.zip(keys, values, SimpleImmutableEntry::new)
        .collect(toImmutableListMultimap(Map.Entry::getKey, Map.Entry::getValue));

另一個庫是StreamEx ,它公開了EntryStream - 鍵值EntryStream的抽象。

所以,你幾乎做對了! 下面是您更新的代碼(假設您的列表是Integer類型):

Streams.zip(keys.stream(), values.stream(), AbstractMap.SimpleImmutableEntry::new)
                .collect(toImmutableListMultimap(Map.Entry<Integer, Integer>::getKey,
                        Map.Entry<Integer, Integer>::getValue)
                );

但我總是喜歡在本地做事,因為它給你更多的力量。 使用collect查看下面的代碼:

Streams.zip(keys.stream(), values.stream(), (k, v) -> new AbstractMap.SimpleImmutableEntry(k, v))
                        .collect(ImmutableListMultimap::builder,
                                ImmutableListMultimap.Builder::put,
                                (builder2, builder3) -> builder2.putAll(builder3.build())

                        ).build();

注意: - builder2.putAll(builder3.build()) BiConsumer僅在您使用並行流時才有效。 這就是collect的行為(我最喜歡的一個來自溪流)。

暫無
暫無

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

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