【源码运行】Stream API 在Java8及以上版本:creation, parallelStream, iterate, filter, map, match, reduce,collect示例

【源码运行】Stream API 在Java8及以上版本:creation, parallelStream, iterate, filter, map, match, reduce,collect示例_第1张图片

在这里插入图片描述

※目录

        ⚜ 1 简介
    ⚜ 2 流接口Stream API
    ⚜ 3 流操作Stream Operations
    ⚜ 4 综合示例
    ⚜ 5 小结
    ⚜ 参考文章

本文涉及的示例源代码可在GitHub账号【hcysky】找到并下载。

1 简介

返回目录

  • ✨ 在Java8 API中增添了新的抽象类Streams,将待处理的元素集合视作一种流,并在管道中传输,且可在管道的节点上进行多种处理,比如排序、筛选、聚合等。

  • ✨ 因此,在Java8及以上版本中,可利用stream().filter来筛选出理想的结果,也即根据条件来查找对象集合。


2 流接口Stream API

返回目录


2.1 创建流 Stream Creation

Streams 使用stream()和of()方法,可以由不同的数据源创建,比如集和Collection、数组Array。

String[] array = new String[]{"Beijing", "Tianjin", "Shanghai"};
Stream<String> stream_method = Arrays.stream(array);//using stream() method

Stream<String> stream_of = Stream.of("Beijing", "Tianjin", "Shanghai");//using of() method

stream() 默认方法被添加到集合Collection接口,并允许使用任何集合作为元素源创建Stream

Stream<String> stream = list.stream();
  • 完整示例代码如下:
import java.util.*;
import java.util.stream.Stream;

//使用method()和of()方法来创建Stream
//数据源包括集和Collection、数组Array
//数据类型包括Integer和String

public class stream_creation {
    public static void main(String[] args) {
        //Integer
        List<Integer> list_int = Arrays.asList(9, 12, 25, 36, 42, 55, 73, 95); //by Collection
        System.out.println("Output(x > 10 && x < 30):");
        list_int.stream().filter(number -> (number > 10 && number < 30)).forEach(System.out::println);//使用stream().filter获取大于10且小于30的数,并打印出来

        Integer[] array_int = new Integer[] { 9, 12, 25, 36, 42, 55, 73, 95 };//by Array
        Stream<Integer> stream_int1 = Arrays.stream(array_int);//using stream() method
        System.out.println("Output(x % 2 == 0):");
        stream_int1.filter(number -> (number % 2 == 0)).forEach(System.out::println);

        Stream<Integer> stream_int2 = Stream.of(9, 12, 25, 36, 42, 55, 73, 95);//using of() method
        System.out.println("Output(x % 5 == 0):");
        stream_int2.filter(number -> (number % 5 == 0)).forEach(System.out::println);

        //String
        List<String> list_str = Arrays.asList("Beijing", "Tianjin", "Shanghai"); //by Collection
        System.out.println("Output(location != Shanghai):");
        list_str.stream().filter(location -> location != "Shanghai").forEach(System.out::println);

        String[] array_str = new String[] { "Beijing", "Tianjin", "Shanghai" };//by Array
        Stream<String> stream1 = Arrays.stream(array_str);//using stream() method
        System.out.println("Output(location != Beijing):");
        stream1.filter(location -> location != "Beijing").forEach(System.out::println);

        Stream<String> stream2 = Stream.of("Beijing", "Tianjin", "Shanghai");//using of() method
        System.out.println("Output(location != Tianjin):");
        stream2.filter(location -> location != "Tianjin").forEach(System.out::println);
    }
}
  • 运行结果为:
    【源码运行】Stream API 在Java8及以上版本:creation, parallelStream, iterate, filter, map, match, reduce,collect示例_第2张图片

在这里插入图片描述

2.2多线程流 Multi-threading With Streams

  1. Stream API 还通过提供以并行模式在流元素上运行操作的 parallelStream() 方法来简化多线程。
  2. parallelStream是流并行处理程序的替代方法。
  3. 下面的代码允许为流的每个元素并行的运行doWork()方法:
list.parallelStream().forEach(element -> doWork(element));

以下实例利用 parallelStream() 输出满足条件的整数及其数量.

  • 完整示例代码如下:
