JDK8 Stream流

流通常是有三个部分组成

  1. 数据源:流的获取,比如list.stream()方法;

  2. 中间处理:中间处理是对流元素的一系列处理。比如过滤filter,排序sorted,映射map

  3. 终端处理:终端处理会生成结果,结果可以是任何不是流值。生成List,可用collect(Collectors.toList()),生成Map可用collect(Collectors.toMap()) 也可以不返回结果,如stream.forEach(System.out::println)就是将结果打印到控制台中,并没有返回。

中间操作符

流方法描述
filterfilter函数接收一个Lambda表达式作为参数,该表达式返回 boolean,在执行过程中,流将元素逐一输送给filter,并筛选出执行结果为 true 的元素;
distinct对流元素去重
limit截取流的前N个元素
skip跳过流的前n个元素,截取流后面的元素
map对流中的每个元素执行一个函数,使得元素转换成另一种类型输出。流会将每一个元素输送给map函数,并执行map中的Lambda表达式,最后将执行结果存入一个新的流中。 如:将 list 中每一个 Integer类型元素自增后转化为 String类型/对流元素加前缀/后缀等
flatMap对流进行偏平化
sorted排序, 默认按照ascii, 也可以传入自定义排序规则

终止操作符

流方法描述
anyMatch是否匹配任一元素anyMatch用于判断流中是否存在至少一个元素满足指定的条件,这个判断条件通过Lambda表达式传递给anyMatch,执行结果为boolean类型。
allMatch是否匹配所有元素
noneMatch是否未匹配所有元素
findAny获取任一元素(Stream()得到的是第一个元素/parallelStream()是随机获取)
findFirst获取第一个元素findAny从流中随机选出 一个元素出来,它返回一个Optional类型的元素。
forEach遍历流
collect流转换
reduce将流中的元素进行合并,形成一个新的值,常见的归约操作包括求和等运算, 求最大值或最小值。
count将流中的元素个数返回

Optional 对象介绍

Optional是Java8新加入的一个容器,这个容器只存1个或0个元素,它用于防止出现NullpointException,它提供如下方法:

isPresent() 判断容器中是否有值。 ifPresent(Consume lambda) 容器若不为空则执行括号中的Lambda表达式。 T get() 获取容器中的元素,若容器为空则抛出NoSuchElement异常。 T orElse(T other) 获取容器中的元素,若容器为空则返回括号中的默认值。

流转换

数值流的使用

采用Stream 的 redure 方法 进行数值归约操作会涉及到基本数值类型和引用数值类型之间的装箱、拆箱操作,因此效率较低; 此时最好是将当流操作为纯数值操作时,这样使用数值流能获得较高的效率;

  • StreamAPI提供了三种数值流:IntStream、DoubleStream、LongStream;

1) 将 Stream 转换成数值流 StreamAPI 提供了将普通流转换成数值流的三种方法:mapToInt、mapToDouble、mapToLong(参数:相应的转化Lambda表达式);

将数值流转化为Stream 的方法:boxed;

List<Double> list = Arrays.asList(2.3,2.4,2.5,2.7,2.8);
 
//普通Stream转为数值Stream
DoubleStream doubles = list.stream().mapToDouble(x->x);    //转化为DoubleStream
IntStream ints = list.stream().mapToInt(x->Integer.parseInt(String.format("%.0f",x))); //转化为IntStream,同时进行取舍操作
 
//数值Stream转为普通Stream
Stream stream = list.boxed();

2)数值流的数值计算

每种数值流都提供了数值计算函数,如max、min、sum、avg等。

List<Integer> list = Arrays.asList(1,2,3,4,5,6,7);
 
OptionalInt max = list.stream().max();
int max_value = max.orElse(0);
OptionalInt sum = list.steam().sum();
iny sum_value = sum.orElse(0);

Stream 可以通过 Collector 收集器,将其转化为 Array,Collection,Map,String;

//普通转换
Stream<String> stream = Stream.of("are","you","ok");
String[] array = stream().toArray();
 
//涉及拆箱、装箱操作的转换
Stream<Integer> stream = Stream.of(1,2,3,4,5,6);
int[] array = stream.mapToInt(x->x).toArray();
Integer[] array = stream.toArray(Integer[]::new);
 
