Узнайте, как объединить коллекцию коллекций в единую коллекцию, используя метод flatCollect в Коллекции Eclipse.

Что такое FlatCollect?

Метод flatCollect - это особая форма collect, где выходные данные Function, предоставленные методу, всегда должны быть какого-то типа Iterable. Цель flatCollect - обеспечить преобразование, которое выравнивает коллекцию коллекций. Этот метод аналогичен по функциям flatMap в Java Streams. Основное отличие состоит в том, что Function для flatCollect должен возвращать Iterable, а Function для flatMap должен возвращать Stream.

Плоский сбор списка (Java 8)

@Test
public void flatCollectingAListJava8()
{
    MutableList<Integer> list = mList(5, 4, 3, 2, 1);
    MutableList<Integer> result = list.flatCollect(Interval::oneTo);

    MutableList<Integer> expected = mList(
            1, 2, 3, 4, 5,
            1, 2, 3, 4,
            1, 2, 3,
            1, 2,
            1);
    Assert.assertEquals(expected, result);
}

Сборные трубопроводы

Мартин Фаулер описывает паттерн Collection Pipeline здесь. Вот пример flatCollect, используемого в конвейере сбора, чтобы найти все методы, которые содержат плоский в своем имени для Списка классов. Здесь я использовал перегруженную форму flatCollect, которая принимает в качестве аргумента целевую коллекцию.

@Test
public void flatCollectingAListOfMethodsToASetJava8()
{
    MutableList<Class<?>> list = mList(
            ListIterable.class,
            MutableList.class,
            ImmutableList.class);
    MutableSet<String> result = list
            .collect(Class::getMethods)
            .flatCollect(Lists.fixedSize::with, mSet())
            .collect(Method::getName)
            .select(each -> each.toLowerCase().contains("flat"));

    MutableSet<String> expected = mSet("flatCollect");
    Assert.assertEquals(expected, result);
}

Метод getMethods в классе возвращает массив, поэтому в Function я перехожу к flatCollect, я конвертирую массив в List. Если бы getMethods вернул List или какой-нибудь другой Iterable тип, я мог бы просто использовать flatCollect передачу Class::getMethods.

Вот тот же пример с использованием Java 10 с выводом типа локальной переменной.

@Test
public void flatCollectingAListOfMethodsToASetJava10()
{
    var list = mList(
            ListIterable.class,
            MutableList.class,
            ImmutableList.class);
    var resultSet = list
            .collect(Class::getMethods)
            .flatCollect(Lists.fixedSize::with, mSet())
            .collect(Method::getName)
            .select(each -> each.toLowerCase().contains("flat"));

    var expected = mSet("flatCollect");
    Assert.assertEquals(expected, resultSet);
}

Симметричная симпатия снова наносит удар

Хотя существует метод с именем collectWith, который является формой collect, который принимает Function2, в настоящее время не существует метода с именем flatCollectWith, который также принимает Function2. Я обнаружил отсутствие flatCollectWith (снова) на этой неделе. Я отправил проблему для этой функции и начал работать над ней на выходных. Я ожидаю, что реализация flatCollectWith будет протестирована и завершена в течение следующих недель или двух.

API, рассмотренные в примерах

  1. flatCollect - преобразует элементы исходной коллекции в новую коллекцию, сглаживая коллекции в исходной коллекции в единую коллекцию.
  2. mList - создает MutableList
  3. mSet - создает MutableSet
  4. Interval.oneTo(int) - создает интервал от 1 до указанного значения
  5. var - Вывод типа локальной переменной включен в Java 10 (JEP 286)

Обратитесь к моим предыдущим блогам из серии EC by Example для примеров collect и select.

Ознакомьтесь с этой презентацией, чтобы узнать больше о происхождении, дизайне и эволюции Eclipse Collections API. Также есть видео, охватывающее слайды, которое было записано на виртуальной встрече сообщества Eclipse.

Коллекции Eclipse открыты для взносов. Если вам нравится библиотека, вы можете сообщить нам об этом, отметив ее на GitHub.