import java.util.*;
import java.util.stream.Stream;

public class stream_multi_threading {
    public static void main(String[] args) {
 
        List<Integer> list_int = Arrays.asList(9, 12, 25, 36, 42, 55, 73, 95); //by Collection
        System.out.println("Output(x > 10 && x < 30):");
        
        //使用stream().filter获取大于10且小于30的数,并打印出来
        list_int.stream().filter(number -> (number > 10 && number < 30)).forEach(System.out::println);
        
		//打印满足上述条件整数的数量
        long count = list_int.parallelStream().filter(number -> (number > 10 && number < 30)).count();
        System.out.println("Output number(x > 10 && x < 30):\t" + count);
    }
}
  • 运行结果为:
    在这里插入图片描述


3 流操作Stream Operations

返回目录


  1. 可以基于流执行许多有用的操作。
  2. 流操作可以细分为中间操作 (返回Stream) 和终端操作 (返回定类型的结果)。中间操作允许有多重链式处理。
  3. 值得注意的是:对流的操作不会改变源。

简单示例如下:distinct() 方法表示一个中间操作,它创建一个新流,其中包含前一个流的唯一性元素集。count() 方法是一个终端操作,它返回流的大小。

long count = list.stream().distinct().count();

3.1 迭代Iterating

流 API 有助于替换forfor-eachwhile循环。它专注于操作的逻辑,但不能处理元素序列的迭代。

下面的示例:是将for循环替代为streamiterating的操作:

for循环:

for (String string : list) {
    if (string.contains("Apple")) {
        return true;
    }
}

Stream的Iterating操作:

boolean isExist = list.stream().anyMatch(element -> element.contains("Apple"));
  • 完整示例代码如下:
import java.util.*;
import java.util.stream.Stream;

public class stream_iterating {
    public static void main(String[] args) {

        List<Integer> list_int = Arrays.asList(9, 12, 25, 36, 42, 55, 73, 95); //by Collection

        //基于Iterating,查询是否有整除5发整数
        System.out.print("Output( 25 ? ):\t");
        boolean isExistNum1 = list_int.stream().anyMatch(number -> number == 25);
        if (isExistNum1) {
            System.out.println("Yes");
        } else {
            System.out.println("No");
        }

        //基于Iterating,查询是否有整数17
        System.out.print("Output( 17 ? ):\t");
        boolean isExistNum2 = list_int.stream().anyMatch(number -> number == 17);
        if (isExistNum2) {
            System.out.println("Yes");
        } else {
            System.out.println("No");
        }
    }
}
  • 运行结果为:
    在这里插入图片描述
    在这里插入图片描述

3.2 过滤Filtering

filter()方法允许我们选取满足谓词predicate的元素流。
例如,下面语句创建了list,并添加了元素:

ArrayList<String> list = new ArrayList<>();
list.add("One");
list.add("Derek");
list.add("Change");
list.add("Italy");
list.add("");
list.add("Thursday");
list.add("Apple");

下面的代码创建一个List的Stream,查找此流中包含 字符a 的所有元素,并创建一个仅包含筛选元素的新流:

Stream<String> stream = list.stream().filter(element -> element.contains("a"));
  • 完整示例代码如下:
import java.util.*;
import java.util.stream.Stream;

public class stream_filtering {
    public static void main(String[] args) {

        ArrayList<String> list = new ArrayList<>();
        list.add("One");
        list.add("Derek");
        list.add("Change");
        list.add("Italy");
        list.add("");
        list.add("Thursday");
        list.add("Apple");

        Stream<String> stream = list.stream().filter(element -> element.contains("a"));
        stream.forEach(System.out::println);//forEach()迭代流中的每个元素
    }
}
  • 运行结果为:在这里插入图片描述
    在这里插入图片描述

3.3 映射Mapping

map():将特定的函数作用于源Stream的元素,然后把得到的新元素形成新的Stream。

以下代码片段使用 map 输出了对应元素的平方数:

List<Integer> numList = Arrays.asList(1, 2, 3, 4, 5);
// 获取对应的平方数
List<Integer> numSquareList = numList.stream().map( number -> number*number).distinct().collect(Collectors.toList());
  • 完整示例代码如下:
import java.util.*;
import java.util.stream.Collectors;
// import java.util.stream.Stream;

