当前位置: 代码迷 >> 综合 >> Stream API ------java8 新特性(2)
  详细解决方案

Stream API ------java8 新特性(2)

热度:36   发布时间:2023-11-18 07:46:14.0

一、流(Stream)

是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列。
(集合讲的是数据,流讲的是计算!)

注意:
①Stream 自己不会存储元素。
②Stream 不会改变源对象。相反,会返回一个持有结果的新Stream。
③Stream 操作是延迟执行的。它会等到需要结果的时候才执行

Stream 操作三步:

  • 创建 Stream
    一个数据源(如:集合、数组),获取一个流
  • 中间操作
    一个中间操作链,对数据源的数据进行处理
  • 终止操作(终端操作)
    一个终止操作,执行中间操作链,并产生结果

二、流(Stream)的创建

package com.Stream;import com.lambda1.Employe;
import org.junit.Test;import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;/*** 一、Stream 的三个操作步骤**  1、创建 Stream**  2、中间操作**  3、终止操作(终端操作)**/
public class TestStreamAPI1{//创建 Stream@Testpublic void test1(){//1.可以通过 Collection 系列集合提供的 stream() 或 paralleStream()List<String> list = new ArrayList<>();Stream<String> stream1 = list.stream();//2.通过 Arrays 中的静态方法 stream() 获取数组流Employe[] emps = new Employe[10];Stream<Employe> stream2 = Arrays.stream(emps);//3.通过 Stream 类中的静态方法 of()Stream<String> stream3 = Stream.of("aa", "bb", "cc");//4.创建无限流//迭代Stream<Integer> stream4 = Stream.iterate(0, x -> x + 2);stream4.limit(10).forEach(System.out::println);//生成Stream<Double> stream5 = Stream.generate(() -> Math.random());stream5.limit(10).forEach(System.out::println);}
}

三、流(Stream)中间操作

? 多个中间操作可以连接起来形成一个流水线,除非流水线上触发终止操作,否则中间操作不会执行任何的处理!而在终止操作时一次性全部处理,称之为“惰性求值”

1、筛选与切片

筛选与切片:
?? filter —— 接收 Lambda,从流中排除某些元素;
?? limit —— 截断流,使其元素不超过给定数量;
?? skip(n) —— 跳过元素,返回一个仍掉了前 n 个元素的流。若流中元素不足 n 个,则返回一个空流。与 limit(n) 互补;
?? distinct —— 筛选,通过流所生成元素的 hashCode() 和 equals() 去除重复元素。

package com.Stream;import com.lambda1.Employe;
import org.junit.Test;import java.util.Arrays;
import java.util.List;/*** 一、Stream 的三个操作步骤**  1、创建 Stream**  2、中间操作**  3、终止操作(终端操作)**/
public class TestStreamAPI2 {//中间操作//内部迭代由 StreamAPI 完成/*** 筛选与切片* filter —— 接收 Lambda,从流中排除某些元素;* limit —— 截断流,使其元素不超过给定数量;* skip(n) —— 跳过元素,返回一个仍掉了前 n 个元素的流。若流中元素不足 n 个,则返回一个空流。与 limit(n) 互补;* distinct —— 筛选,通过流所生成元素的 hashCode() 和 equals() 去除重复元素。*/List<Employe> employes = Arrays.asList(new Employe("张三", 18,9999.99),new Employe("李四", 38,5555.99),new Employe("王五", 50,6666.66),new Employe("赵六", 16,3333.33),new Employe("田七", 10,7777.77),new Employe("田七", 10,7777.77),new Employe("田七", 10,7777.77));//filter 过滤@Testpublic void test1(){employes.stream()//创建流.filter(e->e.getAge() >= 35)//中间操作.forEach(System.out::println);//终止操作}//limit 限制@Testpublic void test2(){employes.stream().filter(e->e.getSalary() >= 5000).limit(2).forEach(System.out::println);}//skip(n) 跳过@Testpublic void test3(){employes.stream().filter(e -> e.getSalary() >= 5000).skip(2).forEach(System.out::println);}//distinct 去重,通过hashCode() 和 equals() 去重@Testpublic void test4(){employes.stream().distinct().forEach(System.out::println);}
}

注意:distinct 去重的时候,Employee.java 中要覆写 equals() 和 hashCode() 方法:

