java8(三)Stream API
文章目录
- Stream API
- Stream和Collection的区别
- Stream操作的三个步骤
- 创建Stream
- 方法一:通过集合创建
- 方法二:通过数组创建
- 通过Stream类的静态方法 of创建
- 方式四:无限流
- 中间操作
- 筛选与切片
- 映射
- 排序
- 终止操作
- 匹配与查找
- 归约
- 收集
Stream API
Stream API – > java.util.stream
Stream是java8中处理集合的关键抽象概念
可以执行非常复杂的查找、过滤和映射数据等操作
类似于使用SQL执行的数据库查询
Stream API提供了一种高效且易于使用的数据处理方式
Stream和Collection的区别
Collection是一种静态的内存数据,主要面向内存,存储在内存中
Stream与计算有关,主要面向CPU,通过CPU实现计算
注意:
- Stream 自己不会存储元素
- Stream 不会改变源对象。会返回一个持有结果的新Stream
- Stream 操作时延迟执行的,需要结果的时候才执行
Stream操作的三个步骤
- 创建Stream
使用一个数据源(如:集合、数组),获取一个Stream流 - 中间操作(过滤、映射…)
中间操作链,对数据源进行数据加工处理 - 终止操作(终端操作)
一点执行终止操作,就执行中间操作链,并返回结果。之后,不会再被使用
创建Stream
方法一:通过集合创建
- 顺序流:按照集合中的顺序进行执行
// default Stream<E> stream();
List<Employee> employees = EmployeeData.getEmployees();
Stream<Employee> stream = employees.stream();
- 并行流
// default Stream<E> parallelStream()
List<Employee> employees = EmployeeData.getEmployees();
Stream<Employee> parallelStream = employees.parallelStream();
方法二:通过数组创建
// Arrays static <T> Stream<T> stream(T[] array)
Employee[] empArr = employees.toArray(new Employee[employees.size()]);
Stream<Employee> stream1 = Arrays.stream(empArr);
int[] iArr = {1,2,3};
IntStream intStream = Arrays.stream(iArr);
通过Stream类的静态方法 of创建
// static<T> Stream<T> of(T... values);
Stream<String> stringStream = Stream.of("1", "2", "3", "4");
Stream<Integer> integerStream = Stream.of(1, 2, 3, 4, 5);
方式四:无限流
- 迭代:
public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f)
- 生成:
public static<T> Stream<T> generate(Supplier<T> s)
Stream.iterate(0, t -> t + 2).limit(10).forEach(System.out::println);
Stream.generate(Math::random).limit(10).forEach(System.out::println);
中间操作
多个中间操作可以链接起形成一条链,除非链上触发终止操作,否则中间操作不会执行任何处理,只有在终止操作时一次性全部处理,称为惰性求值
筛选与切片
方法 | 描述 |
---|---|
filter(Predicate p) | 接收Lambda,从流中排出某些元素 |
distinct() |
筛选,通过流所生成元素的hashCode() 和equals() 去除重复元素
|
limit(long maxSize) | 截断流,使元素不超过给定数量 |
skip(long n) |
跳过元素,返回一个扔掉了前n个元素的流。若流中元素不足n个,则返回一个空流。与limit(long maxSize) 互补
|
// filter(Predicate p) 接收Lambda,从流中排出某些元素
List<Employee> list = EmployeeData.getEmployees();
Stream<Employee> stream = list.stream();
// 查询员工薪资大于90000
stream.filter(e -> e.getSalary() > 90000).forEach(System.out::println);
System.out.println("******************************************************");
stream = list.stream();
// limit(long maxSize) 截断流,使元素不超过给定数量
stream.limit(3).forEach(System.out::println);
System.out.println("******************************************************");
// skip(long n) 跳过元素,返回一个扔掉了前n个元素的流。若流中元素不足n个,则返回一个空流。与 limit(long maxSize) 互补
list.stream().skip(5).forEach(System.out::println);
System.out.println("******************************************************");
// distinct() 筛选,通过流所生成元素的 hashCode() 和 equals() 去除重复元素
list.add(new Employee(1009, "扎克伯格1", 28, 3422.34));
list.add(new Employee(1009, "扎克伯格1", 28, 3422.34));
list.add(new Employee(1009, "扎克伯格1", 28, 3422.34));
list.stream().distinct().forEach(System.out::println);
映射
方法 | 描述 |
---|---|
map(Function f) | 接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新元素 |
mapToDouble(ToDoubleFunction f) | 接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的DoubleStream |
mapToInt(ToIntFunction f) | 接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的IntStream |
mapToLong(ToLongFunction f) | 接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的LongStream |
flatMap(Function f) | 接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流 |
// 中间操作:映射
@Test
public void test3() {// map(Function f) 接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新元素List<String> list = Arrays.asList(new String[]{"tom", "jerry"});list.stream().map(str -> str.toUpperCase()).forEach(System.out::println);List<Employee> employeeList = EmployeeData.getEmployees();employeeList.stream().map(Employee::getName).filter(name -> name.length() > 3).forEach(System.out::println);System.out.println("########################################S");// flatMap(Function f) 接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流list.stream().map(StreamAPITest::stringToStream).forEach(s -> {s.forEach(System.out::println);});System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");list.stream().flatMap(StreamAPITest::stringToStream).forEach(System.out::println);
}public static Stream<Character> stringToStream(String str) {List<Character> list = new ArrayList<>();for (char c : str.toCharArray()) {list.add(c);}return list.stream();
}
排序
方法 | 描述 |
---|---|
sorted() | 自然排序 |
sorted(Comparator com) | 按比较强顺序排序 |
// sorted() 自然排序
List<Integer> intList = Arrays.asList(2, 6, 2, 1, 7, 12, 45, 67);
intList.stream().sorted().forEach(System.out::println);
System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");// sorted(Comparator com) 按比较强顺序排序
List<Employee> list = EmployeeData.getEmployees();
list.stream().sorted((e1, e2) -> Integer.compare(e1.getAge(), e2.getAge())).forEach(System.out::println);
终止操作
会使流产生结果,其中的结果可以是任何不是流的值,如:List,Integer,void。流进行终止操作后,不能再次使用。
匹配与查找
方法 | 描述 |
---|---|
allMatch(Predicate p) | 检查是否匹配到所有元素 |
anyMatch(Predicate p) | 检查是否匹配到至少一个元素 |
noneMatch(Predicate p) | 检查是否没有匹配到所有元素 |
findFirst() | 返回第一个元素 |
findAny() | 返回当前流中的任意元素 |
count() | 返回流中元素总数 |
max(Comparator c) | 返回流中最大值 |
min(Comparator c) | 返回流中最小值 |
forEach(Consumer c) | 内部迭代 ,使用Collection接口需要yoghurt去做的迭代叫外部迭代,StreamAPI使用内部迭代。也可以用Collection.forEach(Consumer c)做迭代 |
// 匹配与查找
@Test
public void test1() {// | allMatch(Predicate p) | 检查是否匹配到所有元素 |List<Employee> list = EmployeeData.getEmployees();boolean b = list.stream().allMatch(e -> e.getAge() >= 30);System.out.println(b);System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");// | anyMatch(Predicate p) | 检查是否匹配到至少一个元素 |boolean b1 = list.stream().anyMatch(e -> e.getSalary() > 50000);System.out.println(b1);System.out.println("####################################################");// | noneMatch(Predicate p) | 检查是否没有匹配到所有元素 |boolean b2 = list.stream().noneMatch(e -> e.getName().contains("马"));System.out.println(b2);System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@S");// | findFirst() | 返回第一个元素 |Optional<Employee> firstEmployee = list.stream().sorted((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary())).findFirst();System.out.println(firstEmployee);System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");// | findAny() | 返回当前流中的任意元素 |Optional<Employee> anyEmployee = list.parallelStream().findAny();System.out.println(anyEmployee);System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");// | count() | 返回流中元素总数 |long count = list.stream().count();System.out.println(count);System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");// | max(Comparator c) | 返回流中最大值 | 注意,比较方法写反了,取得最小值// Optional<Employee> max = list.stream().max((e1, e2) -> Double.compare(e2.getSalary(), e1.getSalary()));Optional<Employee> max = list.stream().max((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()));System.out.println("max:" + max);Optional<Double> maxSalary = list.stream().map(Employee::getSalary).max(Double::compare);System.out.println("maxSalary:" + maxSalary);System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");// | min(Comparator c) | 返回流中最小值 |Optional<Employee> min = list.stream().min((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()));System.out.println(min);System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");// | forEach(Consumer c) | 内部迭代 |list.stream().forEach(System.out::println);
}
归约
方法 | 描述 |
---|---|
reduce(T iden, BunaryOperator b) | 可以将流中元素反复结合起来,得到一个值。返回T |
reduce(BinaryOperator b) | 将流中元素反复结合,得到一个值。返回Optional<T> |
**备注:**map和reduce的连接通常称为map-reduce模式,因Google用它来进行网络搜索而出名
// 归约
@Test
public void test3() {// | reduce(T iden, BunaryOperator b) | 可以将流中元素反复结合起来,得到一个值。返回T |List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);Integer reduce = list.stream().reduce(0, Integer::sum);System.out.println(reduce);// | reduce(BinaryOperator b) | 将流中元素反复结合,得到一个值。返回Optional\<T> |List<Employee> employeeList = EmployeeData.getEmployees();Optional<Double> reduce1 = employeeList.stream().map(Employee::getSalary).reduce(Double::sum);System.out.println(reduce1);
}
收集
方法 | 描述 |
---|---|
collect(Collector c) | 将流转换为其他形式。接收一个Collector接口的实现 |
Collector接口中方法的实现决定了如何对流执行收集操作(如收集到List、Set、Map)
Collectors实现类提供了很多的静态方法,可以方便地创建常见收集器实例,方法见下表:
方法 | 返回类型 | 作用 | 示例 |
---|---|---|---|
toList | List<T> | 把流中元素收集到List | list.stream().collect(Collectors.toList()) |
toSet | Set<T> | 把流中元素收集到Set | list.stream().collect(Collectors.toSet()) |
toCollection | Collection<T> | 把流中元素收集到创建的集合 | list.stream().collect(Collectors.toCollection(ArrayList::new)) |
counting | Long | 计算流中元素个数 | list.stream().collect(Collectors.counting()) |
summingInt | Integer | 对流中元素整数属性进行求和 | list.stream().collect(Collectors.summingInt(Employee::getSalary)) |
averagingInt | Integer | 对流中Integer属性求平均值 | list.stream().collect(Collectors.averagingInt(Employee::getAge)) |
summarizingInt | IntSummaryStatics | 收集流中Integer属性的统计值。如平均值 | list.stream().collect(Collectors.summarizingInt(Employee::getAge)) |
joining | String | 连接流中每个字符串 | list.stream().collect(Collectors.joining()) |
maxBy | Optional<T> | 根据比较器获取最大值 | list.stream().collect(Collectors.maxBy(Employee::getSalary)) |
minBy | Optional<T> | 根据比较器获取最小值 | list.stream().collect(Collectors.minBy(Employee::getSalary)) |
reducing | 归约产生的类型 | 从一个作为累加器的初始值开始,利用BinaryOperator与流中元素逐个结合,从而归约成单个值 | list.stream().collect(Collectors.reducing(0, Employee::getSalary, Integer::sum)) |
collectIngAndThen | 转换函数返回的类型 | 包裹另一个收集器,对其结果转换函数 | list.stream().collect(Collectors.collectIngAndThen(Collectors.toList(), List::size)) |
groupingBy | Map<k, List<T>> | 根据某属性值对流分组,属性为K,结果为V | list.stream().collect(Collectors.groupingBy(Employee::getStatus) |
partitioningBy | Map<Boolean, List<T>> | 根据true或false进行分区 | list.stream().collect(Collectors.partitioningBy(Employee::getManage) |
// 收集
@Test
public void test4() {// | collect(Collector c) | 将流转换为其他形式。接收一个Collector接口的实现 |List<Employee> list = EmployeeData.getEmployees();List<Employee> collect = list.stream().filter(e -> e.getSalary() > 200000).collect(Collectors.toList());System.out.println(collect);System.out.println();// | toSet | Set\<T> | 把流中元素收集到Set| list.stream().collect(Collectors.toSet()) |Set<Employee> collect1 = list.stream().filter(e -> e.getSalary() > 200000).collect(Collectors.toSet());System.out.println(collect1);System.out.println();// | toCollection | Collection\<T> | 把流中元素收集到创建的集合| list.stream().collect(Collectors.toCollection(ArrayList::new)) |ArrayDeque<Employee> collect2 = list.stream().filter(e -> e.getSalary() > 200000).collect(Collectors.toCollection(ArrayDeque::new));System.out.println(collect2);System.out.println();// | counting | Long | 计算流中元素个数 | list.stream().collect(Collectors.counting()) |Long collect3 = list.stream().collect(Collectors.counting());System.out.println(collect3);// | summingInt | Integer | 对流中元素整数属性进行求和|list.stream().collect(Collectors.summingInt(Employee::getSalary)) |Integer collect4 = list.stream().collect(Collectors.summingInt(Employee::getAge));System.out.println(collect4);IntSummaryStatistics collect5 = list.stream().collect(Collectors.summarizingInt(Employee::getAge));System.out.println("collect5:" + collect5);}
java8(三)Stream API相关推荐
- 【Java8新特性】关于Java8的Stream API,看这一篇就够了!!
写在前面 Java8中有两大最为重要的改变.第一个是 Lambda 表达式:另外一个则是 Stream API(java.util.stream.*) ,那什么是Stream API呢?Java8中 ...
- Java8的Stream API使用(笔记)
个人转载仅作为笔记使用,如有任何问题可以到原文链接探讨,原文连接为:https://www.cnblogs.com/jimoer/p/10995574.html 前言 这次想介绍一下Java Stre ...
- Java8的Stream API使用
前言 这次想介绍一下Java Stream的API使用,最近在做一个新的项目,然后终于可以从老项目的祖传代码坑里跳出来了.项目用公司自己的框架搭建完成后,我就想着把JDK版本也升级一下吧(之前的项目, ...
- java8之Stream API(提取子流和组合流)
为什么80%的码农都做不了架构师?>>> Stream.limit(n)会返回一个包含n个元素的新流(如果原始流的长度小于n,则会返回原始的流).例如: package jav ...
- java8三次分组_Java8分组(groupingBy)
1.分组,计数,排序 public class Java8Example1 { public static void main(String[] args) { List items = Arrays ...
- Java8 Lambda表达式(三)Lambda表达式与Stream API
目录 1 Stream基本概念 1.1 什么是Stream 1.2 Stream的特点 2 Stream API初体验 2.1 构造数据 2.1 使用for循环实现 2.2 使用Lambda表达式结合 ...
- java8新特性-lambda表达式和stream API的简单使用
一.为什么使用lambda Lambda 是一个 匿名函数,我们可以把 Lambda表达式理解为是 一段可以传递的代码(将代码像数据一样进行传递).可以写出更简洁.更灵活的代码.作为一种更紧凑的代码风 ...
- 学习笔记之-java8的新特性-函数式接口,lambda表达式,方法引用,Stream API,Optional类
1.Lambda表达式 用匿名内部类的方法去创建多线程1.new Thread2.参数传递new Runnable3.重写run方法4.在run方法中去设置线程任务5.调用start问题:我们最终目标 ...
- 【java8新特性】——Stream API详解(二)
一.简介 java8新添加了一个特性:流Stream.Stream让开发者能够以一种声明的方式处理数据源(集合.数组等),它专注于对数据源进行各种高效的聚合操作(aggregate operation ...
最新文章
- 软件行业项目经理主要的职责是什么?(转)
- python人工智能入门书籍推荐-小编就给大家推荐几本python机器学习入门书!
- JSP标准标签库JSTL总结
- 当adobe flash player不能安装时
- cocos ScrollView(滚动容器)加载大量item导致的卡顿问题解决方案
- 用户画像_什么是“用户画像”?如何利用用户画像进行精准营销?
- 日志服务与SIEM(如Splunk)集成方案实战 1
- SSH中设置字符编码防止乱码
- 芯片测试探针卡_测试接口业者先受惠苹果A14 GPU双雄4Q再加Socket、探针卡急单
- 新征程 linux下C编程
- 大觉寺到鹫峰线路_大觉寺到鹫峰怎么走
- 解决php截取文字乱码问题
- GAX (Guidance Automation Extensions) 与 GAT (Guidance Automation Toolkit)
- Android源码编译 首发ViVo Xplay X510w 2.14.8 完美root/美颜相机/状态栏美化/支持官方OTA/纯净,稳定ROM
- FreeBSD搭建Nginx+Apache24+php56+mysql56手把手一步步的笔记
- (十)损失函数与反向传播
- QT的QScrollArea使用详解
- 使用mysqldump+WinRAR压缩备份数据库
- Who is the lion(谁是狮子)!
- 【C++】9.GIS应用:开源GIS平台开发入门(MapServer+QGIS+PostGIS+OpenLayers)