2017-02-20 3 views
2

У меня есть Artist класс следующим образом:Использование flatMap() в Java8

class Artist { 
    private final String name; 
    private final String origin; 
    private Stream<Artist> members; 

    public Artist(String name, String origin) { 
     this.name = name; 
     this.origin = origin; 
     this.members = null; 
    } 

    public Artist(String name, String origin,Stream<Artist> members) { 
      this.name = name; 
      this.origin = origin; 
      this.members = members; 
    } 

    public String getName() { 
      return name; 
    } 

    public String getOrigin() { 
     return origin; 
    } 

    public Stream<Artist> getMembers() { 
     return members; 
    } 

    @Override 
    public String toString() { 
     return name; 
    } 
} 

Теперь мы создаем список художников, где имя художника является группа или юридическим лицом. Для одного объекта "members" атрибут остается null.Now списка выглядит следующим образом:

List<Artist> artists = Arrays.asList(
       new Artist("Fossils","Kolkata", Stream.of(new Artist("Rupam Islam","Kolkata"), new Artist("Deep","Kolkata"),new Artist("Allan","Kolkata"), new Artist("Chandramouli","Kolkata"),new Artist("Tanmoy","Kolkata"))), 
       new Artist("Linkin Park","California",Stream.of(new Artist("Chester Bennington","California"),new Artist("Dave Farrell","California"), new Artist("Mike Shinoda","California"),new Artist("Rob Bourdon","California"),new Artist("Brad Delson","California"))), 
       new Artist("Cactus","Kolkata",Stream.of(new Artist("Sidhartha Sankar","Kolkata"),new Artist("Dibyendu Mukherjee","Kolkata"), new Artist("Ritaprabha","Kolkata"),new Artist("Sudipto","Kolkata"),new Artist("Mainak","Kolkata"))), 
       new Artist("Backstreet Boys","Florida",Stream.of(new Artist("A. J. McLean","Florida"),new Artist("Howie D.","Florida"),new Artist("Nick Carter","Florida"), new Artist("Kevin Richardson","Florida"), new Artist("Brian Littrell","Florida"))), 
       new Artist("Prohori","Kolkata",Stream.of(new Artist("Pritam","Kolkata")))); 

Мы хотим иметь не из одного лица от «Калькутты». Использование внешней итерации мы можем иметь следующее решение:

int totalMembers = 0; 
for (Artist artist : artists) { 
    if(artist.getOrigin().equals("Kolkata") { 
     Stream<Artist> members = artist.getMembers(); 
     totalMembers += members.count(); 
    } 
} 

Что будет решение для внутренней итерации с использованием stream() и flatMap() с помощью лямбда-выражения?

Я думал о решении, но может быть, это неверно.

int totalMember = artists.stream() 
         .filter(d -> d.getOrigin().equals("Kolkata")) 
         .flatMap(e -> e.getMembers()) 
         .map(f -> 1).reduce(0, (a, b) -> a + b); 
+0

Большая вещь, почему это неправильно это у вас есть поле типа '' потока . Потоки могут использоваться только один раз, если вы вызываете свой код два раза подряд, вы получите исключение. Помимо этого, ваше решение можно улучшить, используя соответствующие встроенные функции (например, счетный коллектор), но в целом все в порядке. –

+1

@SoumyaKantiNaskar немного неясно .. вы хотите, чтобы общее количество художников из определенного региона, где 'members' равно null? Взяв ваш пример: «Новый художник (« Ископаемые »,« Калькутта », Stream.of (новый художник (« Рупам Ислам »,« Калькутта »), новый художник (« Глубокий »,« Калькутта »), новый художник (" Аллан »,« Калькутта »), новый художник (« Чандрамули »,« Калькутта »), новый художник (« Танмой »,« Калькутта »))). Должно ли это производить ноль или 5? Вы хотите также считать внутренних художников? – Eugene

+1

@SoumyaKantiNaskar ваш пример «внешней итерации» (помимо возможности бросать исключение NullPointerException, поскольку члены могут быть нулевыми), также не соответствует вашим собственным требованиям: «Мы не хотим иметь единого объекта», где «Для одного объекта», members "атрибут остается null. – Eugene

ответ

3

Ваш внешний контур подсчитывает количество членов, которые имеют диапазон от Kolkata. если вы действительно этого хотите:

long result = artists.stream().filter(a -> a.getOrigin().equals("Kolkata")) 
      .filter(a -> a.getMembers() != null) 
      .flatMap(a -> a.getMembers()) 
      .count(); 
+0

Ваш первый решение дает результат 0 –

+1

@SoumyaKantiNaskar для вашего примера, что такое выход желания 11? Если это так, то второй пример подсчитывает эти внутренние члены – Eugene

+0

Это решение дает мне ошибку: java.lang.IllegalStateException: поток уже оперирован или закрыто –

0

суммы графы потоков в качестве LongStream:

long totalMember = artists.stream() 
          .filter(d -> d.getOrigin().equals("Kolkata")) 
          .map(Artist::getMembers) 
          .filter(m -> m != null) 
          .mapToInt(Stream::count) 
          .sum(); 
+0

'Для атрибутов« для отдельных объектов »остается null. Похоже, что должен быть еще один фильтр. – Eugene

+0

@eugene OK ... добавлен нет нулевого фильтра – Bohemian

+0

Я не уверен, что OP действительно хочет посчитать. Он говорит: «Мы хотим, чтобы у кого-то из« Калькутты »не было единого объекта, но его внешний цикл подсчитывает фактические члены (так, как вы это сделали). – Eugene

1

Ваше решение даст ожидаемый выход 11 т.е.. Вы также можете использовать:

int totalMembers = (int) artists.stream() 
           .flatMap(d->d.getMembers()) 
           .filter(d->d.getOrigin().equals("Kolkata")) 
           .count(); 

Разница между двумя решениями, у меня есть flattened перечень перед filtering его и использовал long count(); вместо reduce(). Что, в конце концов, делает это, он проверяет origin от Stream<Artist> members, а не origin от artists. Надеюсь, эта помощь. Буду признателен, если кто-нибудь сможет обсудить оптимизированное решение.

+0

. Ваше решение дает ошибку Исключение из потока «main» java.lang.IllegalStateException: поток уже оперирует или закрыто –

+0

Не знаю, почему это дает вам IllegalStateException, потому что это работает для меня отлично. Можете ли вы скопировать код вставить, а затем попробовать. –

+0

Мой плохой .. Он работает нормально. Но сначала нужно использовать фильтр(). Это уменьшит некоторые накладные расходы, когда мы отфильтровываем «полосы». –

0

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

long totalMember = artists.stream().filter(a -> a.getOrigin().equals("Kolkata")) 
          .flatMap(a -> a.getMembers()) 
          .filter(a -> a.getOrigin().equals("Kolkata")) 
          .count(); 
Смежные вопросы