//将 List<Inetegr> 转化为 String[]
List<Integer> list = Arrays.asList(1,2,3,4,5);
String[] array = list.stream().map(String::valueOf).toArray(String[]::new);
​
// 转换为list集合
List<Integer> list1 = stream.collect(Collectors.toList());
List<Integer> list2 = stream.collect(Collectors.toCollection(ArrayList::new));
​
// 转换为Set集合
Set<Integer> set = stream.collect(Collectors.toCollection(Set::new));
​
// 转换为栈
Stack<Integer> stack = stream.collect(Collectors.toCollection(Stack::new));
​
// 转换为map
//使用val的hashcode为key,val本身为value
Map<Integer, String> map = Stream.of("are","you","ok").collect(Collectors.toMap( s -> s.hashCode(), s -> s));
// 使用val的hashcode为key,val本身为value,如果key的value重复,则使用新的value
Map<Integer, String> map = Stream.of("are","you","ok").collect(Collectors.toMap( s -> s.hashCode(), s -> s,(oldval,newval)->newval));
​
//将 List 转化为使用 “,” 分隔的字符串
List<Integer> list = Arrays.asList(1,2,3,4,5,6,7);
String str = list.stream().map(x->x.toString()).collect(Collectors.joining(","));
System.out.println(str);
//输出: 1,2,3,4,5,6,7

过滤和排序

Stream.of(1, 8, 5, 2, 1, 0, 9, 2, 0, 4, 8)
    .filter(n -> n > 2)     // 对元素过滤,保留大于2的元素
    .distinct()             // 去重,类似于SQL语句中的DISTINCT
    .skip(1)                // 跳过前面1个元素
    .limit(2)               // 返回开头2个元素,类似于SQL语句中的SELECT TOP
    .sorted()               // 对结果排序
    .forEach(System.out::println);
​
    //filter后剩下:8,5,9,4,8
    //去重后排序剩下:5,9

of()方法的底层是 Array.Stream()

查找和匹配

Stream中提供的查找方法有anyMatch()、allMatch()、noneMatch()、findFirst()、findAny(), 这些方法被用来查找或匹配某些元素是否符合给定的条件:

  boolean  hasMatch = Stream.of("Java", "C#", "PHP", "C++", "Python")
                .anyMatch(s -> s.equals("Java"));
    // hasMatch:true
  boolean hasAllMatch = Stream.of("Java", "C#", "PHP", "C++", "Python")
        .allMatch(s -> s.contains("#"));
        //hasAllMatch:false
   Optional<String> element = Stream.of("Java", "C#", "PHP", "C++", "Python")
        .filter(s -> s.contains("C"))
        // .findFirst()     // 查找第一个元素
        .findAny();         // 查找任意元素
        //element:Optional[C#]

实际上测试结果发现,findFirst()findAny()返回的都是第一个元素,两者之间到底有没什么区别呢

因为Stream()是串行,调用findAny()都会获取第一个

而parallelStream()是并行,调用findAny()会随机获得

归约

归约操作就是将流中的元素进行合并,形成一个新的值,常见的归约操作包括求和等运算, 求最大值或最小值。归约操作一般使用reduce()方法, 与map()方法搭配使用,可以处理一些很复杂的归约操作。

​
      List<Book> books =Arrays.asList(
            new Book("Java编程思想", "Bruce Eckel", "机械工业出版社", 108.00D),
            new Book("Java 8实战", "Mario Fusco", "人民邮电出版社", 79.00D),
            new Book("MongoDB权威指南(第2版)", "Kristina Chodorow", "人民邮电出版社", 69.00D)
      );
      // 计算所有图书的总价
      Optional<Double> totalPrice = books.stream()
                                          .map(Book::getPrice)
                                          .reduce((n, m) -> n + m);
      // 价格最高的图书
      Optional<Book> expensive = books.stream().max(Comparator.comparing(Book::getPrice));
      // 价格最低的图书
      Optional<Book> cheapest = books.stream().min(Comparator.comparing(Book::getPrice));
      // 计算总数
      long count = books.stream().count();

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值