Java 8-опуская утомительный метод сбора
Java 8 stream api-очень хорошая функция, и мне это очень нравится. Одна вещь, которая действует мне на нервы, заключается в том, что 90% времени я хочу иметь вход в виде коллекции и выход в виде коллекций. Следствием этого является то, что я должен позвонить stream() и collect() способ все время:
collection.stream().filter(p->p.isCorrect()).collect(Collectors.toList());
есть ли какой-либо Java api, который позволил бы мне пропустить поток и напрямую работать с коллекциями (например,linq в c#?):
collection.filter(p->p.isCorrect)
10 ответов:
Если вы хотите работать над коллекциями гуава FluentIterable - это путь!
пример (получить идентификаторы 10 первых vip-клиентов):
FluentIterable .from(customers) .filter(customer -> customer.isVIP()) .transform(Client::getId) .limit(10);
да, с помощью
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()); }
вы можете использовать StreamEx
StreamEx.of(collection).filter(PClass::isCorrect).toList();Это имеет преимущества быть немного более кратким, сохраняя неизменность.
потоки имели хорошо определенную архитектуру,который вы можете прочитать много о. Возможно, вы захотите прочитать об этом, прежде чем начать этот путь.
но почему бы не реализовать коллекцию, которая реализует аналогичный интерфейс потока, который обертывает этот код для вас?
public class StreamableCollection implements Collection, Stream { ... }тогда вы могли бы сделать некоторые сложные предположения для вашего варианта использования. Вы все еще можете открыть поток из интерфейса коллекций, но вы также можете перейти прямо и затем на внутренней стороне этой ручки открывается поток, я полагаю.
streamableCollection cs = new streamableCollection(); cs.filter(); cs.stream();ваша IDE будет прыгать вам прямо на реализацию всего... просто передайте все обратно в реализации по умолчанию.
Если вам нужно отфильтрованное представление без изменения исходной коллекции, рассмотрим Guava
Collections2.filter().
Я также думаю, что 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 + "]");обычно я статический импорт метода, а также.
Если вы открыты для использования сторонней библиотеки, вы можете использовать Коллекции Eclipse который имеет богатые API, непосредственно доступные в коллекциях. Ваш пример может быть записан, как показано ниже, с коллекциями Eclipse.
collection.select(p->p.isCorrect) collection.select(MyClass::isCorrect)примечание: Я являюсь коммиттером для коллекций Eclipse.
вы можете попробовать это, из библиотеки гуавы. Он кажется немного менее загроможденным, чем подход к ручью.
ImmutableList.copyOf(Iterables.filter(collection, MyClass::isCorrect));посмотреть Google Collections (Guava Libraries): ImmutableSet/List/Map and Filtering для обсуждения техники.
Да, есть несколько библиотек, которые обращаются к потоковой многословности Java 8. Неполный список:
мои предпочтения идут с jOOL. Я использовал его в своих последних проектах. Другие я знаю, но я действительно не использовал, поэтому я не могу дать вам впечатление.
ваш пример с jOOL будет:
Seq.seq(collection).filter(p->p.isCorrect()).toList();
С Циклоп-реагировать у вас есть несколько вариантов.
мы можем использовать ленивые расширенные коллекции
CollectionX<String> collection = ListX.of("hello","world"); CollectionX<String> filtered = collection.filter(p->p.isCorrect());существует поддержка изменяемых, неизменяемых и постоянных расширенных коллекций. Функциональные операции над коллекциями являются ленивыми (т. е. ведут себя как воспроизводимые потоки) и материализуются только при первом доступе.
мы можем использовать мощный расширенный тип потока
ReactiveSeq.fromIterable(collection) .filter(p->p.isCorrect()) .toList();[раскрытие я ведущий разработчик Циклопа-реагировать]
Comments