使用身份密钥将流映射到Map的快捷方式

时间:2019-07-02 06:49:03

标签: java java-stream

考虑以下示例代码,通过将每个字符串映射到其长度并打印每个映射项来处理字符串列表

package com.dbenergie.ndm.bnb.business;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

public class Application {

    public static void main(String[] args) {
        final List<String> strings = Arrays.asList("Hello", "World", "!");

        // 1
        final Map<String, Integer> stringCharacterCountMapping = strings.stream()
                .collect(Collectors.toMap(Function.identity(), String::length));

        stringCharacterCountMapping.entrySet().stream().forEach(System.out::println);
    }
}

现在,我个人觉得比较混乱或样板式是使用Function.identity()(在1)将每个流条目作为映射的键进行显式映射,但是到目前为止,我发现的每个映射收集器都需要一个键映射器-是否有一些我忽略的收集器,或者如果我需要它,我是否必须定义自己的收集器?像这样

会很方便
Collectors.toMap(String::length);

或类似。有什么想法吗?

1 个答案:

答案 0 :(得分:3)

There is no toMap method in the Collectors class that does not take a keyMapper.我怀疑这是因为传递给您的单个参数映射到的内容可能非常模棱两可。是值还是键?

您可以轻松地自己编写这样的收集器:

class MyCollectors {
    public static <K, U> Collector<K, ?, Map<K,U>> toMapWithValueWrapper(Function<? super K, ? extends U> valueMapper) {
        return Collectors.toMap(Function.identity(), valueMapper);
    }
}

请注意,签名与Collectors.toMap有点不同。只有2个通用参数。原始的Collectors.toMap具有3-T(我们正在收集的类型),K(键的类型)和U(值的类型)。由于您对密钥使用身份功能,因此密钥将始终与我们要收集的类型具有相同的类型,因此T == K。因此,我们可以消除T

编辑:

如Holger在评论中所建议,我们不必强制T == K,因为T可以是K的子类,并且您仍然可以使用恒等函数从{ {1}}至T。因此,您可以使用以下方法:

K

如果要允许收集到键类型是要收集的类型的超类的地图。