2016-03-08 2 views
3

У меня есть List<POJO>, что я хочу, чтобы извлечь данные из и переменные Я заинтересован в являются:Java 8 лямбда добавление к списку в Hashmap, в Hashmap

  • Environment: String
  • Application: String
  • Throughput: Double

есть 7 Environment объекты и каждый Environment имеет 18 Application объекты, каждая из которых имеет несколько values.

Я пытаюсь перебрать List<POJO> и хранить эти значения в Hashmap<Environment.ToString, Hashmap<Applications.ToString, List<Double>>

Я пытаюсь использовать Java-8 в функции лямбда; мой код до сих пор:

private HashMap<String, List<BigDecimal>> appMap = new HashMap<String, List<BigDecimal>>(); 
private HashMap<String, HashMap> envMap = new HashMap<String, HashMap>(); 

for(POJO chartModel: List<POJO>) { 
    appMap.computeIfAbsent(chartModel.getName(), v -> new ArrayList<BigDecimal>()) 
      .add(BigDecimal.valueOf(chartModel.getThroughput())); 
    envMap.put(chartModel.getEnvironment(), appMap); 
} 

Во-первых, есть сокращенный способ перебрать List во внутренней Map с помощью Java8?

Во-вторых, мой код не совсем прав, поэтому в настоящее время карта добавляет все значения Throughput в свой Application ключ, поэтому я получаю 18 ключей со списком значений.

Что мне нужно сделать, это в моем envMap я должен иметь 7 Environment объектов, каждый из которых имеет свои 18 Application объектов и ценность, так что будет 126 Application объектов в целом. Может ли это быть достигнуто так, как я пытаюсь это сделать, есть ли способ Лямбды достичь этого?

+1

Ну, для начала у вас есть только один экземпляр 'appMap', и это будет вставляться в' envMap' 7 раз, один раз для каждой «Среда». –

ответ

6

Вам необходимо использовать 2 группировки по операциям: первая группа группируется в соответствии с окружающей средой, а вторая - в соответствии с именем. Наконец, вам нужно сопоставить каждое значение с величиной их пропускной способности BigDecimal.

Предполагая pojo является List<POJO>:

Map<String, Map<String, List<BigDecimal>>> result = 
    pojo.stream() 
     .collect(Collectors.groupingBy(
      POJO::getEnvironment, 
      Collectors.groupingBy(
       POJO::getName, 
       Collectors.mapping(p -> BigDecimal.valueOf(p.getThroughput()), Collectors.toList()) 
      ) 
     )); 
+0

Это прекрасно, спасибо. – Johntk

3

Вы создаете только один Map, appMap, который вы кладете в envMap для каждого ключа. Вы, очевидно, хотите создать новый Map для каждого отдельного ключа, и вы уже знаете нужный инструмент, computeIfAbsent. Но вы также должны помнить “diamond operator”. Хотя это не новая функция Java 8, ваш код явно выиграет от удаления повторений параметров типа. Собираем все вместе, операция будет выглядеть следующим образом:

HashMap<String, Map<String, List<BigDecimal>>> envMap = new HashMap<>(); 
for(POJO chartModel: list) { 
    envMap.computeIfAbsent(chartModel.getEnvironment(), env -> new HashMap<>()) 
     .computeIfAbsent(chartModel.getName(), name -> new ArrayList<>()) 
     .add(BigDecimal.valueOf(chartModel.getThroughput())); 
} 

Вы также можете выразить ту же логику, используя поток API, as shown by Tunaki, но вам не нужно.

+0

Есть ли какое-либо преимущество в использовании одного метода над другим? – Johntk

+2

В этом конкретном случае нет важных отличий. Вы можете использовать все, что захотите, но это стоит знать * оба пути. – Holger

+0

Я бы предпочел это решение, так как здесь у нас меньше вложенных вызовов. Пять закрывающих круглых скобок в строке слишком много. –

Смежные вопросы