Java8新特性-Stream API
一、Stream简介
1.1 Stream API说明
- Stream API(java.util.stream)把真正的函数式编程风格引入到Java中,提供了简单高效的操作
- Stream 是Java8中处理集合的关键抽象概念,它可以指定对集合进行操作,可以执行非常复杂的查找、过滤和映射数据等操作。使用Stream API对集合数据进行操作,就类似于使用SQL执行的数据库查询。也可以使用Stream API来并行执行操作
1.2 什么是Stream
Stream是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列。集合存储数据,Stream是对集合元素进行计算
- Stream本省并不存储元素
- Stream不会改变源对象,会返回一个持有结果的新Stream
- Stream是延迟执行的,只有等到需要结果的时候才执行
1.3 Stream操作步骤
创建Stream
一个数据源(如:集合、数组)获取一个流
中间操作
一个中间操作链,可以进行多种操作,对数据源的数据进行处理
终止操作
一旦执行终止操作,就执行中间操作链,并产生结果,之后,创建的流将不能再被使用,如果使用,需要重新创建一个新的流
二、Stream使用
2.1 创建执行流
集合创建执行流
List<User> userList = User.getUserList();
//创建顺序流
Stream<User> userStream = userList.stream();
//创建并行流 中间操作可以并行执行
Stream<User> userParallelStream = userList.parallelStream();
Collection接口中实现了默认的stream和parallelStream方法,所以Collection的实现类可以直接调用这两个方法
通过数组创建执行流
int[] intArr = {
1,2,3,4,5,6};
IntStream intStream = Arrays.stream(intArr);
int[] longArr = {
1,2,3,4,5,6};
IntStream longStream = Arrays.stream(longArr);
double[] doubleArr = {
1.1,2.2,3.3};
DoubleStream stream = Arrays.stream(doubleArr);
User[] userArr = {
new User(1,"zhangsan",25),new User(2,"lisi",26)};
Stream<User> userStream = Arrays.stream(userArr);
Arrays工具类中提供了静态的stream方法实现,其中基本类型int、long、double的数组返回的是对应与基本类型的执行流
通过Stream的of方法创建
Stream<Integer> integerStream = Stream.of(1, 2, 3, 4, 5, 6);
Stream<Boolean> booleanStream = Stream.of(true, false);
Stream<Float> floatStream = Stream.of(1.1f, 2.2f, 3.3f);
通过of方法创建基本数据类型的执行流时,返回的基本类型对应的包装类型的执行流
通过Stream的iterate()和generate()创建无限流
Stream.iterate(0,t -> t+2).limit(10).forEach(System.out::println);
Stream.generate(Math::random).limit(10).forEach(System.out::println);
iterate是通过迭代的方式一直生成数据,其中第一个参数为起始值,后面的lambda表达式为具体的迭代逻辑,如果没有通过后面的limit方法限制,则会一直迭代下去
generate是通过重复调用lambda表达式来生成数据,如果不加limit限制,也会一直调用里面的lambda表达式
2.2 Stream的中间操作
Stream的中间操作可以连接起来形成一个调用链(流水线),只有流水线执行了终止操作,中间操作才会执行,否则中间操作不会做任何处理,而是在终止操作时一次性处理,这种方式称为“惰性求值”
筛选与切片
//过滤出年龄大于25的用户,filter的参数是Predicate函数接口的实现
List<User> userList = User.getUserList();
userList.stream().filter(user -> user.getAge() >25).forEach(System.out::println);
//限制集合元素的数量,只输出三个用户
List<User> userList = User.getUserList();
userList.stream().limit(3).forEach(System.out::println);
//跳过前面指令数量的集合元素,例子中为跳过前两个
List<User> userList = User.getUserList();
userList.stream().skip(2).forEach(System.out::println);
//distinct去重,通过流所生成元素的hashCode()和equals()去除重复元素
List<User> userListDistinct = new ArrayList<User>(){
{
new User(1,"lizhi",23);
new User(1,"lizhi",23);
new User(1,"lizhi",23);
}
};
userListDistinct.stream().distinct().forEach(System.out::println);
如果Stream流已经执行过了终止操作,再次调用该流的Stream API将会导致异常:java.lang.IllegalStateException: stream has already been operated upon or closed
映射
//通过映射原有Stream的元素映射成新的元素构成的Stream
List<String> list = Arrays.asList("aa","bb","cc");
list.stream().map(String::toUpperCase).forEach(System.out::println);
//将user实体集合映射成user的name集合
List<User> userList = User.getUserList();
Stream<String> nameStream = userList.stream().map(User::getName);
nameStream.filter(name -> name.startsWith("li")).forEach(System.out::println);
//flatmap接收一个函数作为参数,将流中的每个值都映射成另一个流,然后将所有流合并成一个流
Stream<Character> characterStream = list.stream().flatMap(StreamOperateTest::stringFormat);
characterStream.forEach(System.out::println);
/** 原始写法 */
Stream<Stream<Character>> streamStream = list.stream().map(StreamOperateTest::stringFormat);
streamStream.forEach(stream -> stream.forEach(System.out::println));
public static Stream<Character> stringFormat(String string){
List<Character> list = new ArrayList<>(8);
for (Character c: string.toCharArray()) {
list.add(c);
}
return list.stream();
}
映射将原有的Stream流通过映射关系转换成一个新的Stream流
排序
//默认排序
List<Integer> integerList = Arrays.asList(12, 95, 32, 2, 95, -2, 35);
integerList.stream().sorted().forEach(System.out::println);
//自定义排序
List<User> userList = User.getUserList();
userList.stream().sorted(Comparator.comparingInt(User::getAge)).forEach(System.out::println);
2.3 终止操作
查找与匹配
//检查是否匹配所有元素
List<User> userList = User.getUserList();
boolean allMatch = userList.stream().allMatch(user -> user.getAge() > 24);
//检查是否匹配任何一个元素
boolean anyMatch = userList.stream().anyMatch(user -> user.getAge() > 25);
//检查是否没有匹配的元素
boolean noneMatch = userList.stream().noneMatch(user -> user.getAge() > 25);
//查找第一个元素
Optional<User> firstUser = userList.stream().findFirst();
//查找任意一个元素
Optional<User> anyUser = userList.stream().findAny();
//统计流中元素个数
long count = userList.stream().count();
//统计流中最大值 如果比较的用户最大年龄有多个时,则任意返回一个
Optional<User> maxUser = userList.stream().max(Comparator.comparing(User::getAge));
归约
//将流中元素反复结合起来,得到一个值
//计算集合中元素的和 第一个参数为起始值,也参与运算
List<Integer> integerList = Arrays.asList(5, 6, 8, 22, 72, 365, 85);
Integer reduce = integerList.stream().reduce(0, Integer::sum);
//不需要初始值反复运算,通过map将User流变成age流
Optional<Integer> allAge = userList.stream().map(User::getAge).reduce(Integer::sum);
收集
//将操作后的数据收集到一个集合中
List<User> userList = User.getUserList();
List<User> collect = userList.stream().filter(user ->
user.getAge() > 25).collect(Collectors.toList());
Set<User> userSet = userList.stream().filter(user ->
user.getName().startsWith("zhu")).collect(Collectors.toSet());
还没有评论,来说两句吧...