package com.lambda1;import java.util.Objects;public class Employe {private String name;private int age;private double salary;public Employe() {}public Employe(String name, int age, double salary) {this.name = name;this.age = age;this.salary = salary;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public double getSalary() {return salary;}public void setSalary(double salary) {this.salary = salary;}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Employe employe = (Employe) o;return age == employe.age &&Double.compare(employe.salary, salary) == 0 &&Objects.equals(name, employe.name);}@Overridepublic int hashCode() {return Objects.hash(name, age, salary);}@Overridepublic String toString() {return "Employe{" +"name='" + name + '\'' +", age=" + age +", salary=" + salary +'}';}
}

2、映射

映射:
?? map —— 接收 Lambda,将元素转换成其它形式或提取信息。接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素;
?? flatMap —— 接收一个函数作为参数,将流中的每个值都转换成另一个流,然后把所有流连接成一个流;

package com.Stream;import com.lambda1.Employe;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;/*** 一、Stream 的三个操作步骤**  1、创建 Stream**  2、中间操作**  3、终止操作(终端操作)**/
public class TestStreamAPI3 {List<Employe> employes = Arrays.asList(new Employe("张三", 18,9999.99),new Employe("李四", 38,5555.99),new Employe("王五", 50,6666.66),new Employe("赵六", 16,3333.33),new Employe("田七", 10,7777.77));/*** 映射:*   map —— 接收 Lambda,将元素转换成其它形式或提取信息。接收一个函数作为参数,*          该函数会被应用到每个元素上,并将其映射成一个新的元素;*   flatMap —— 接收一个函数作为参数,将流中的每个值都转换成另一个流,然后把所有流连接成一个流;*/@Testpublic void test1(){List<String> list = Arrays.asList("aaa","bbb","ccc","ddd","eee");list.stream()
//                .map(e -> e.toUpperCase()).map(String::toUpperCase).forEach(System.out::println);System.out.println("--------------------------------");employes.stream().map(Employe::getName).forEach(System.out::println);System.out.println("--------------------------------");list.stream().flatMap(TestStreamAPI3::filterCharacter).forEach(System.out::print);}public static Stream<Character> filterCharacter(String str){ArrayList<Character> list = new ArrayList<>();for (Character ch : str.toCharArray()){list.add(ch);}return list.stream();}
}

3、排序

排序:
?? sorted() —— 自然排序(Comparable);
?? sorted(Comparator com) —— 定制排序(Comparator);

package com.Stream;import com.lambda1.Employe;
import org.junit.Test;
import java.util.Arrays;
import java.util.List;/*** 排序*/
public class TestStreamAPI4 {List<Employe> employes = Arrays.asList(new Employe("张三", 18,9999.99),new Employe("李四", 38,5555.99),new Employe("王五", 50,6666.66),new Employe("赵六", 16,3333.33),new Employe("田七", 10,7777.77),new Employe("田七", 16,7777.77),new Employe("田八", 10,7777.77));/*** 排序*   sorted() —— 自然排序(Comparable)*   sorted(Comparator com) —— 定制排序(Comparator)*/@Testpublic void test1(){List<String> list = Arrays.asList("ccc","eee","aaa","ddd","bbb");list.stream().sorted().forEach(System.out::println);System.out.println("--------------------------------------------------");employes.stream().sorted((e1, e2) -> {if (e1.getAge() == e2.getAge()){return e1.getName().compareTo(e2.getName());}else {return e1.getAge()-e2.getAge();}}).forEach(System.out::println);}
}

4、终止操作

4.1、查找与匹配

查找与匹配:
??(1)allMatch —— 检查是否匹配所有元素;
??(2)anyMatch —— 检查是否至少匹配一个元素;
??(3)noneMatch —— 检查是否没有匹配所有元素;
??(4)findFirst —— 返回第一个元素;
??(5)findAny —— 返回当前流中的任意元素;
??(6)count —— 返回流中元素的总数;
??(7)max —— 返回流中最大值;
??(8)min —— 返回流中最小值;

package com.Stream;import com.Stream.Employe.Status;
import org.junit.Test;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;/*** 终止操作*/
public class TestStreamAPI5 {List<Employe> emps = Arrays.asList(new Employe("张三", 18,9999.99, Status.FREE),new Employe("李四", 38,5555.99, Status.BUSY),new Employe("王五", 50,6666.66, Status.VOCATION),new Employe("赵六", 16,3333.33, Status.FREE),new Employe("田七", 10,7777.77, Status.BUSY),new Employe("李八", 16,8888.88, Status.VOCATION));/*** 查找与匹配*  (1)allMatch —— 检查是否匹配所有元素;*  (2)anyMatch —— 检查是否至少匹配一个元素;*  (3)noneMatch —— 检查是否没有匹配所有元素;*  (4)findFirst —— 返回第一个元素;*  (5)findAny —— 返回当前流中的任意元素;*  (6)count —— 返回流中元素的总数;*  (7)max —— 返回流中最大值;*  (8)min —— 返回流中最小值;*/@Testpublic void test1(){//是否匹配所有元素boolean b1 = emps.stream().allMatch(e -> e.getStatus().equals(Status.FREE));System.out.println(b1);//至少匹配一个元素boolean b2 = emps.stream().anyMatch(e -> e.getStatus().equals(Status.FREE));System.out.println(b2);//没有匹配的元素boolean b3 = emps.stream().noneMatch(e -> e.getStatus().equals(Status.FREE));System.out.println(b3);//先按工资排序,然后再找出第一个Optional<Employe> op1 = emps.stream()
//                .sorted((o1, o2) -> Double.compare(o1.getSalary(), o2.getSalary())).sorted(Comparator.comparingDouble(Employe::getSalary)).findFirst();System.out.println(op1.get());//返回当前流中的任意元素Optional<Employe> op2 = emps.parallelStream().filter(e -> e.getStatus().equals(Status.FREE)).findAny();System.out.println(op2.get());}@Testpublic void test2(){//总数long count = emps.stream().count();System.out.println(count);//工资最高Optional<Employe> max = emps.stream()
//                .max((x, y) -> Double.compare(x.getSalary(), y.getSalary()));.max(Comparator.comparingDouble(Employe::getSalary));System.out.println(max.get());//年龄最小Optional<Employe> min = emps.stream()
//                .min((x, y) -> Double.compare(x.getAge(), y.getAge()));.min(Comparator.comparingDouble(Employe::getAge));System.out.println(min.get());//最低工资Optional<Double> minSalary = emps.stream().map(Employe::getSalary).min(Double::compareTo);System.out.println(minSalary.get());}
}

4.2、归约与收集

归约:
?? reduce(T identity, BinaryOperator)/reduce(BinaryOperator) —— 可以将流中元素反复结合起来,得到一个值。

备注:map 和 reduce 的连接通常称为 map-reduce 模式,因为 Google 用它来进行网络搜索而出名。

收集:
?? collect —— 将流转换为其他形式。接收一个 Collector 接口的实现,用于给 Stream 中元素做汇总的方法。

package com.Stream;import org.junit.Test;
import com.Stream.Employe.Status;
import java.util.*;
import java.util.stream.Collectors;/*** 终止操作*/
public class TestStreamAPI6 {List<Employe> emps = Arrays.asList(new Employe("张三", 18,9999.99, Status.FREE),new Employe("李四", 38,5555.99, Status.BUSY),new Employe("王五", 50,6666.66, Status.VOCATION),new Employe("赵六", 16,3333.33, Status.FREE),new Employe("田七", 10,7777.77, Status.BUSY),new Employe("田七", 16,8888.88, Status.VOCATION));/*** 归约*  reduce(T identity, BinaryOperator)/reduce(BinaryOperator) —— 可以将流中元素反复结合起来,*                                                               得到一个值。*/@Testpublic void test1(){List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);Integer sum = list.stream().reduce(0, (x, y) -> x + y);System.out.println(sum);System.out.println("-------------------------------------------");//计算工资总和Optional<Double> op = emps.stream().map(Employe::getSalary).reduce(Double::sum);System.out.println(op.get());}/*** 收集:*    collect —— 将流转换为其他形式。接收一个Collector 接口的实现,*                用于给 Stream 中元素做汇总的方法。*/@Testpublic void test2(){List<String> list = emps.stream().map(Employe::getName).collect(Collectors.toList());list.forEach(x->System.out.print(x+"\t\t"));System.out.println("\n ----------------------------------------------");Set<String> set = emps.stream().map(Employe::getName).collect(Collectors.toSet());set.forEach(x-> System.out.print(x+"\t\t"));}@Testpublic void test3(){//人员总数Long count = emps.stream().count();
//                .collect(Collectors.counting());System.out.println("总数量:"+count);//工资平均值Double avgSalary = emps.stream().collect(Collectors.averagingDouble(Employe::getSalary));System.out.println("平均工资:"+avgSalary);//工资总和Double sumSalary = emps.stream().mapToDouble(Employe::getSalary).sum();
//                .collect(Collectors.summingDouble(Employe::getSalary));System.out.println("工资总和:"+sumSalary);//工资最大值Optional<Employe> maxSalary = emps.stream().max(Comparator.comparingDouble(Employe::getSalary));
//                .max((x, y) -> Double.compare(x.getSalary(), y.getSalary()));
//                .collect(Collectors.maxBy((x, y) -> Double.compare(x.getSalary(), y.getSalary())));System.out.println("工资最大值:"+ maxSalary.get().getSalary());//工资最小值Optional<Employe> minSalary = emps.stream().min(Comparator.comparingDouble(Employe::getSalary));
//                .min((x, y) -> Double.compare(x.getSalary(), y.getSalary()));
//                .collect(Collectors.minBy((x, y) -> Double.compare(x.getSalary(), y.getSalary())));System.out.println("工资最小值:"+ minSalary.get().getSalary());}
}

四、流(Stream)使用

1、streamAPI 练习《一》

package com.Stream;import org.junit.Test;
import com.Stream.Employe.Status;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;/*** streamAPI 练习**/
public class TestStreamAPI7 {List<Employe> emps = Arrays.asList(new Employe("张三", 18,9999.99, Status.FREE),new Employe("李四", 38,5555.99, Status.BUSY),new Employe("王五", 50,6666.66, Status.VOCATION),new Employe("赵六", 16,3333.33, Status.FREE),new Employe("田七", 10,7777.77, Status.BUSY),new Employe("田七", 16,8888.88, Status.VOCATION));/*** 1.给定一个数列表,返回一个由每个数的平方根构成的列表;*   给定【1,2,3,4,5】,应返回【1,4,9,16, 25】*/@Testpublic void test1(){List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);List<Integer> collect = list.stream().map(e -> e * e).collect(Collectors.toList());System.out.println(collect);Integer[] nums = new Integer[]{2, 3, 4, 5, 6};List<Integer> collect1 = Arrays.stream(nums).map(e -> e * e).collect(Collectors.toList());System.out.println(collect1);}/*** 2.用 map 和 reduce 方法数一数流中有多少个Employee?*/@Testpublic void test2(){Optional<Integer> sum = emps.stream().map(e -> 1).reduce(Integer::sum);System.out.println(sum.get());System.out.println("-------------");Optional<Integer> sum2 = emps.stream().map(x -> 1)
//                .reduce((x, y) -> Integer.sum(x, y));.reduce(Integer::sum);System.out.println(sum2.get());}
}

2、streamAPI 练习《二》

(1)、创建 Trader.java 交易员实体类

package com.Stream;/*** 交易员*/
public class Trader {private String name;private String city;public Trader() {}public Trader(String name, String city) {this.name = name;this.city = city;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getCity() {return city;}public void setCity(String city) {this.city = city;}@Overridepublic String toString() {return "Trader{" +"name='" + name + '\'' +", city='" + city + '\'' +'}';}
}

(2)、创建 Trader.java 交易类实体类

package com.Stream;/*** 交易类*/
public class Transaction {private Trader trader;private int year;private int value;public Transaction() {}public Transaction(Trader trader, int year, int value) {this.trader = trader;this.year = year;this.value = value;}public Trader getTrader() {return trader;}public void setTrader(Trader trader) {this.trader = trader;}public int getYear() {return year;}public void setYear(int year) {this.year = year;}public int getValue() {return value;}public void setValue(int value) {this.value = value;}@Overridepublic String toString() {return "Transaction{" +"trader=" + trader +", year=" + year +", value=" + value +'}';}
}

(3)、实现相应的需求

1.找出2011年发生的所有交易,并按交易额排序(从高到底)
2.交易员都在哪些不同的城市工作过?
3.查找来自剑桥的交易员,并按姓名排序
4.返回所有交易员的姓名字符串,并按字母顺序排序
5.有没有交易员是在米兰工作的?
6.打印生活在剑桥的交易员的所有交易额
7.所有交易中,最高的交易额是多少?
8.找到交易额最小的交易

package com.Stream;import org.junit.Before;
import org.junit.Test;
import java.util.*;
import java.util.stream.Collectors;/*** @Description: //TODO streamAPI 练习* @Author: LL* @Date: 2019/9/25*/
public class TestTransaction {List<Transaction> transactions = null;@Beforepublic void before(){Trader raoul = new Trader("Raoul","Cambridge");Trader mario = new Trader("Mario","Milan");Trader alan = new Trader("Alan","Cambridge");Trader brian = new Trader("Brian","Cambridge");transactions = Arrays.asList(new Transaction(brian,2011,300),new Transaction(raoul,2012,1000),new Transaction(raoul,2011,400),new Transaction(mario,2012,710),new Transaction(mario,2012,700),new Transaction(alan,2012,950));}//1.找出2011年发生的所有交易,并按交易额排序(从高到底)@Testpublic void test1(){transactions.stream().filter(e -> e.getYear()==2011).sorted((x, y) -> Integer.compare(x.getValue(), y.getValue()))
//                .sorted(Comparator.comparingInt(Transaction::getValue)).forEach(System.out::println);}//2.交易员都在哪些不同的城市工作过?@Testpublic void test2(){transactions.stream().map(x -> x.getTrader().getCity()).distinct().forEach(System.out::println);}//3.查找来自剑桥的交易员,并按姓名排序@Testpublic void test3(){transactions.stream().filter(t->"Cambridge".equals(t.getTrader().getCity())).map(Transaction::getTrader).sorted(Comparator.comparing(Trader::getName)).distinct().forEach(System.out::println);}//4.返回所有交易员的姓名字符串,并按字母顺序排序@Testpublic void test4(){transactions.stream().map(t -> t.getTrader().getName()).distinct().sorted().forEach(System.out::println);System.out.println("-------------------------------------");String s = transactions.stream().map(t -> t.getTrader().getName()).distinct().sorted().collect(Collectors.joining());System.out.println(s);System.out.println("-------------------------------------");String s2 = transactions.stream().map(t -> t.getTrader().getName()).distinct().sorted().reduce("",String::concat);System.out.println(s2);}//5.有没有交易员是在米兰工作的?@Testpublic void test5(){boolean b = transactions.stream().anyMatch(x -> x.getTrader().getCity().equals("Milan"));System.out.println(b);}//6.打印生活在剑桥的交易员的所有交易额@Testpublic void test6(){Optional<Integer> sum = transactions.stream().filter(t -> t.getTrader().getCity().equals("Cambridge")).map(Transaction::getValue).reduce(Integer::sum);System.out.println(sum.get());System.out.println("---------------------------------------");Integer sum2 = transactions.stream().filter(t -> t.getTrader().getCity().equals("Cambridge")).map(Transaction::getValue).mapToInt(t -> t).sum();
//                .collect(Collectors.summingInt(t -> t));System.out.println(sum2);}//7.所有交易中,最高的交易额是多少?@Testpublic void test7(){OptionalInt max = transactions.stream().map(Transaction::getValue).mapToInt(t -> t).max();System.out.println(max.getAsInt());System.out.println("-----------------------");Optional<Integer> max1 = transactions.stream().map(Transaction::getValue).max(Integer::compare);System.out.println(max1.get());}//8.找到交易额最小的交易@Testpublic void test8(){OptionalInt min = transactions.stream().map(Transaction::getValue).mapToInt(t -> t).min();transactions.stream().filter(t -> t.getValue() <= min.getAsInt()).forEach(System.out::println);System.out.println("---------------------");Optional<Transaction> min1 = transactions.stream().min(Comparator.comparingInt(Transaction::getValue));
//                .min(Comparator.comparingInt(x -> x.getValue()));
//                .min((x,y) -> Integer.compare(x.getValue(),y.getValue()));System.out.println(min1.get());}
}


 

  相关解决方案