2016-09-14 3 views
1

У меня есть следующий контейнер в Java, что мне нужно работать наJava 8 Streams API для фильтрации Карта записей

Map<String, List<Entry<Parameter, String>>> 

Где Parameter является перечисляемого типа определяется следующим образом:

public enum Parameter { 
    Param1, 
    Param2, 
    Param3 
} 

приведенный ниже код показывает, как я инициализирую структуру карты - эффективно помещая 2 строки в контейнер.

Map<String, List<Entry<Parameter, String>>> map2 = new HashMap<String, List<Entry<Parameter, String>>>() {{ 
     put("SERVICE1", new ArrayList<Entry<Parameter, String>>(){{ 
      add (new AbstractMap.SimpleEntry<>(Parameter.Param1,"val1")); 
      add (new AbstractMap.SimpleEntry<>(Parameter.Param2,"val2")); 
      add (new AbstractMap.SimpleEntry<>(Parameter.Param3,"val3")); 
     }}); 
     put("SERVICE2", new ArrayList<Entry<Parameter, String>>(){{ 
      add (new AbstractMap.SimpleEntry<>(Parameter.Param1,"val4")); 
      add (new AbstractMap.SimpleEntry<>(Parameter.Param2,"val5")); 
      add (new AbstractMap.SimpleEntry<>(Parameter.Param3,"val6")); 
     }}); 
    }}; 

Мне нужно использовать Java 8 потоков API, чтобы найти val1 и val2 значения от «SERVICE1», но я не знаю, правильно ява потоки фильтра и отображение синтаксиса.

Ближайшее, что я могу придумать, состоит в следующем, но это только фильтры на верхнем уровне и возвращает список списков, а не список Parameter.Param1,"val1" & Parameter.Param2,"val3", что я ищу из SERVICE1 строки.

List<List<Entry<Parameter, String>>> listOfLists = myMap.entrySet().stream() 
      .filter(next -> next.getKey().equals("SERVICE1")) 
      .map(Map.Entry::getValue) 
      .collect(Collectors.toList()); 
    listOfLists.size(); 

ответ

3

Если вам нужно только «val1» и значение «val2», вы можете сначала использовать getOrDefault, чтобы получить соответствующий список, а затем фильтровать по клавишам Записи, чтобы получить записи с Param1 или Param2 как ключ, и, наконец, снова примените карту, чтобы получить значения этих записей.

List<String> list = 
    myMap.getOrDefault("SERVICE1", Collections.emptyList()) 
     .stream() 
     .filter(e -> e.getKey() == Parameter.Param1 || e.getKey() == Parameter.Param2) 
     .map(Map.Entry::getValue) 
     .collect(Collectors.toList()); 

Кроме того, вы можете быть заинтересованы, чтобы посмотреть на Efficiency of Java "Double Brace Initialization"?

+0

Хороший, но есть какой-то способ достижения того же результата, оставляя в текущем фильтре верхнего уровня (далее -.> Next.getKey() равна («SERVICE1»)), который у меня сейчас есть, или который всегда будет возвращать список списков. Я думаю, что код, который я написал, почти есть, но есть какой-то способ просто вернуть первый из этих списков. – johnco3

+2

@ johnco3 Ну да, используйте 'flatMap' вместо' map' и фильтруйте записи таким же образом '.filter (next -> next.getKey(). Equals (" SERVICE1 ")). FlatMap (e -> e .getValue(). stream()) .filter (e -> e.getKey() == Parameter.Param1 || e.getKey() == Parameter.Param2) .map (Map.Entry :: getValue) .collect (...) '. Но с этим подходом нет никакой пользы, так как у вас будет только один список, потому что вас интересует сопоставление с определенным ключом. –

+2

... если фильтрация на ключах не может содержать несколько списков, например 'next -> next.getKey(). StartWith (" SERVICE ")' например. –

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