簡體   English   中英

使用流,我如何 map HashMap 中的值?

[英]Using streams, how can I map the values in a HashMap?

給定一個Map<String, Person> ,其中 Person 有一個String getName() (等)方法,我怎樣才能將Map<String, Person>變成一個Map<String, String> ,其中String是從調用Person::getName()獲得的Person::getName()

我會使用 Pre-Java 8

Map<String, String> byNameMap = new HashMap<>();

for (Map.Entry<String, Person> person : people.entrySet()) {
    byNameMap.put(person.getKey(), person.getValue().getName());
}

但我想使用流和 lambda 來做到這一點。

我看不到如何以功能樣式執行此操作: Map/HashMap 不實現Stream

people.entrySet()返回一個Set<Entry<String, Person>>我可以在 ZF7B44CFFAFD5C52223D5498196C8A2E7BZ 上,但是如何將新的Entry<String, String>添加到目標 map?

使用 Java 8,您可以執行以下操作:

Map<String, String> byNameMap = new HashMap<>();
people.forEach((k, v) -> byNameMap.put(k, v.getName());

盡管您最好使用 Guava 的Maps.transformValues ,它包裝原始Map並在您執行get時進行轉換,這意味着您僅在實際消耗該值時才支付轉換成本。

使用番石榴看起來像這樣:

Map<String, String> byNameMap = Maps.transformValues(people, Person::getName);

編輯:

按照@Eelco 的評論(為了完整性),使用Collectors.toMap更好地轉換為地圖,如下所示:

Map<String, String> byNameMap = people.entrySet()
  .stream()
  .collect(Collectors.toMap(Map.Entry::getKey, (entry) -> entry.getValue().getName());

一種方法是使用toMap收集器:

import static java.util.stream.Collectors.toMap;

Map<String, String> byNameMap = people.entrySet().stream()
                                     .collect(toMap(Entry::getKey, 
                                                    e -> e.getValue().getName()));

使用一些我手頭的庫中沒有找到的通用代碼

public static <K, V1, V2> Map<K, V2> remap(Map<K, V1> map,
        Function<? super V1, ? extends V2> function) {

    return map.entrySet()
            .stream() // or parallel
            .collect(Collectors.toMap(
                    Map.Entry::getKey, 
                    e -> function.apply(e.getValue())
                ));
}

這與 Guavas Maps.transformValues基本相同,減去其他人提到的缺點。

Map<String, Person> persons = ...;
Map<String, String> byNameMap = remap(persons, Person::getName);

如果您需要重新映射函數中的鍵和值,第二個版本使這成為可能

public static <K, V1, V2> Map<K, V2> remap(Map<K, V1> map,
        BiFunction<? super K, ? super V1, ? extends V2> function) {

    return map.entrySet()
            .stream() // or parallel
            .collect(Collectors.toMap(
                    Map.Entry::getKey,
                    e -> function.apply(e.getKey(), e.getValue())
                ));
}

它可以用於例如

Map<String, String> byNameMap = remap(persons, (key, val) -> key + ":" + val.getName());

由於 Java 9 你也可以這樣做:

Entry<String, String> entry = Map.entry("a", "b");

在您的 Map 中,它將像這樣使用:

Map<String, String> byNameMap = people.entrySet()
  .stream()
  .map(entry -> Map.entry(entry.getKey(), entry.getValue().getName()))
  .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue);

暫無
暫無

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

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