Stream:不同于IO流,Stream流是数据渠道,用于操作数据源(集合/数组)所生成的元素序列
三大特性:
1.Stream 不会存储元素
2.Stream 不会改变源对象,相反,会返回一个持有结果的新Stream
3.Stream 操作是延时的,遇到终止操作才会一次性全部执行
1.流的创建
//创建 @Test public void test1() { //1.Collection系列集合提供的stream()串行流 或 paralleStream()并行流 List<String> list = new ArrayList<>(); Stream<String> stream1 = list.stream(); //2.Arrays中静态方法Stream()获取数组流 Employee[] employees = new Employee[10]; Stream<Employee> stream2 = Arrays.stream(employees); //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); //5. Stream.generate(() -> Math.random()) .forEach(System.out::println); }
2.流的操作
@Test public void test2() { //filter employees.stream().filter((e) -> e.getAge() > 18).forEach((employee -> System.out.println(employee))); System.out.println("=========================================================="); Stream<Employee> stream = employees.stream() .filter((e) -> { System.out.println("这里是中间操作!"); return e.getAge() > 19; }); //终止操作:一次性执行全部 stream.forEach(System.out::println); // employees.stream().filter((e) -> e.getAge() > 25).forEach(System.out::println); } @Test public void test3() { //找到匹配条件的 不会继续迭代 类似 && || employees.stream() .filter((e -> { System.out.println("短路"); return e.getSalary() > 5000; })) .limit(1) .forEach(e -> System.out.println(e)); } @Test public void test4() { //distinct 通过hashCode() 和 equals去重 //要想达到效果,需要重写employee中的hashCode方法或者equals方法 employees.stream() .filter((e -> { // System.out.println("短路"); return e.getSalary() > 5000; })) .distinct() .forEach(e -> System.out.println(e)); } @Test public void test5() { // distinct employees.stream() .filter((e -> { // System.out.println("短路"); return e.getSalary() > 5000; })) .skip(2) .forEach(e -> System.out.println(e)); } /** * 映射: * map:接收Lambda,将元素转换成其他形式或提取信息。接收一个函数作为参数,该函数会被应用到每个参数上,并将其映射成一个新的元素 * flatMap:接收一个函数作为参数,将流中的每一个值都转换成另一个流,然后把所有的流连接成一个流 */ @Test public void test6() { List<String> list = Arrays.asList("aaa", "bbb", "ccc", "ddd", "eee"); list.stream() //从"aaa", "bbb", "ccc", "ddd", "eee"提取出每一个元素 将map中的函数应用于每一个参数上 .map(str -> str.toUpperCase()) .forEach(System.out::println); System.out.println("-------------------------------"); employees.stream() //对employee集合中的每一参数 都做employee.getName()操作 .map(employee -> employee.getName()) .forEach(System.out::println); }
@Test public void test7() { List<String> list = Arrays.asList("aaa", "bbb", "ccc", "ddd", "eee"); Stream<Stream<Character>> stream = list.stream() .map(TestStream1::filterCharacter); stream.forEach(sm->sm.forEach(System.out::println)); System.out.println("---------------------------------------------"); Stream<Character> characterStream = list.stream().flatMap(TestStream1::filterCharacter); characterStream.forEach(System.out::println); } public static Stream<Character> filterCharacter(String str) { List list = new ArrayList(); //Character -> char的包装类型 for (Character ch : str.toCharArray()) { list.add(ch); } return list.stream(); }
@Test public void test8() { //sort employees.stream() .sorted((e1, e2) -> { if (e1.getAge() == e2.getAge()) { //年龄相同按照姓名排序 return e1.getName().compareTo(e2.getName()); }else { return ((Integer)e1.getAge()).compareTo((Integer)e2.getAge()); } }).forEach(System.out::println); }
@Test /** * 查找于匹配 * */ public void test1() { //需求:找出salary最低的员工 Optional<Double> op = employees.stream() .map(Employee::getSalary) .min(Double::compareTo); System.out.println(op.get()); } /** * 归约 * reduce:将流中的元素反复结合起来,得到一个值 */ @Test public void test2() { List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); Integer reduce1 = list.stream() //reduce 第一个参数 起始值,即将0赋给x 1赋给y 运算后将结果1赋给x 如此循环 .reduce(0, (x, y) -> x + y); System.out.println(reduce1); System.out.println("---------------------------------------------"); //计算salary总和 Optional<Double> reduce2 = employees.stream().map(Employee::getSalary) .reduce(Double::sum); // .reduce((x, y) -> x + y); System.out.println(reduce2.get()); } //collect:将流转换为其他形式,接收一个Collection接口的实现,用于给Stream中元素做汇总 @Test //把员工名收集 public void test3() { List<String> list1 = employees.stream() .map(Employee::getName) .collect(Collectors.toList()); list1.forEach(System.out::println); System.out.println("------------------------------------"); //可以收集到set集合中去重 Set<String> list2 = employees.stream() .map(Employee::getName) .collect(Collectors.toSet()); list2.forEach(System.out::println); System.out.println("------------------------------------"); HashSet<String> hashSet = employees.stream() .map(Employee::getName) .collect(Collectors.toCollection(HashSet::new)); hashSet.forEach(System.out::println); } @Test public void test4() { //返回集合总数 Long num = employees.stream().collect(Collectors.counting()); System.out.println(num); System.out.println("---------------------"); System.out.println(employees.stream().count()); System.out.println("---------------------"); //平均值 System.out.println(employees.stream() .collect(Collectors.averagingDouble(Employee::getSalary))); } @Test public void test5() { //总和 System.out.println(employees.stream().collect(Collectors.summingDouble(Employee::getSalary))); //工资最大值员工 System.out.println(employees.stream().collect(Collectors.maxBy((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary())))); //最小值 System.out.println(employees.stream() .map(Employee::getSalary) // .map(e -> e.getSalary()) .collect(Collectors.minBy(Double::compare))); }
//分组操作 @Test public void test6() { //根据Status分组 Map<Status, List<Employee>> collect1 = employees.stream() .collect(Collectors.groupingBy(Employee::getStatus)); } //收集一个组函数对象 之后可以做分组处理 @Test public void test7() { //根据Status分组 DoubleSummaryStatistics dss = employees.stream() .collect(Collectors.summarizingDouble(Employee::getSalary)); System.out.println(dss.getAverage());//8000.0 System.out.println(dss.getCount());//7 System.out.println(dss.getMax());//11000.0 } //将收集的所有内容连接 @Test public void test8() { //根据Status分组 String s = employees.stream() .map(Employee::getName) .collect(Collectors.joining(",","===","===")); System.out.println(s);//===Mike,Yan,Lee,Rose,Sk,Sk,Sk=== }