Java8在Map <object,string =“”>中转换[List <object>,String]

时间:2017-01-13 17:10:26

标签: java java-8 java-stream

我有List<Computer>。每台计算机都有一个CPU列表和一个主机名。 所以,假设我有:

List<Computer> computers

我可以打电话

List<CPU> CPUs = computer.getCPUs();

我可以致电

String hostname = computer.getHostName();

我想要做的是,使用Streams,获取一个包含CPU密钥的Map和一个包含主机名的String。同一台计算机内的相同CPU将复制主机名。

我该怎么做?

Pre Java8代码就是这样:

public Map<CPU, String> getMapping(List<Computer> computers) {
    Map<CPU, String> result = new HashMap<>();
    for (Computer computer : computers) {
        for (CPU cpu : computer.getCPUs()) {
            result.put(cpu, computer.getHostname());
        }
    }

    return result;
}

3 个答案:

答案 0 :(得分:1)

如果您的CPU班级对其Computer实例有反向引用,那么您可以轻松完成此操作。首先在所有计算机上流式传输,使用getCPUs进行平面映射,这将为您提供所有CPU的Stream<CPU>。然后,您可以使用Collectors.toMap收集Map<CPU, String>使用Function.identity作为密钥,并使用lambda首先提取Computer,然后使用CPU中的主机名获取值。 在代码中:

computers.stream()
    .flatMap(computer -> computer.getCPUs().stream())
    .collect(Collectors.toMap(Function.identity(), cpu -> cpu.getComputer().getHostname()));

答案 1 :(得分:1)

您可以通过实现自己的Collector来实现,以便为同一台计算机的所有CPU分配相同的值:

Map<CPU, String> cpus = computers.stream().collect(
    Collector.of(
        HashMap::new,
        // Put each cpu of the same computer using the computer's hostname as value
        (map, computer) -> computer.getCPUs().stream().forEach(
            cpu -> map.put(cpu, computer.getHostName())
        ),
        (map1, map2) -> { map1.putAll(map2); return map1; }
    )
);

这基本上相当于你目前使用Stream API所做的事情,唯一的区别是你可以通过简单地使用并行流而不是普通流来并行化它,但在这种特殊情况下,任务很小,在表演方面可能没有多大帮助,因此在这种情况下使用Stream API可能会被视为有点滥用。

答案 2 :(得分:1)

您可以使用中间Entry来保存CPU和主机名:

Map<CPU, String> map = computers.stream()
        .flatMap(c -> c.getCPUs().stream().map(cpu -> new AbstractMap.SimpleEntry<>(cpu, c.getHostName())))
        .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));