Reputation: 378
I have a List<Computer>
. Every Computer has a list of CPU and a hostname.
So,suppose I have:
List<Computer> computers
I can call
List<CPU> CPUs = computer.getCPUs();
and I can call
String hostname = computer.getHostName();
What I want to do is, using Streams, obtain a Map that contains as key the CPU and as String the hostname. Same CPU inside the same Computers will replicate the hostname.
How can I do that?
Pre Java8 code would be this:
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;
}
Upvotes: 3
Views: 159
Reputation: 50716
You can do it using an intermediate Entry
to hold the CPU and hostname together:
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));
Upvotes: 1
Reputation: 44965
You could do it by implementing your own Collector
in order to assign the same value to all the CPUs of the same computer:
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; }
)
);
This is basically the equivalent of what you currently do using the Stream API
, the only difference is the fact that you could parallelize it by simply using a parallel stream instead of a normal stream, but in this particular case as the tasks are quite small, it would probably not help much in term of performances such that using the Stream API
in this case could be considered as a little bit abusive.
Upvotes: 1
Reputation: 1547
If your CPU
class has a back-reference to it's Computer
instance, then you can do this easily. First stream over all the computers, and flat-map with getCPUs
, this will give you a Stream<CPU>
of all CPUs. Then you can use Collectors.toMap
to collect into a Map<CPU, String>
using Function.identity
for the key and a lambda extracting first the Computer
and then the hostname from the CPU for the value.
In code:
computers.stream()
.flatMap(computer -> computer.getCPUs().stream())
.collect(Collectors.toMap(Function.identity(), cpu -> cpu.getComputer().getHostname()));
Upvotes: 1