Java8最具革命性新特性之StreamAPI
上一篇总结了Lambda表达式,本篇主要对StreamAPI进行总结归纳,这是Java8中两大最为重要的改变。StreamAPI(java.util.stream)是真正的函数式编程风格引入到Java中。是目前为止对Java类库最好的补充,因为Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。
Stream API 对集合数据进行操作,就类似于使用 SQL 执行的数据库查询。也可以使用 Stream API 来并行执行操作。简言之,Stream API 提供了一种高效且易于使用的处理数据的方式。
1.Stream是什么,有什么特点?
Stream是什么数据处理流,是对内存中的数据,一般是集合或数组中的数据进行处理用的。Stream只负责对数据进行处理(筛选、过滤、统计、遍历显示等),不负责存储。存储数据仍然由集合、数组等容器完成Stream对数据的处理是不修改集合和数组,只会返回处理后的结果。类似select的sql查询语句对数据库进行查询,得到结果,但是查询不会修改数据库中的数据。
Stream特点:
①Stream对数据的处理是不修改集合和数组,只会返回处理后的结果
②Stream操作是一个延迟操作,如果没有进行终结操作之前,之前的操作是不会执行的
③Stream是不可变对象 即,每次调用stream的中间操作方法后,必须重新用Stream的对象接收,否则就会有问题,或者进行连写操作。
2.Stream数据流创建方式(4种)
①通过集合创建 -----> 集合对象.stream()
②通过数组工具类 -----> Arrays.stream(数组对象)
③Stream.of
④无限流 -----> Stream.generate(Supplier s)
代码示例01:
public class TestStream01 { @Test public void test01(){ ArrayList<Integer> list = new ArrayList<>(); for (int i = 1; i <= 10; i++) { list.add(i); } //Java8给集合添加了stream() Stream<Integer> stream = list.stream();// (1)集合对象.stream() } @Test public void test02(){ int[] arr = {1,2,3,4,5}; IntStream stream = Arrays.stream(arr);//(2)Arrays.stream(数组对象) } @Test public void test03(){ Stream<Integer> stream = Stream.of(1,2,3,4,5,6);//(3)Stream.of } @Test public void test04(){ Stream<Double> stream = Stream.generate(Math::random);// 3ff7 (5)Stream.generate(Supplier<T> s) } }
3.Stream的操作步骤(3步)
①创建Stream
②中间操作 (0~n步的筛选、排序…)
③终结操作
代码示例02:
public class TestStream02 { @Test public void test05(){ //创建流 Stream<Integer> stream = Stream.of(1,2,3,4,5,6); //中间操作 //Consumer void accept(T t) stream = stream.peek(System.out::println); //终结操作 long count = stream.count(); System.out.println("个数:"+count); } @Test public void test06(){ //创建流 Stream<Double> stream = Stream.generate(Math::random); //终结操作 stream.forEach(System.out::println); } @Test public void test07(){ ArrayList<Integer> list = new ArrayList<>(); for (int i = 1; i <= 10; i++) { list.add(i); } //Java8给集合添加了stream() Stream<Integer> stream = list.stream(); //过滤:filter //Predicate<T> boolean test(T t) stream = stream.filter(num -> num%3==0); stream.forEach(System.out::println); System.out.println(list); } @Test public void test08(){ //创建流、中间、终结 进行了“连写” Stream.generate(Math::random) .limit(10) .filter(num->num>0.5) .distinct() .forEach(System.out::println); } }
4.Stream的操作步骤之中间操作
中间操作常见方法:0~n步
①filter(Predicate p):过滤
②distinct():去重
③limit(long maxSize):限制几个
④skip(long n):跳过几个
⑤sorted():排序 (用元素的自然排序)
sorted(Comparator com):排序 (用定制排序)
⑥peek(Consumer action):对流中的数据进行Consumer指定的操作,但是不影响元素的个数
⑦map(Function f):映射
⑧mapToDouble(ToDoubleFunction f)
⑨flatMap(Function f) :扁平映射
代码示例03:
public class TestMiddle { @Test public void test13(){ //把流中的"hello:java"等,拆开,合并成一个新的流 Stream.of("hello:java","atguigu:good","world:big") /* * <R> Stream<R> flatMap(Function<? super T,? extends Stream<? extends R>> mapper) * Function<T,R> R apply(T t) * Function<T,R> Stream<R> apply(T t) * Function<String,R> Stream<R> apply(String t) * * t.split(":")返回值类型 String[] */ .flatMap(t -> Stream.of(t.split(":"))) .forEach(System.out::println); } @Test public void test12(){ ArrayList<Employee> list = new ArrayList<>(); list.add(new Employee("张三", 13000)); list.add(new Employee("李四", 14000)); list.add(new Employee("王五", 9000)); //用流操作集合的元素 //(1)打印流中的每一个元素 //(2)只保留薪资是10000以上的 //(3)统计最后留下的员工的薪资总数 OptionalDouble sum = list.stream() .peek(System.out::println) .filter(e -> e.getSalary()>10000) /* * ToDoubleFunction 抽象方法 double applyAsDouble(T value) */ .mapToDouble(e -> e.getSalary()) /* * DoubleBinaryOperator 抽象方法 double applyAsDouble(double left, double right) */ .reduce((a,b)->a+b); System.out.println("sum = " + sum); } @Test public void test11(){ //假设,把流中的字符串的首字母变为大写 Stream.of("hello","java","world") /* * Function<T,R> R apply(T t) */ .map(str -> Character.toUpperCase(str.charAt(0)) + str.substring(1)) .forEach(System.out::println); } @Test public void test10(){ //假设,把流中的数据都扩大2倍 Stream.of(1,2,3,4,5) /* * Function<T,R> R apply(T t) */ .map(num -> num*2) .forEach(System.out::println); } @Test public void test09(){ //对流中的数据进行去重、打印、统计最后的元素个数 long c = Stream.of(11,20,1,3,4,44,23,11,20,34,2,2,5,6) .distinct()//中间操作1 .peek(t -> System.out.println(t))//中间操作1 .count();//终结 System.out.println("数量是:"+c); } @Test public void test08(){ //对流中的数据进行排序,取出第三大的 Stream.of(11,20,1,3,4,44,23,11,20,34,2,2,5,6) .sorted((n1,n2)-> -Integer.compare(n1, n2)) .distinct() .limit(3) .skip(2) .forEach(str -> System.out.println(str)); } @Test public void test07(){ //对流中的数据进行排序,取出最大的三个 Stream.of(11,20,1,3,4,44,23,11,20,34,2,2,5,6) .sorted((n1,n2)-> -Integer.compare(n1, n2)) .distinct() .limit(3) .forEach(str -> System.out.println(str)); } @Test public void test06(){ //对流中的数据进行排序,取出最小的三个 Stream.of(11,20,1,3,4,44,23,11,20,34,2,2,5,6) .sorted() .distinct() .limit(3) .forEach(str -> System.out.println(str)); } @Test public void test05(){ Stream.of(1,2,1,3,4,2,5,6) .distinct() //1,2,3,4,5,6 .skip(3) //4,5,6 .forEach(str -> System.out.println(str)); } @Test public void test04(){ Stream.generate(Math::random) .limit(5) .forEach(num -> System.out.println(num)); } @Test public void test03(){ Stream.of(1,2,1,3,4,2,5,6) .distinct() .filter(num -> num<5) .forEach(str -> System.out.println(str)); } @Test public void test02(){ Stream.of(1,2,1,3,4,2,5,6) .distinct() .forEach(str -> System.out.println(str)); } @Test public void test01(){ Stream.of("hello","world","java","hi","atguigu") /* * Predicate<T>:判断型接口 boolean test(T t) */ .filter(str -> str.length()<=5) /* * Consumer<T> void accept(T t) */ .forEach(str -> System.out.println(str)); } } class Employee{ private String name; private double salary; public Employee(String name, double salary) { super(); this.name = name; this.salary = salary; } public String getName() { return name; } public void setName(String name) { this.name = name; } public double getSalary() { return salary; } public void setSalary(double salary) { this.salary = salary; } @Override public String toString() { return "Employee [name=" + name + ", salary=" + salary + "]"; } }
5.Stream的操作步骤之终结操作
终结操作常见方法:
①void forEach(Consumer c):遍历流中的元素
②long count():统计流中的元素的总个数
③U reduce(BinaryOperator b) :对流中的元素,反复执行某个操作,得到最后的一个总结果
④boolean allMatch(Predicate p):是否都匹配
⑤boolean noneMatch(Predicate p):是否都不匹配
⑥boolean anyMatch(Predicate p):任意一个匹配
⑦Optional findFirst():查找第一个
⑧Optional max(Comparator c) :比较最大值
⑨Optional min(Comparator c):比较小大值
⑩R collect(Collector c):收集(把处理完的结果收集到集合等里面)
代码示例04:
public class TestEnding { @Test public void test05(){ List<Integer> list = Stream.of(1,2,3,4,5,6,7,8) .filter(num -> num%2==0)< 8000 /span> /* * java.util.stream.Collector接口 * 它有一个工具类 java.util.stream.Collectors工具类 */ .collect(Collectors.toList()); System.out.println(list); } @Test public void test04(){ Optional<Integer> first = Stream.of(1,2,3,4) .sorted((t1,t2) -> Integer.compare(t2, t1)) .findFirst(); System.out.println(first); } @Test public void test03(){ //是否都是奇数 boolean allMatch = Stream.of(1,21,3,5,7) /* * Predicate<T> boolean test(T t) */ .allMatch(num -> num%2!=0); System.out.println(allMatch); } @Test public void test02(){ Optional<Integer> max = Stream.of(1,2,3,4,5) /* * BinaryOperator T apply(T t1, T t2) */ .reduce((t1,t2) -> t1>t2?t1:t2); System.out.println(max); } @Test public void test01(){ Optional<Integer> sum = Stream.of(1,2,3,4) /* * BinaryOperator T apply(T t1, T t2) */ .reduce((t1,t2) -> t1+t2); System.out.println(sum); } }
推荐阅读往期博文:
•【JavaSE】Java8最具革命性新特性之Lambda表达式
#轻松一刻
☝上述分享来源个人总结,如果分享对您有帮忙,希望您积极转载;如果您有不同的见解,希望您积极留言,让我们一起探讨,您的鼓励将是我前进道路上一份助力,非常感谢!我会不定时更新相关技术动态,同时我也会不断完善自己,提升技术,希望与君同成长同进步!
☞本人博客:https://coding0110lin.blog.csdn.net/ 欢迎转载,一起技术交流吧!
- 【小家java】java8新特性之---Stream API 详解 (Map-reduce、Collectors收集器、并行流)
- 详解Java8特性之Stream API补充
- Java 8新特性:Stream API
- Java 8新特性:全新的Stream API
- Java8新特性-Stream API 之Collector(三)
- Java8新特性之三:Stream API
- Java 8新特性:全新的Stream API (三) 转载整理
- Java8新特性之Stream API
- Java 8新特性:Stream API
- java8新特性之Stream API(二)
- Java8新特性-Stream API(二)
- java8新特性_day04_(Stream,过滤器,常用API)
- Java8 新特性之Stream API
- 详解Java8特性之Stream API
- Java8新特性之Stream API
- java8新特性(二):StreamAPI
- Java8新特性Stream API与Lambda表达式详解(1)
- Java 8新特性:Stream API
- 详解Java8特性之Stream API并行流
- JAVA8新特性-Stream API,函数式编程