Подтвердить что ты не робот

Java 8 - пропуская утомительный метод сбора

Java 8 stream api - очень приятная функция, и мне это абсолютно нравится. Одна вещь, которая нервничает, заключается в том, что 90% времени я хочу получить в качестве коллекции и выпускать в виде коллекций. В результате я должен все время называть метод stream() и collect():

collection.stream().filter(p->p.isCorrect()).collect(Collectors.toList());

Есть ли какой-либо java-api, который позволит мне пропускать поток и напрямую работать с коллекциями (например, linq в С#?):

collection.filter(p->p.isCorrect)
4b9b3361

Ответ 1

Если вы хотите работать с коллекциями Guava FluentIterable - это путь!

Пример (введите идентификатор 10 первых клиентов vip):

FluentIterable
       .from(customers)
       .filter(customer -> customer.isVIP())
       .transform(Client::getId)
       .limit(10);

Ответ 2

Да, используя Collection#removeIf(Predicate):

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

Обратите внимание, что он изменит данную коллекцию, а не вернет новую. Но вы можете создать копию коллекции и изменить ее. Также обратите внимание, что предикат должен быть сведен к нулю, чтобы действовать как фильтр:

public static <E> Collection<E> getFilteredCollection(Collection<E> unfiltered,
                                                      Predicate<? super E> filter) {
    List<E> copyList = new ArrayList<>(unfiltered);

    // removeIf takes the negation of filter 
    copyList.removeIf(e -> { return !filter.test(e);});  

    return copyList;
}

Но поскольку @Holger предлагает в комментариях, если вы решите определить этот метод утилиты в своем коде и использовать его повсюду, вам нужно получить отфильтрованную коллекцию, а затем просто делегировать вызов методу collect в этой утилите. Ваш код вызывающего абонента будет более кратким.

public static <E> Collection<E> getFilteredCollection(Collection<E> unfiltered,
                                                      Predicate<? super E> filter) {
   return unfiltered.stream()
                    .filter(filter)
                    .collect(Collectors.toList());
}

Ответ 3

Вам может понравиться использовать StreamEx

StreamEx.of(collection).filter(PClass::isCorrect).toList();

Это имеет преимущества быть немного более краткими, сохраняя неизменность.

Ответ 4

Если вам требуется отфильтрованное представление без изменения оригинальной коллекции, рассмотрите Guava Collections2.filter().

Ответ 5

В потоках была четко определенная архитектура, о которой вы можете многое прочитать. Вы можете прочитать об этом, прежде чем начинать путь по этому пути.

Но почему бы не реализовать коллекцию, которая реализует аналогичный интерфейс потока, который завершает этот код для вас?

public class StreamableCollection implements Collection, Stream {
...
}

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

    streamableCollection cs = new streamableCollection();
    cs.filter();
    cs.stream();

В вашей среде IDE вам будет предоставлено право реализовать все... просто передайте все обратно к реализациям по умолчанию.

Ответ 6

Я также считаю, что Stream API хорош, но многословен для коротких операций. Я использовал эти утилиты в нескольких проектах:

import java.util.List;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Functions {

    public static <T,V> List<V> map(final List<T> in, final Function<T, V> function) {
        return in == null ? null : map(in.stream(), function);
    }

    public static <T,V> List<V> map(final Stream<T> in, final Function<T, V> function) {
        return in == null ? null : in
            .map(function)
            .collect(Collectors.toList());
    }

    public static <T> List<T> filter(final List<T> in, final Predicate<T> predicate) {
        return in == null ? null : filter(in.stream(), predicate);
    }

    public static <T> List<T> filter(final Stream<T> in, final Predicate<T> predicate) {
        return in == null ? null : in
            .filter(predicate)
            .collect(Collectors.toList());
    }
}

Это позволяет мне, например,

List<String> wrapped = Functions.map(myList, each -> "[" + each + "]");

Обычно я статично импортирую метод.

Ответ 7

Если вы открыты для использования сторонней библиотеки, вы можете использовать Eclipse Collections, который имеет богатые API-интерфейсы, доступные непосредственно под коллекциями. Ваш пример можно записать, как показано ниже, с помощью Eclipse Collections.

collection.select(p->p.isCorrect)
collection.select(MyClass::isCorrect)

Примечание. Я являюсь коммиттером для коллекций Eclipse.

Ответ 9

Да, существует несколько библиотек, которые ссылаются на многословие потока Java 8. Неполный список:

Мои предпочтения касаются jOOL. Я использовал его в своих последних проектах. Другие, которые я знаю, но я действительно не использовал, поэтому я не могу дать вам впечатления.

Ваш пример с помощью jOOL:

Seq.seq(collection).filter(p->p.isCorrect()).toList();

Ответ 10

С cyclops-react у вас есть несколько вариантов.

Мы можем использовать Lazy Extended Collections

  CollectionX<String> collection = ListX.of("hello","world");
  CollectionX<String> filtered = collection.filter(p->p.isCorrect());

Существует поддержка изменяемых, неизменных и постоянных расширенных коллекций. Функциональные операции над коллекциями ленивы (т.е. Ведут себя как воспроизводимые потоки) и материализуются только при первом доступе.

Мы можем использовать мощный расширенный тип потока

  ReactiveSeq.fromIterable(collection)
             .filter(p->p.isCorrect())
             .toList();

[Раскрытие информации Я ведущий разработчик реакции циклопов]