Новые коллекционеры потоков в Java 9

Новые коллекционеры потока в Java 9

1. обзор

Collectors были добавлены в Java 8, что помогло накапливать входные элементы в изменяемые контейнеры, такие какMap,List иSet.

В этой статье мы собираемся изучитьtwo new collectors added in Java 9: Collectors.filtering andCollectors.flatMapping, используемое в сочетании сCollectors.groupingBy, обеспечивающее интеллектуальные коллекции элементов.

2. Filtering Collectorс

Collectors.filtering аналогиченStream filter(); он используется для входных элементовfiltering, но используется для разных сценариев. Stream’sfilter используется в цепочке потоков, тогда какfiltering - этоCollector, который был разработан для использования вместе сgroupingBy.

СStream’sfilter значения сначала фильтруются, а затем группируются. Таким образом, значения, которые отфильтровываются, исчезают, и их нет. Если нам нужна трассировка, тогда нам нужно сначала сгруппировать, а затем применить фильтрацию, которую на самом деле делаетCollectors.filtering.

Collectors.filtering принимает функцию для фильтрации входных элементов и коллектор для сбора отфильтрованных элементов:

@Test
public void givenList_whenSatifyPredicate_thenMapValueWithOccurences() {
    List numbers = List.of(1, 2, 3, 5, 5);

    Map result = numbers.stream()
      .filter(val -> val > 3)
      .collect(Collectors.groupingBy(i -> i, Collectors.counting()));

    assertEquals(1, result.size());

    result = numbers.stream()
      .collect(Collectors.groupingBy(i -> i,
        Collectors.filtering(val -> val > 3, Collectors.counting())));

    assertEquals(4, result.size());
}

3. FlatMapping Collectorс

Collectors.flatMapping аналогиченCollectors.mapping, но имеет более детальную цель. Оба сборщика принимают функцию и сборщик, в котором собираются элементы, но функцияflatMapping принимаетStream элементов, которые затем накапливаются сборщиком.

Давайте посмотрим на следующий класс модели:

class Blog {
    private String authorName;
    private List comments;

    // constructor and getters
}

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

@Test
public void givenListOfBlogs_whenAuthorName_thenMapAuthorWithComments() {
    Blog blog1 = new Blog("1", "Nice", "Very Nice");
    Blog blog2 = new Blog("2", "Disappointing", "Ok", "Could be better");
    List blogs = List.of(blog1, blog2);

    Map>> authorComments1 = blogs.stream()
     .collect(Collectors.groupingBy(Blog::getAuthorName,
       Collectors.mapping(Blog::getComments, Collectors.toList())));

    assertEquals(2, authorComments1.size());
    assertEquals(2, authorComments1.get("1").get(0).size());
    assertEquals(3, authorComments1.get("2").get(0).size());

    Map> authorComments2 = blogs.stream()
      .collect(Collectors.groupingBy(Blog::getAuthorName,
        Collectors.flatMapping(blog -> blog.getComments().stream(),
        Collectors.toList())));

    assertEquals(2, authorComments2.size());
    assertEquals(2, authorComments2.get("1").size());
    assertEquals(3, authorComments2.get("2").size());
}

Collectors.mapping отображает все сгруппированные комментарии авторов в контейнер коллектора, т.е. List, тогда как эта промежуточная коллекция удаляется с помощьюflatMapping, поскольку она дает прямой поток списка комментариев, который будет отображаться в контейнер сборщика.

4. Заключение

В этой статье показано использование новогоCollectors, введенного вJava9, т.е. Collectors.filtering() and Collectors.flatMapping() used in combination with Collectors.groupingBy().

Эти коллекторы также можно использовать вместе сCollectors.partitioningBy(), но он создает только два раздела в зависимости от условий, а реальная мощность коллекторов не используется; поэтому исключен из этого руководства.

Полный исходный код для фрагментов кода в этом руководстве доступенover on GitHub.