美文网首页
如何过滤Java集合中的元素

如何过滤Java集合中的元素

作者: 大哥你先走 | 来源:发表于2019-01-09 23:04 被阅读0次

    1. Overview

    在本篇简短的教程中,我们将学习在Java中过滤集合元素的几种方法,过滤其实就是找到集合中满足条件的所有元素(某种条件下等同于删除不满足条件的元素)。

    在实际的Java应用中集合过滤是一个基本的工作,为此有很多第三方类库提供了集合过滤的功能。

    在本篇教程中我们使用以下方法实现集合过滤功能:

    • Java 8 Streams’ filter() function
    • Relevant Eclipse Collections APIs
    • Apache’s CollectionUtils filter() method
    • Guava’s Collections2 filter() approach
    • Vavr's Stream API

    2. 使用Java Stream API

    自Java 8 推出以来,Streams 在集合数据处理场景发挥了巨大的作用。在大多数情况下,使用Streams都是处理集合数据的首选方法,Java 提供原生支持,不依赖任何第三方类库。

    2.1. 使用 Stream.filter 对集合过滤

    为了简单起见,我们所有样例代码都以提取整数集合中所有的偶数为目标。因此,集合中的所有元素都需要执行 ‘value % 2 == 0‘ 检查,在Java中可以用 Predicate 对象表示检查条件。

        @Test
        public void test_findEvenNumber_returnSuccess() throws Exception {
            List<Integer> numbers = Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
            List<Integer> evenNumbers = findEvenNumbersUserStream(numbers);
            evenNumbers.forEach(new Consumer<Integer>() {
                @Override
                public void accept(Integer integer) {
                    assertTrue(integer % 2 == 0);
                }
            });
        }
    
        private List<Integer> findEvenNumbersUserStream(List<Integer> baseCollection) {
            Predicate<Integer> streamsPredicate = item -> item % 2 == 0;
            return baseCollection.stream()
                .filter(streamsPredicate)
                .collect(Collectors.toList());
        }
    

    本文提供的所有可以对集合进行过滤的第三方类库都有自己特有的 *Predicate * 实现,但是所有的实现都是一个函数式接口,因此可以使用 Lambda 表达式来定义。

    3. 使用 Eclipse Collections

    我们利用第三方库来实现我们的目标(集合过滤),不管是我们的应用还没有使用Java 8 开发还是我们想使用第三方组件提供但是Java不具备的高级功能。

    Eclipse Collections是一个努力跟上新范例,不断发展并接受所有最新Java版本引入的更改的第三方优秀Java类库。

    3.1. 依赖

    pom.xml 文件添加如下依赖即可使用 Eclipse Collections:

    <dependency>
        <groupId>org.eclipse.collections</groupId>
        <artifactId>eclipse-collections</artifactId>
        <version>9.2.0</version>
    </dependency>
    

    eclipse-collections 包括所有必须的数据结构接口和API实现。

    3.2. 使用 Eclipse Collections 过滤集合

    基于Eclipse Collections 提供的 MutableList 数据结构实现集合过滤:

        @Test
        public void test_findEvenNumbersUseEclipse_returnSuccess() throws Exception {
            List<Integer> numbers = Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
            List<Integer> evenNumbers = findEvenNumbersUseEclipse(numbers);
            evenNumbers.forEach(integer -> assertTrue(integer % 2 == 0));
        }
        
    
        public List<Integer> findEvenNumbersUseEclipse(List<Integer> input) {
            org.eclipse.collections.api.block.predicate.Predicate<Integer> eclipsePredicate
                = item -> item % 2 == 0;
    
            List<Integer> filteredList = Lists.mutable
                .ofAll(input)
                .select(eclipsePredicate);
            return filteredList;
        }
    

    一种替代方案是使用 Iterate 的静态方法 select() 来实现集合过滤功能:

        @Test
        public void test_findEvenNumbersUseEclipseWithStaticMethod_returnSuccess() throws Exception {
            List<Integer> numbers = Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
            List<Integer> evenNumbers = findEvenNumbersUseEclipseWithStaticMethod(numbers);
            evenNumbers.forEach(integer -> assertTrue(integer % 2 == 0));
        }
    
        public List<Integer> findEvenNumbersUseEclipseWithStaticMethod(List<Integer> input) {
            org.eclipse.collections.api.block.predicate.Predicate<Integer> eclipsePredicate
                = item -> item % 2 == 0;
            return (List<Integer>) Iterate.select(input, eclipsePredicate);
        }
    

    4. 使用 Apache 的 CollectionUtils

    4.1. 依赖

    pom.xml 文件添加如下依赖即可使用 Apache 的 CollectionUtils:

    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-collections4</artifactId>
        <version>4.2</version>
    </dependency>
    

    4.2. 使用 CollectionUtils 过滤集合

    使用 CollectonUtils‘ 过滤集合的样例代码如下:

        @Test
        public void test_findEvenNumbersUseApache_returnSuccess() throws Exception {
            List<Integer> inputs = Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
            Collection<Integer> numbers = new LinkedList(inputs);
            Collection<Integer> evenNumbers = findEvenNumbersUseApache(numbers);
            evenNumbers.forEach(integer -> assertTrue(integer % 2 == 0));
        }
    
        public Collection<Integer> findEvenNumbersUseApache(Collection<Integer> baseCollection) {
            org.apache.commons.collections4.Predicate<Integer> apachePredicate = item -> item % 2 == 0;
    
            CollectionUtils.filter(baseCollection, apachePredicate);
            return baseCollection;
        }
    

    注意Apache 的 CollectionUtils 过滤方法会移除输入集合中不满足过滤条件的元素,因此要求集合是可变集合而且支持 remove 操作,否在会抛出异常。

    5. 使用 Guava 的 Collections2 进行集合过滤

    Guava工程包含了若干被Google的 Java项目广泛依赖 的核心库,提供了很多简化Java开发的功能,感兴趣的可以从官方文档获取更多信息。

    5.1. 依赖

    使用Guava之前首先引入Guava,对于maven构建的工程可以将如下依赖添加到 pom.xml 文件:

    <dependency>
      <groupId>com.google.guava</groupId>
      <artifactId>guava</artifactId>
      <version>27.0.1-jre</version>
    </dependency>
    

    5.2. 使用 Collections2 过滤集合

    Guava Collections2* 过滤集合的方式和 Apache CollectionUtils 过滤集合的方式类似,但是不需要修改原来的集合,因此不要求原集合为可变集合:

        @Test
        public void test_findEvenNumbersUseGuava_returnSuccess() throws Exception {
            List<Integer> inputs = Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
            Collection<Integer> evenNumbers = findEvenNumbersUseGuava(inputs);
            evenNumbers.forEach(integer -> assertTrue(integer % 2 == 0));
        }
    
        public Collection<Integer> findEvenNumbersUseGuava(Collection<Integer> baseCollection) {
            com.google.common.base.Predicate<Integer> guavaPredicate = item -> item % 2 == 0;
    
            return Collections2.filter(baseCollection, guavaPredicate);
        }
    

    6. 使用 Vavr 的 Stream 进行集合过滤

    Vavr(以前称为Javaslang)是Java 8+的函数库,它提供持久数据类型和功能控制结构。

    6.1. 依赖

    使用Vavr之前首先引入Vavr,对于maven构建的工程可以将如下依赖添加到 pom.xml 文件

    <dependency>
        <groupId>io.vavr</groupId>
        <artifactId>vavr</artifactId>
        <version>0.9.2</version>
    </dependency>
    

    6.2. 使用 Collections2 过滤集合

    使用 Vavr的 Strem 对集合过滤和使用Java原生的 Stream 对集合过滤语法一样,而且两者都使用Java 定义的 Predicate

        @Test
        public void test_findEvenNumbersUseVavr_returnSuccess() throws Exception {
            List<Integer> inputs = Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
            List<Integer> evenNumbers = Stream.concat(inputs).filter(integer -> integer.intValue() % 2 == 0).asJavaMutable();
            evenNumbers.forEach(integer -> assertTrue(integer % 2 == 0));
        }
    

    7. 总结

    本文介绍了5种对Java 集合过滤的方法,包括Java原生支持的Stream和其他第三方库支持的方法,这些第三方库都是很好的Java开发工具,建议大家可以了解一下。

    本文所有样例的源代码可以从Github获取。

    8 参考

    [1] How to Filter a Collection in Java
    [2] eclipse-collections
    [3] Apache commons-collections
    [4] Guava
    [5] Vavr

    相关文章

      网友评论

          本文标题:如何过滤Java集合中的元素

          本文链接:https://www.haomeiwen.com/subject/gcfwrqtx.html