省略繁琐的collect方法

zzoitvuj  于 2021-07-03  发布在  Java
关注(0)|答案(10)|浏览(338)

Java8流api是一个非常好的特性,我非常喜欢它。有一件事让我很紧张,那就是90%的时间我都想把输入作为集合,把输出作为集合。结果是我不得不打电话 stream() 以及 collect() 一直以来的方法:

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

有没有JavaAPI可以让我跳过流并直接操作集合(比如 linq 在c#?):

collection.filter(p->p.isCorrect)
6za6bjd0

6za6bjd01#

是的,使用 Collection#removeIf(Predicate) :
删除此集合中满足给定 predicate 的所有元素。
请注意,它将更改给定集合,而不是返回新集合。但您可以创建集合的副本并对其进行修改。还要注意, 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());
}
p3rjfoxz

p3rjfoxz2#

streams有一个定义良好的体系结构,您可以阅读很多关于它的内容。在你开始走这条路之前,你可能想读一下。
但是为什么不实现一个集合呢?它实现了一个类似的流接口,为您封装代码?

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

然后你可以为你的用例做一些棘手的假设。您仍然可以从collections接口打开一个流,但是您也可以直接跳入,然后在这个句柄的内部打开流。

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

你的ide将帮助你实现一切。。。只需将所有内容传递回默认实现。

p5cysglq

p5cysglq3#

我还认为streamapi很好,但是对于短操作来说冗长。我在一些项目中使用了这些实用方法:

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 + "]");

通常我也会静态导入方法。

eivgtgni

eivgtgni4#

是的,有几个库处理Java8的流详细性。不完整的列表:
乔尔
java 俚语
拖缆
我更喜欢乔。我在上一个项目中一直在使用它。其他的我知道,但我没有真正使用,所以我不能给你一个印象。
你和乔尔的例子是:

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

izkcnapc5#

如果您愿意使用第三方库,那么可以使用eclipse集合,它在collections下直接提供丰富的api。您的示例可以用eclipse集合编写如下。

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

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

rslzwgfq

rslzwgfq6#

您可能喜欢使用streamex

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

这样做的好处是在保持不变性的同时稍微简短一些。

z3yyvxxp

z3yyvxxp7#

如果你想操作收集Guava的fluentiterable是一种方式去!
示例(获取10个首批vip客户的id):

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

tzxcd3kk8#

你可以试试这个,从Guava图书馆。它似乎比流式方法要简单一点。

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

有关该技术的讨论,请参见googlecollections(guava库):immutableset/list/map和filtering。

nszi6y05

nszi6y059#

有了独眼巨人,你有很多选择。
我们可以利用延迟的扩展集合

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

支持可变、不可变和持久的扩展集合。集合上的函数操作是惰性的(即行为类似于可重放流),并且仅在第一次访问时才具体化。
我们可以使用强大的扩展流类型

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

[我是独眼巨人react的首席开发者]

yfwxisqw

yfwxisqw10#

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

相关问题