
Java8新特性——Stream API
发布日期:2021-05-08 01:13:48
浏览次数:21
分类:精选文章
本文共 14375 字,大约阅读时间需要 47 分钟。
1、stream API——相识
Stream是元素的集合,这点让Stream看起来有些类似Iterator;可以支持顺序和并行的对原Stream进行汇聚的操作。
大家可以把Stream当成一个高级版本的Iterator。原始版本的Iterator,用户只能一个一个的遍历元素并对其执行某些操作;高版本的Stream,用户只要给出需要对其包含的元素执行什么操作,比如:“过滤掉长度大于10的字符串”、“获取每个字符串的首字母”等,这些操作如何应用到每个元素上,就给Stream就好了!
2、Stream API——创建、中间操作、终止操作(终端操作)
创建:一个数据源(如:集合、数组),获取一个流。
// 创建Stream @Test public void fun1(){// 1.可以通过Collection系列集合提供的stream()串行流或parallelStream()并行流 Listlist = new ArrayList<>(); Stream stream1 = list.stream();// 2.通过Arrays中的静态方法stream()获得数组流 Employee [] emps = new Employee[10]; Stream stream2 = Arrays.stream(emps);// 3.通过Stream类中的静态方法of() Stream stream3 = Stream.of("aa","bb","cc");// 4.创建无限流// (1)迭代 Stream stream4 = Stream.iterate(0, (x) -> x + 2); stream4.limit(10) .forEach(System.out::println);// (2)生成 Stream.generate(() -> Math.random()) .limit(5) .forEach(System.out::println); }
中间操作:一个中间操作链,对数据源的数据进行处理。
(1)、筛选与切片
// 中间操作 /* 筛选和切片 filter——接收Lambda,从流中排除某些元素。 limit——截断流,使其元素不超过给定数量。 skip(n)——跳过元素,返回一个扔掉了前n个元素的流,若流中元素不足n个时,则返回一个空流,与limit互补 distinct——筛选,通过流所生成元素的HashCode()和equals()去除重复元素 */Listemployees = Arrays.asList( new Employee("张三",18,9999.99), new Employee("张三",18,9999.99), new Employee("张三",18,9999.99), new Employee("张三",18,9999.99), new Employee("张三",18,9999.99), new Employee("张三",18,9999.99), new Employee("李四",18,8888.88), new Employee("王五",100,1.11), new Employee("赵六",80,2.22), new Employee("田七",20,9898.98) ); /*内部迭代:迭代操作由Stream API完成*/ @Test public void fun2(){// 中间操作:不会执行任何操作 Stream stream = employees.stream() .filter((e) -> { System.out.println("Stream API的中间操作"); System.out.println("没有终止操作的话,中间操作不执行。"); return e.getAge() > 35; });// 终止操作:一次性执行全部内容,即惰性求值 stream.forEach(System.out::println); } /*外部迭代*/ @Test public void fun3(){ Iterator iterator = employees.iterator(); while (iterator.hasNext()){ System.out.println(iterator.next()); } } @Test public void fun4(){ employees.stream() .filter((e) -> { System.out.println("短路!"); //&& || return e.getSalary() >5000; }) .limit(2) .forEach(System.out::println); } @Test public void fun5(){ employees.stream() .filter((e) -> e.getSalary()>5000) .skip(2) .forEach(System.out::println); } @Test public void fun6(){ employees.stream() .filter((e) -> e.getSalary()>5000) .distinct() .forEach(System.out::println); }
package Lambda.LambdaCase;public class Employee { private String name; private Integer age; private Double salary; public Employee() { } public Employee(Integer age) { this.name = name; } public Employee(String name, Integer age) { this.name = name; this.age = age; } public Employee(String name, Integer 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 Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public Double getSalary() { return salary; } public void setSalary(Double salary) { this.salary = salary; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Employee employee = (Employee) o; if (!name.equals(employee.name)) return false; if (!age.equals(employee.age)) return false; return salary.equals(employee.salary); } @Override public int hashCode() { int result = name.hashCode(); result = 31 * result + age.hashCode(); result = 31 * result + salary.hashCode(); return result; } @Override public String toString() { return "Employee{" + "name='" + name + '\'' + ", age=" + age + ", salary=" + salary + '}'; }}
(2).映射
/* 映射 map——接收lambda,将元素转换成其他形式或提取信息。 接收一个函数作为参数,该函数会应用到每个元素上,并将其映射成一个新的元素。 flagMap——接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流。 */ @Test public void fun7(){ Listlist = Arrays.asList("aaa","bbb","ccc","ddd","eee"); list.stream() .map((str) -> str.toUpperCase()) .forEach(System.out::println); System.out.println("------------我是分割线-------------"); employees.stream() .map(Employee::getName) .forEach(System.out::println); System.out.println("------------我是分割线-------------"); Stream > stream = list.stream() .map(GetUnlimitedFlow::filterCharacter);//{ {a,a,a},{b,b,b}} stream.forEach((sm) ->{ sm.forEach(System.out::println); }); System.out.println("------------我是分割线-------------"); Stream stream1 = list.stream() .flatMap(GetUnlimitedFlow::filterCharacter);//{a,a,a,b,b,b} stream1.forEach(System.out::println); } /*解析字符串,将字符串中的字符一个个打印出来*/ public static Stream filterCharacter(String str){//add(Object obj) addAll(Collection coll) ArrayList list = new ArrayList<>(); for (Character ch:str.toCharArray()) { list.add(ch); } return list.stream(); } @Test public void fun8(){ List list = Arrays.asList("aaa", "bbb", "ccc", "ddd", "eee"); ArrayList list1 = new ArrayList(); list1.add(11); list1.add(33);// list1.add(list);// System.out.println(list1); list1.addAll(list); System.out.println(list1); }
(3).排序
/* 排序 sorted()——自然排序(Comparable) sorted(Comparator com)——定制排序(Comparater) */ @Test public void fun9(){ Listlist = Arrays.asList("bbb", "ddd", "aaa", "eee", "ccc"); list.stream() .sorted() .forEach(System.out::println); System.out.println("------------我是分割线-------------"); employees.stream() .sorted((e1,e2) -> { if (e1.getAge().equals(e2.getAge())){ return e1.getName().compareTo(e2.getName()); }else { return -e1.getAge().compareTo(e2.getAge()); } }).forEach(System.out::println); }
终止操作:一个终止操作,执行中间操作链,并产生结果。
查找与匹配
Listemployees1 = Arrays.asList( new Employee("张三",18,9999.99, Employee.Status.BUSY), new Employee("李四",18,8888.88, Employee.Status.FREE), new Employee("王五",100,1.11, Employee.Status.VOCATION), new Employee("赵六",80,2.22, Employee.Status.FREE), new Employee("田七",20,9898.98, Employee.Status.BUSY) ); /* 查找与匹配 allMatch——检查是否匹配所有元素 anyMatch——检查是否至少匹配一个元素 noneMatch——检查是否没有匹配所有元素 findFirst——返回第一个元素 findAny——返回当前流中的任意元素 count——返回流中元素的总个数 max——返回流中最大值 min——返回流中最小值 */ @Test public void fun10(){ boolean b1 = employees1.stream() .allMatch((e) -> e.getStatus().equals(Employee.Status.BUSY)); System.out.println(b1); boolean b2 = employees1.stream() .anyMatch((e) -> e.getStatus().equals(Employee.Status.BUSY)); System.out.println(b2); boolean b3 = employees1.stream() .noneMatch((e) -> e.getStatus().equals(Employee.Status.BUSY)); System.out.println(b3); Optional op = employees1.stream() .sorted((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary())) .findFirst(); System.out.println(op.get()); Optional any = employees1.stream() .filter((e) -> e.getStatus().equals(Employee.Status.BUSY)) .findAny(); System.out.println(any.get()); } @Test public void fun11() { long count = employees1.stream() .count(); System.out.println(count); Optional max = employees1.stream() .max((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary())); System.out.println(max.get()); Optional min = employees1.stream() .map(Employee::getSalary) .min(Double::compare); System.out.println(min.get()); }
归约
/* 归约 reduce(T identity,BinaryOperator)/reduce(BinaryOperator) ——可以将流中元素反复结合起来,得到一个值 */ @Test public void fun12(){ Listlist = 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 reduce = employees1.stream() .map(Employee::getSalary) .reduce(Double::sum); System.out.println(reduce.get()); }
收集
/* 收集: collect——将流转换为其他形式,接收一个Collector接口的实现, 用于给Stream中元素做汇总的方法。 */ @Test public void fun13(){ Listlist = employees1.stream() .map(Employee::getName) .collect(Collectors.toList()); list.forEach(System.out::println); System.out.println("------------我是分割线-------------"); Set set = employees1.stream() .map(Employee::getName) .collect(Collectors.toSet()); set.forEach(System.out::println); System.out.println("------------我是分割线-------------"); HashSet hashSet = employees1.stream() .map(Employee::getSalary) .collect(Collectors.toCollection(HashSet::new)); hashSet.forEach(System.out::println); } @Test public void fun14(){// 总数 Long count = employees1.stream() .collect(Collectors.counting()); System.out.println(count); System.out.println("------------我是分割线-------------");// 平均值 Double avg = employees1.stream() .collect(Collectors.averagingDouble(Employee::getSalary)); System.out.println(avg); System.out.println("------------我是分割线-------------");// 总和 Double sum = employees1.stream() .collect(Collectors.summingDouble(Employee::getSalary)); System.out.println(sum); System.out.println("------------我是分割线-------------");// 最大值 Optional max = employees1.stream() .collect(Collectors.maxBy((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()))); System.out.println(max.get()); System.out.println("------------我是分割线-------------");// 最小值 Optional min = employees1.stream() .map(Employee::getSalary) .collect(Collectors.minBy(Double::compare)); System.out.println(min.get()); }
分组和多级分组
@Test public void fun15(){// 分组 Map> map = employees1.stream() .collect(Collectors.groupingBy(Employee::getStatus)); System.out.println(map); }// 多级分组 @Test public void fun16(){ Map >> mapMap = employees1.stream() .collect(Collectors.groupingBy(Employee::getStatus, Collectors.groupingBy((e) -> { if (e.getAge() < 5) { return "青年"; } else if (e.getAge() < 10) { return "中年"; } else { return "老年"; } }))); System.out.println(mapMap); }
分区
// 分区 @Test public void fun17(){ Map> partition = employees1.stream() .collect(Collectors.partitioningBy((e) -> e.getSalary() > 8000)); System.out.println(partition); }
汇总统计
// 汇总统计 @Test public void fun18(){ DoubleSummaryStatistics summary = employees1.stream() .collect(Collectors.summarizingDouble(Employee::getSalary)); System.out.println(summary); System.out.println(summary.getAverage()); System.out.println(summary.getCount()); System.out.println(summary.getMax()); System.out.println(summary.getMin()); System.out.println(summary.getSum()); }
字符串拼接
// 字符串拼接 @Test public void fun19(){ String join = employees1.stream() .map(Employee::getName) .collect(Collectors.joining(",","===","===")); System.out.println(join); }
package Steam;import Lambda.LambdaCase.Employee;import org.junit.Test;import java.util.Arrays;import java.util.List;import java.util.Optional;public class TestStreamAPI { /* 1、给定一个数字列表,如何返回一个由每个数的平方构成的列表呢? 给定【1,2,3,4,5】,应该返回【1,4,9,16,25】 */ @Test public void fun1(){ Integer [] arr = new Integer[]{1,2,3,4,5}; Arrays.stream(arr) .map((x) -> x*x) .forEach(System.out::println); } /* 2、怎样用map和reduce方法数一数流中有多少个Employee? */ Listemployees = Arrays.asList( new Employee("张三",18,9999.99, Employee.Status.BUSY), new Employee("李四",18,8888.88, Employee.Status.FREE), new Employee("王五",100,1.11, Employee.Status.VOCATION), new Employee("赵六",80,2.22, Employee.Status.FREE), new Employee("田七",20,9898.98, Employee.Status.BUSY) ); @Test public void fun2(){ Optional sum = employees.stream() .map((e) -> 1) .reduce(Integer::sum); System.out.println(sum.get()); }}
发表评论
最新留言
路过,博主的博客真漂亮。。
[***.116.15.85]2025年04月11日 23时10分20秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
新生儿不建议吃鱼肝油,这些你知道吗
2021-05-08
新生儿哭是因为什么
2021-05-08
Linux开发环境搭建关键的库文件搜索调用(静态库)
2021-05-08
css属性中的优先级
2021-05-08
不能读取变量的length属性
2021-05-08
html上传图片后,在页面显示上传的图片
2021-05-08
基础知识
2021-05-08
nodeName与tagName的区别
2021-05-08
(九)实现页面底部购物车的样式
2021-05-08
(十)实现购物车中的对商品的数量选择操作
2021-05-08
在vue中给对象扩展属性的方法
2021-05-08
hdu 4545: 魔法串 (动态规划)
2021-05-08
Neo4j : 通过节点的 id属性 对节点进行查,改,删操作
2021-05-08
whatis 显示nothing
2021-05-08
Linux标准错误和标准输出重定向到同一个文件
2021-05-08
CentOS6破解管理员root密码
2021-05-08
HTTP Status 404 – Not Found
2021-05-08
脚本安装MySQL 8.0
2021-05-08