Java 8 – 省去繁琐的收集方法

Java 8的streamAPI是非常好的function,我绝对喜欢它。 有一件事让我感到厌烦,那就是我有90%的时间想把收集和输出作为集合input。 结果是我必须始终调用stream()collect()方法:

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

有没有任何Java API,可以让我跳过stream,直接操作集合(如C#中的linq ?):

 collection.filter(p->p.isCorrect) 

如果你想操作collections番石榴的FluentIterable是一种方式去!

示例(获得10个第一VIP客户的ID):

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

是的,使用Collection#removeIf(Predicate)

删除满足给定谓词的所有这个集合的元素。

请注意,它会改变给定的集合,而不是返回一个新的。 但是你可以创build一个集合的副本并对其进行修改。 还要注意谓词需要被否定为一个filter:

 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在评论中所build议的那样,如果您select在代码中定义此实用程序方法,并在任何地方使用它,则需要获取过滤的集合,然后将该调用委托给该实用程序中的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(); 

这具有稍微更简短而保持不变的优点。

Streams有一个明确的架构进入, 你可以阅读很多 。 在开始这条路之前,您可能需要阅读相关内容。

但为什么不实现一个集合,它实现了一个类似的stream接口,为你打包代码?

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

那么你可以为你的用例做一些棘手的假设。 您仍然可以从集合界面打开一个stream,但是您也可以直接跳转,然后在处理stream的开始位置处进行操作。

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

你的IDE将跳到你正确的实施一切…只是把一切都交还给默认的实现。

如果您需要过滤视图而不修改原始集合,请考虑Guava的Collections2.filter()

我也认为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 + "]"); 

通常我静态导入的方法。

如果您打算使用第三方库,则可以使用集合直接提供丰富API的Eclipse集合。 您的示例可以使用Eclipse Collections编写如下。

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

注意:我是Eclipse集合的提交者。

你可以试试,从番石榴库。 这似乎比Stream方法稍微混乱一些。

  ImmutableList.copyOf(Iterables.filter(collection, MyClass::isCorrect)); 

查看谷歌collections(番石榴图书馆):ImmutableSet /列表/地图和过滤技术的讨论。

是的,有几个库可以解决Java 8stream冗长的问题。 不完整的列表:

  • jOOL
  • javaslang
  • StreamEx

我喜欢用jool。 我一直在使用它在我的最后一个项目。 我认识的其他人,但我没有真正使用,所以我不能给你一个印象。

你用jOOL的例子是:

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

与独眼巨人反应,你有很多select。

我们可以使用懒惰扩展集合

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

支持可变的,不可变的和持久的扩展集合。 对集合的function操作是懒惰的(即像可重放的Streams一样),并且只在第一次访问时被实现。

我们可以使用强大的扩展streamtypes

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

[披露我是独眼巨人反应的主要开发者]