public class stream_mapping {
    public static void main(String[] args) {

        List<Integer> numList = Arrays.asList(1, 2, 3, 4, 5);
        System.out.println("numList:");
        numList.stream().forEach(System.out::println);

		//基于map()方法,将源numList的所有元素计算出平方数,并形成了心流numSquareList
        List<Integer> numSquareList = numList.stream().map(number -> number * number).distinct()
                .collect(Collectors.toList()); 

        System.out.println("\nnumSquareList:");
        numSquareList.stream().forEach(System.out::println);

    }
}
  • 运行结果为:

【源码运行】Stream API 在Java8及以上版本:creation, parallelStream, iterate, filter, map, match, reduce,collect示例_第3张图片
在这里插入图片描述

3.4 匹配Matching

anyMatch()、allMatch()、noneMatch():流 API 提供了一组方便的工具,用于根据某些谓词predicate验证序列的元素。
根据它们的名字,其功能是一目了然的。

这些都是返回布尔值boolean的终端操作terminal operations

boolean isAnyValid = list.stream().anyMatch(element -> element.contains("h")); // true or false
boolean isAllValid = list.stream().allMatch(element -> element.contains("h")); // true or false
boolean isNoneValid = list.stream().noneMatch(element -> element.contains("h")); // true or false

对于空的流,具有任何给定谓词predicate的 allMatch() 方法都将返回 true:

Stream.empty().allMatch(Objects::nonNull); // true
  • 这是一个合理的默认值,因为我们找不到任何不满足谓词的元素。
    类似地,anyMatch()方法总是为空流返回 false:
Stream.empty().anyMatch(Objects::nonNull); // false

同样,这是合理的,因为我们找不到满足此条件的元素。

  • 完整示例代码如下:
import java.util.*;
import java.util.stream.Stream;

public class stream_matching {
    public static void main(String[] args) {

        ArrayList<String> list = new ArrayList<>();
        list.add("One");
        list.add("Derek");
        list.add("Change");
        list.add("Italy");
        list.add("");
        list.add("Thursday");
        list.add("Apple");

        list.stream().forEach(System.out::println);//输出整个list

        boolean isAnyValid = list.stream().anyMatch(element -> element.contains("k")); //anyMatch
        if (isAnyValid) {
            System.out.println("anyMatch(k) is true");
        } else {
            System.out.println("anyMatch(k) is false");
        }

        boolean isAllValid = list.stream().allMatch(element -> element.contains("a")); //allMatch
        if (isAllValid) {
            System.out.println("allMatch(a) is true");
        } else {
            System.out.println("allMatch(a) is false");
        }

        boolean isNoneValid = list.stream().noneMatch(element -> element.contains("x")); //noneMatch
        if (isNoneValid) {
            System.out.println("noneMatch(x) is true");
        } else {
            System.out.println("noneMatch(x) is false");
        }
    }
}
  • 运行结果为:
    【源码运行】Stream API 在Java8及以上版本:creation, parallelStream, iterate, filter, map, match, reduce,collect示例_第4张图片

在这里插入图片描述

3.5 规约Reduction

  1. reduce():Stream API 允许在 Stream 类型中,根据指定的函数将元素序列规约到某个值。
  2. 此方法采用两个参数:第一个 为 起始值,第二个 为累加器函数。

假设您有一个 List,并且希望得到所有这些元素和一些初始Integer的总和(在此示例中为 10)。可以运行以下代码,结果将为 16 (10 + 1 + 2 + 3)。

List<Integer> integers = Arrays.asList(1, 2, 3);
Integer reduced = integers.stream().reduce(10, (a, b) -> a + b);
  • 完整示例代码如下:
import java.util.*;

public class stream_reduction {
    public static void main(String[] args) {

        List<Integer> intList = Arrays.asList(1, 2, 3);
        intList.stream().forEach(System.out::println);

        Integer reduceSum = intList.stream().reduce(10, (a, b) -> a + b);
        System.out.println("result: " + reduceSum);
    }
}
  • 运行结果为:


    在这里插入图片描述

在这里插入图片描述

