2017-01-13 2 views
3

У меня есть List<Computer>. Каждый компьютер имеет список CPU и имя хоста. Итак, предположим, что у меня есть:Java8 transform a [Список <Object>, String] на карте <Объект, строка>

List<Computer> computers 

Я могу назвать

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

и я могу назвать

String hostname = computer.getHostName(); 

То, что я хочу сделать, используя потоки, получить карту, которая содержит как ключ CPU и как String имя хоста. Тот же процессор внутри тех же компьютеров будет реплицировать имя хоста.

Как я могу это сделать?

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

Какова связь между '' computer' и computers'. Если вы хотите, чтобы ваш вопрос выдержал, добавьте код pre-Java 8, который выполнит вашу задачу. –

+0

спасибо, я добавил код pre Java8 –

+1

Я думаю, что нет потоков и решений lambdas, которые лучше, чем тот, который у вас уже есть –

ответ

1

Если CPU класс имеет обратную ссылку на это Computer экземпляр, то вы можете сделать это легко. Первый поток по всем компьютерам и плоская карта с getCPUs, это даст вам Stream<CPU> всех процессоров. Затем вы можете использовать Collectors.toMap для сбора в Map<CPU, String>, используя Function.identity для ключа и извлечение лямбда сначала Computer, а затем имя хоста из ЦП для значения. В коде:

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

Что приводит вас к предположению, что существует метод 'cpu.getComputer()'? – Holger

+0

Как я объяснил в первом предложении, я принял это, потому что это разумное предположение и необходимо для этого разрешить чисто с помощью Stream API. Если такой метод не существует, потоковый конвейер станет более неэффективным, потому что я не думаю, что вы могли бы сделать это без промежуточного шага сбора. – diesieben07

1

Вы можете сделать это путем реализации собственного Collector, чтобы присвоить такое же значение для всех процессоров на одном компьютере:

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 i Этот случай можно считать немного оскорбительным.

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)); 
Смежные вопросы