Как извлечь список <D>из HashMap <E, R>, используя поток - PullRequest
0 голосов
/ 07 января 2019

Я хочу знать, как извлечь List<D> из HashMap<E,R> с учетом этих ограничений:

  • E - это пользовательский класс;
  • R - это пользовательский класс, содержащий Set<D> пользовательских объектов;

Что я пробовал: я пытался решить проблему в этом вопросе .

В этом предыдущем случае у меня был простой Map<E,List<R>>, но в этом случае я должен получить доступ к классу R с целевым значением Set<D>.

В следующей части кода я хочу получить элементы Set<D>, названия стран которых соответствуют заданному параметру.

Я пытался использовать то же решение:

Map<E,R> map = new HashMap<E,R>();
public List<D> method(String countryname) { 
   return map.values().stream().filter((x)->{
        return x.getSet().stream().anyMatch((t) -> {
            return t.getCountry().equals(countryname); 
        });
    })
    .map(R::getSet)
    .flatMap(List::stream)
    .collect(Collectors.toList()); //does not compile
}

// the R class
class R {
    private Set<D> set = new TreeSet<D>();
    //getters & setters & other attributes
}

Ответы [ 3 ]

0 голосов
/ 07 января 2019

получить элементы набора, названия стран которых равны заданному параметр.

Вы, похоже, ищете

// input as parameter to the method for simplicity
public List<D> method(Map<E, R> map, String countryName) {
    return map.values() // Collection<R>
              .stream() // Stream<R>
              .flatMap(a -> a.getSet().stream()) // Stream<D>
              .filter(t -> t.getCountry().equals(countryName)) // filtered
              .collect(Collectors.toList()); // collected to list
}
0 голосов
/ 07 января 2019

Чтобы улучшить читабельность вашего кода, я бы предложил избегать ненужных фигурных скобок в лямбдах и даже в самих лямбдах. Используйте ссылки на метод , где это возможно.

return map.values()
          .stream()
          .map(R::getSet)
          .filter(set -> set.stream()
                            .map(R::getCountry)
                            .anyMatch(countryname::equals))
          .flatMap(Set::stream)
          .collect(toList());

Последние операции flatMap и collect можно сократить до одной строки:

.collect(ArrayList::new, List::addAll, List::addAll); 

Или, если вы используете Java 9: ​​

.collect(flatMapping(Set::stream, toList()));

Однако это просто вопрос вкуса.

0 голосов
/ 07 января 2019

Я считаю, что шаг flatMap неправильный, поскольку ваш шаг map преобразует ваш Stream<R> в Stream<Set<D>>, поэтому flatMap(List::stream) должно быть flatMap(Set::stream):

return map.values()
          .stream()
          .filter(x -> x.getSet().stream().anyMatch(t -> t.getCountry().equals(countryname)))
          .map(R::getSet)
          .flatMap(Set::stream)
          .collect(Collectors.toList());

Кроме того, как вы можете заметить выше, код может быть гораздо более читабельным, если вы не будете использовать фигурные скобки, когда вам это не нужно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...