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();
[披露我是独眼巨人反应的主要开发者]