Java8转换映射中的[List<;Object>;,String]<;对象,字符串>;

Java8转换映射中的[List<;Object>;,String]<;对象,字符串>;,java,java-8,java-stream,Java,Java 8,Java Stream,我有一个列表。每台计算机都有一个CPU列表和一个主机名。 那么,假设我有: List<Computer> computers 我想做的是,使用Streams获得一个映射,其中包含CPU作为键和主机名作为字符串。相同计算机中的相同CPU将复制主机名 我该怎么做 Java8之前的代码如下所示: public Map<CPU, String> getMapping(List<Computer> computers) { Map<CPU, String

我有一个
列表
。每台计算机都有一个CPU列表和一个主机名。 那么,假设我有:

List<Computer> computers
我想做的是,使用Streams获得一个映射,其中包含CPU作为键和主机名作为字符串。相同计算机中的相同CPU将复制主机名

我该怎么做

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;
}
publicmap-getMapping(列出计算机){
映射结果=新的HashMap();
用于(计算机:计算机){
用于(CPU:computer.getCPUs()){
put(cpu,computer.getHostname());
}
}
返回结果;
}

如果您的
CPU
类有一个对其
计算机
实例的反向引用,那么您可以轻松地完成此操作。首先在所有计算机上进行流,并使用
getCPU
进行平面映射,这将为您提供所有CPU的
流。然后,您可以使用
收集器.toMap
收集到
映射中,使用
函数.identity
作为键,lambda首先提取
计算机
,然后从CPU提取主机名作为值。 代码:


您可以通过实现自己的
采集器
将相同的值分配给同一台计算机的所有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; }
    )
);
Map cpu=computers.stream().collect(
收藏(
HashMap::新建,
//将同一台计算机的每个cpu使用计算机的主机名作为值
(地图,计算机)->computer.getCPUs().stream().forEach(
cpu->map.put(cpu,computer.getHostName())
),
(map1,map2)->{map1.putAll(map2);返回map1;}
)
);

这基本上等同于您当前使用的
流API
,唯一的区别是您可以通过简单地使用并行流而不是普通流来并行化它,但在这种特殊情况下,由于任务非常小,就性能而言,它可能没有多大帮助,因此在这种情况下使用
流API
可能被认为有点滥用

您可以使用中间的
条目将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));
Map Map=computers.stream()
.flatMap(c->c.getCPU().stream().map(cpu->new AbstractMap.SimpleEntry(cpu,c.getHostName()))
.collect(Collectors.toMap(Map.Entry::getKey,Map.Entry::getValue));

计算机与计算机之间的关系是什么。如果您希望您的问题继续存在,请添加完成任务的Java 8之前的代码。谢谢,我添加了Java 8之前的代码。我认为没有比您现有的更好的streams&lambdas解决方案了。如果相同的CPU链接到两个以上的主机名,会发生什么?是什么导致您假设存在
CPU.getComputer()
method?正如我在第一句中所解释的,我假设这是因为这是一个合理的假设,并且需要使用流API来清晰地解决这一问题。如果这样的方法不存在,流管道将变得更加低效,因为我认为如果没有中间收集步骤,您就无法做到这一点。
computers.stream()
    .flatMap(computer -> computer.getCPUs().stream())
    .collect(Collectors.toMap(Function.identity(), cpu -> cpu.getComputer().getHostname()));
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; }
    )
);
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));