Java 8 - 省略繁琐的收集方法

时间:2016-05-09 19:40:48

标签: java java-8 java-stream

Java 8 stream api是一个非常好的功能,我非常喜欢它。让我紧张的一件事是90%的时间我想作为集合输入作为集合和输出。结果是我必须一直调用stream()collect()方法:

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

是否有任何java api可以让我跳过流并直接对集合进行操作(比如c#中的linq):

collection.filter(p->p.isCorrect)

10 个答案:

答案 0 :(得分:42)

是的,使用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());
}

答案 1 :(得分:17)

您可能喜欢使用StreamEx

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

这具有在保持不变性的同时略微更短暂的优点。

答案 2 :(得分:10)

如果你想对集合进行操作Guava's FluentIterable是一种方法!

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

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

答案 3 :(得分:7)

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

答案 4 :(得分:7)

Streams有一个定义良好的架构,which you can read a lot about。在开始这条道路之前,你可能想要了解它。

但为什么不实现一个集合,它实现了一个包含该代码的类似流接口呢?

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

然后你可以为你的用例做一些棘手的假设。您仍然可以从集合界面打开一个流,但您也可以直接跳入,然后在该句柄的内部打开我想要的流的开头。

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

您的IDE将直接向您推送实现所有内容...只需将所有内容传递回默认实现。

答案 5 :(得分: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 + "]");

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

答案 6 :(得分:3)

如果您愿意使用第三方库,则可以使用Eclipse Collections,其中包含可直接在集合下使用的丰富API。您的示例可以使用Eclipse Collections编写如下。

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

注意:我是Eclipse Collections的提交者。

答案 7 :(得分:1)

您可以从番石榴库中试试这个。它似乎比Stream方法更混乱。

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

有关该技术的讨论,请参阅Google Collections (Guava Libraries): ImmutableSet/List/Map and Filtering

答案 8 :(得分:1)

是的,有几个库可以解决Java 8的流详细问题。一份不完整的清单:

我喜欢jOOL。我在上一期项目中一直在使用它。我认识的其他人但我并没有真正使用,所以我无法给你一个印象。

使用jOOL的例子是:

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

答案 9 :(得分:0)

使用cyclops-react,您有多种选择。

我们可以使用Lazy Extended Collections

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

支持可变,不可变和持久的扩展集合。集合上的函数操作是惰性的(即表现得像可重放的Streams),并且仅在首次访问时才实现。

我们可以使用强大的扩展Stream类型

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

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