3.6 聚合Collecting

  1. 规约也可以由 Stream 类型的 collect() 方法提供。在将流转换为聚合器或映射器,并以单个字符串的形式表示流的情况下,此操作非常方便。
  2. 有一个实用程序类聚合器Collectors,它为几乎所有典型的收集操作提供了解决方案。对于某些负责的任务,可以创建自定义聚合器。
List<String> resultList 
  = list.stream().map(element -> element.toUpperCase()).collect(Collectors.toList());
  • 完整示例代码如下:
import java.util.*;
import java.util.stream.Collectors;

public class stream_collecting {
    public static void main(String[] args) {

        ArrayList<String> list = new ArrayList<>();
        list.add("One");
        list.add("Derek");
        list.add("Change");
        list.add("Italy");
        list.add("");
        list.add("Thursday");
        list.add("Apple");

        System.out.println("List: ");
        list.stream().forEach(System.out::println);

        System.out.println("\nresultList: ");
        List<String> resultList = list.stream().map(element -> element.toUpperCase()).collect(Collectors.toList());
        resultList.stream().forEach(System.out::println);
   }
}
  • 运行结果为:


    【源码运行】Stream API 在Java8及以上版本:creation, parallelStream, iterate, filter, map, match, reduce,collect示例_第5张图片


4 综合示例

返回目录


下面为一个简单的示例:新建了一个类Fruit,包含两个成员变量pricename;使用List来存储Fruit类型的变量,然后由stream().filter来筛选满足条件的集和。

  • 完整示例代码如下:
import java.io.*;
import java.util.*;
import java.util.stream.Collectors;

public class stream_filter {
    public static void main(String[] args) throws IOException{
        
        List<Fruit> fruits = new ArrayList<Fruit>();
        fruits.add(new Fruit("Apple", 9.9));
        fruits.add(new Fruit("Orange", 12.5));
        fruits.add(new Fruit("Banana", 15.9));

        //展示原始的水果列表
        System.out.println(">>>>>> Before filter: ");
        for(Fruit r : fruits){
            System.out.println("Name: " + r.name + ", Price: " + r.price);
        }
       
        //filter-1: 筛选出水果价格大于10.0的
        List<Fruit> res1 = fruits.stream().filter(f -> f.getPrice() > 10.0).collect(Collectors.toList()); //Note: 此处的f可以设置为任意的变量名
        System.out.println(">>>>>> After filter-1: ");
        for( Fruit r : res1){
            System.out.println("Name: " + r.name + ", Price: " + r.price);
        }

        //filter-2: 筛选出水果名称为"Apple"的
        List<Fruit> res2 = fruits.stream().filter(o -> "Apple".equals(o.getName())).collect(Collectors.toList()); //Note: 此处的o可以设置为任意的变量名
        System.out.println(">>>>>> After filter-2: ");
        for( Fruit r : res2){
            System.out.println("Name: " + r.name + ", Price: " + r.price);
        }
    }

    public static class Fruit{
        String name;
        double price;

        public Fruit(String name, double price) {
            this.name = name;
            this.price = price;
        }

        public void setName(String name) {
            this.name = name;
        }
        public String getName() {
            return this.name;
        }
        
        public void setPrice(double price) {
            this.price = price;
        }
        public  double getPrice() {
            return this.price;
        }
    }
}


  • 运行结果为:

【源码运行】Stream API 在Java8及以上版本:creation, parallelStream, iterate, filter, map, match, reduce,collect示例_第6张图片



5 小结

返回目录


在本文中,我们简要介绍了Java 8 最有趣的功能之一 Java Stream ,并为每个常用API提供了可直接运行的源码示例,也提供了一个综合示例 。 当然,还有许多使用Stream的更高级的例子;本文的目的只是提供一个快速且实用的介绍,比如:介绍您可以使用该功能开始做什么,并作为探索和进一步学习的起点。



参考文章

  • Introduction to Java Streams | Baeldung
  • Stream filter() in Java with examples - GeeksforGeeks
  • What are Java 8 streams? (logicbig.com)
  • Java 8 Stream | 菜鸟教程 (runoob.com)

【源码运行】Stream API 在Java8及以上版本:creation, parallelStream, iterate, filter, map, match, reduce,collect示例_第7张图片

在这里插入图片描述

你可能感兴趣的:(Java,java,Java,8,Streams,iterate,filter,Stream,API,示例源码)