Java8新增的Stream + Lambda = !!!起飞,谁用谁知道!

什么是Stream?

Stream将要处理的元素集合看作一种流,在流的过程中,借助Stream API对流中的元素进行操作,比如:筛选、排序、聚合等。

Stream可以由数组或集合创建,对流的操作分为两种:

  1. 中间操作,每次返回一个新的流,可以有多个。
  2. 终端操作,每个流只能进行一次终端操作,终端操作结束后流无法再次使用。终端操作会产生一个新的集合或值。

另外,Stream有几个特性:

  1. stream不存储数据,而是按照特定的规则对数据进行计算,一般会输出结果。
  2. stream不会改变数据源,通常情况下会产生一个新的集合或一个值。

Stream的创建

public class BuildStream {

    public static void main(String[] args) {

        List<Integer> list = Arrays.asList(1, 2, 3);
// 通过集合的stream()方法创建顺序流
Stream<Integer> stream1 = list.stream(); // 通过集合的parallelStream()方法创建顺序流
Stream<Integer> parallelStream1 = list.parallelStream(); // 通过parallel()将顺序流转化为并行流
Stream<Integer> parallelStream2 = list.stream().parallel(); int[] arr = {1, 2, 3};
// 通过数组创建流
IntStream stream2 = Arrays.stream(arr); // 通过Stream的静态方法创建流
Stream<Integer> stream3 = Stream.of(1, 2, 3);
Stream<Integer> stream4 = Stream.iterate(1, x -> x + 1).limit(3); stream1.forEach(x -> System.out.print(x + " "));
System.out.println(); // 1 2 3 parallelStream1.forEach(x -> System.out.print(x + " "));
System.out.println(); // 随机
}
}
  • stream是顺序流,由主线程按顺序对流执行操作。
  • parallelStream是并行流,内部以多线程并行执行的方式对流进行操作,但前提流中的数据处理没有顺序要求。并行流能充分利用cpu优势,在数据量足够大的时候,加快处理速度。

测试API

新建测试数据

@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class Book { Long id;
String title;
String author;
Integer pageCount;
Double price;
}
public class TestStream {

    List<Book> bookList = new ArrayList<>();

    @Before
public void init() {
bookList.add(Book.builder().author("天乔巴夏").id(1L).title("Java-Spring").pageCount(100).price(50d).build());
bookList.add(Book.builder().author("summerday").id(2L).title("Java-SpringBoot").pageCount(200).price(100d).build());
bookList.add(Book.builder().author("hyh").id(3L).title("mysql").pageCount(500).price(150d).build());
bookList.add(Book.builder().author("tqbx").id(4L).title("Linux").pageCount(30).price(10d).build());
}
}

findFirst、findAny

        // 匹配第一个
Optional<Book> first = bookList.stream().filter(book -> book.getPageCount() > 100).findFirst();
first.ifPresent(book -> System.out.println("匹配第一个值 : " + book)); // 匹配任意
Optional<Book> any = bookList.parallelStream().filter(book -> book.getPageCount() > 100).findAny();
any.ifPresent(book -> System.out.println("匹配任意的值 : " + book));

anyMatch、noneMatch

        // 是否包含符合条件的书
boolean anyMatch = bookList.stream().anyMatch(book -> book.getPageCount() > 100);
System.out.println("是否存在页数大于100的书 : " + anyMatch); // 检查是否有名字长度大于5 的
boolean noneMatch = bookList.stream().noneMatch(book -> (book.getTitle().length() > 5));
System.out.println("不存在title长度大于5的书 : " + noneMatch);

filter

        // 找到所有id为奇数的书,列出他们的书名到list中
List<String> titleList = bookList.stream()
.filter(book -> book.getId() % 2 == 1)
.map(Book::getTitle)
.collect(Collectors.toList());
System.out.println(titleList);

max、count

        // 获取页数最多的书
Optional<Book> max = bookList.stream().max(Comparator.comparingInt(Book::getPageCount));
max.ifPresent(book -> System.out.println("页数最多的书 : " + book));
// 计算mysql书籍有几本
long count = bookList.stream().filter(book -> book.getTitle().contains("mysql")).count();
System.out.println("mysql书籍的本数 : " + count);

peek、map

        // 将所有的书的价格调高100并输出调高以后的书单
List<Book> result = bookList.stream().peek(book -> book.setPrice(book.getPrice() + 100))
.collect(Collectors.toList());
result.forEach(System.out::println);
// 获取所有书的id列表
List<Long> ids = bookList.stream().map(Book::getId).collect(Collectors.toList());
System.out.println(ids);

reduce

        // 求所有书籍的页数之和
Integer totalPageCount = bookList.stream().reduce(0, (s, book) -> s += book.getPageCount(), Integer::sum);
System.out.println("所有书籍的页数之和 : " + totalPageCount);

collect

        // 将所有书籍存入 author -> title 的map中
Map<String, String> map = bookList.stream().collect(Collectors.toMap(Book::getAuthor, Book::getTitle));
// 取出所有id为偶数的书,存入list
List<Book> list = bookList.stream().filter(book -> book.getId() % 2 == 0).collect(Collectors.toList());
// 取出所有标题长度大于5的书,存入list
Set<Book> set = bookList.stream().filter(book -> book.getTitle().length() > 5).collect(Collectors.toSet());

count、averaging、summarizing、max、sum

        // 统计书籍总数
Long bookCount = bookList.stream().filter(book -> "天乔巴夏".equals(book.getAuthor())).count(); // 求平均价格
Double average = bookList.stream().collect(Collectors.averagingDouble(Book::getPrice)); // 求最贵价格
Optional<Integer> max = bookList.stream().map(Book::getPageCount).max(Double::compare); // 求价格之和
Integer priceCount = bookList.stream().mapToInt(Book::getPageCount).sum(); // 一次性统计所有信息
DoubleSummaryStatistics c = bookList.stream().collect(Collectors.summarizingDouble(Book::getPrice));

group

        // 按书的价格是否高于100分组
Map<Boolean, List<Book>> part = bookList.stream().collect(Collectors.partitioningBy(book -> book.getPrice() > 100)); for (Map.Entry<Boolean, List<Book>> entry : part.entrySet()) {
if (entry.getKey().equals(Boolean.TRUE)) {
System.out.println("price > 100 ==> " + entry.getValue());
} else {
System.out.println("price <= 100 <== " + entry.getValue());
}
} // 按页数分组
Map<Integer, List<Book>> group = bookList.stream().collect(Collectors.groupingBy(Book::getPageCount));
System.out.println(group);

join

        // 获取所有书名
String titles = bookList.stream().map(Book::getTitle).collect(Collectors.joining(","));
System.out.println("所有书名 : " + titles);

sort

        // 按价格升序
List<Book> sortListByPrice = bookList.stream().sorted(Comparator.comparing(Book::getPrice)).collect(Collectors.toList());
System.out.println(sortListByPrice);
// 按价格降序
List<Book> sortListByPriceReversed = bookList.stream().sorted(Comparator.comparing(Book::getPrice).reversed()).collect(Collectors.toList());
System.out.println(sortListByPriceReversed); // 先价格再页数
List<Book> sortListByPriceAndPageCount = bookList.stream().sorted(Comparator.comparing(Book::getPrice)
.thenComparing(Book::getPageCount)).collect(Collectors.toList());
System.out.println(sortListByPriceAndPageCount);

distinct、concat、limit、skip

        Stream<Integer> stream1 = Stream.of(1, 2, 2, 3, 4);
Stream<Integer> stream2 = Stream.of(2, 3, 4, 5, 5);
// 合并
List<Integer> concatList = Stream.concat(stream1, stream2).collect(Collectors.toList());
System.out.println(concatList); // 去重
List<Integer> distinctList = concatList.stream().distinct().collect(Collectors.toList());
System.out.println(distinctList); // 限制
List<Integer> limitList = distinctList.stream().limit(3).collect(Collectors.toList());
System.out.println(limitList); // 跳过
List<Integer> skipList = limitList.stream().skip(1).collect(Collectors.toList());
System.out.println(skipList); // 迭代
List<Integer> iterateList = Stream.iterate(1, x -> x + 2).limit(10).collect(Collectors.toList());
System.out.println(iterateList); // 生成
List<Integer> generateList = Stream.generate(() -> new Random().nextInt()).limit(5).collect(Collectors.toList());
System.out.println(generateList);

参考阅读

Java8的StreamAPI常用方法总结的更多相关文章

  1. 使用java8的StreamAPI对集合计算进行代码重构

    方法: 查询出所有部门成员中年龄大于30的员工姓名 部门对象: 员工对象: 模拟数据: private static List<Dept> list=new ArrayList<De ...

  2. java8中stream常用方法详解

    map: 用作类型转换 如把集合里面的字符串转为大写,或者一个对象的集合取几个字段转为新的对象集合filter: 过滤 符合条件的集合元素保存下来,不符合条件的去掉flatMap:合并集合,比如Lis ...

  3. Java8新增的这些集合骚操作,你掌握了嘛?

    目录 Iterable的forEach Iterator的forEachRemaining Collection的removeIf Stream操作 List的replaceAll List的sort ...

  4. java8 Stream的实现原理 (从零开始实现一个stream流)

    1.Stream 流的介绍 1.1 java8 stream介绍 java8新增了stream流的特性,能够让用户以函数式的方式.更为简单的操纵集合等数据结构,并实现了用户无感知的并行计算. 1.2  ...

  5. Java8新特性——StreamAPI(二)

    1. 收集器简介 收集器用来将经过筛选.映射的流进行最后的整理,可以使得最后的结果以不同的形式展现. collect方法即为收集器,它接收Collector接口的实现作为具体收集器的收集方法. Col ...

  6. Java8新特性——StreamAPI(一)

    1. 流的基本概念 1.1 什么是流? 流是Java8引入的全新概念,它用来处理集合中的数据,暂且可以把它理解为一种高级集合. 众所周知,集合操作非常麻烦,若要对集合进行筛选.投影,需要写大量的代码, ...

  7. Java8新特性——StreamAPI 的使用

    StreamAPI的说明 Java8中有两大最为重要的改变.第一个是 Lambda 表达式:另外一个则是 Stream API. Stream API ( java.util.stream) 把真正的 ...

  8. java8 Stream常用方法和特性浅析

    有一个需求,每次需要将几万条数据从数据库中取出,并根据某些规则,逐条进行业务处理,原本准备批量进行for循环或者使用存储过程,但是for循环对于几万条数据来说效率较低:存储过程因为逻辑非常复杂,写起来 ...

  9. java8的stream功能及常用方法

    Java8中stream对集合操作做了简化,用stream操作集合能极大程度简化代码.Stream 就如同一个迭代器(Iterator),单向,不可往复,数据只能遍历一次,遍历过一次后就用尽了. 一. ...

随机推荐

  1. [LeetCode题解]86. 分隔链表 | 三指针 + 虚拟头节点

    解题思路 三指针,一个指向前半部分待插入位置,一个指向后半部分待插入位置,最后一个从前往后遍历 代码 /** * Definition for singly-linked list. * public ...

  2. 精尽MyBatis源码分析 - MyBatis初始化(二)之加载Mapper接口与XML映射文件

    该系列文档是本人在学习 Mybatis 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释(Mybatis源码分析 GitHub 地址.Mybatis-Spring 源码分析 GitHub ...

  3. python-Requests模块的使用

    1. Requests简介 Requests模块是一个用于网络访问的模块,其实类似的模块有很多,比如urllib,urllib2,httplib,httplib2,他们基本都提供相似的功能,那为什么R ...

  4. 使用Camtasia制作蒙面唱将揭面视频

    要说之前的<蒙面唱将猜猜猜>还是属于比较火的歌唱综艺节目了.这档歌唱类型的综艺节目的精彩点不在于歌唱的水平,而在于猜想的环节.演唱时,嘉宾们都会蒙上面具,直到被评委猜中时才会揭开面具. 我 ...

  5. AWS CodePipeline部署Maven项目至EC2

    背景 AWS CodePipeline 是一种持续性的集成与交付服务,可以实现快速而可靠的应用程序和基础设施更新.根据您定义的发布流程模型,只要代码发生变更,CodePipeline 便会生成.测试和 ...

  6. vulnhub: DC 3

    通过nmap扫描,只开放了80端口,并且该web服务是基于Joomla搭建: root@kali:~# nmap -A 192.168.74.140 Starting Nmap 7.80 ( http ...

  7. 一篇文章彻底搞懂Java的大Class到底是什么

    作者在之前工作中,面试过很多求职者,发现有很多面试者对Java的 Class 搞不明白,理解的不到位,一知半解,一到用的时候,就不太会用. 因为自己本身以前刚学安卓的时候,甚至做安卓2,3年后,也是对 ...

  8. B 站今日黑白页是怎么实现的?

    今天是2020年4月4日哀悼活动,不少相关站点都将网站全部变为灰色,以表示哀悼.以下为CSS代码.直接在*.css文件最前面加入. <!-- 置为灰色 --> <style type ...

  9. 推荐系统实践 0x09 基于图的模型

    用户行为数据的二分图表示 用户的购买行为很容易可以用二分图(二部图)来表示.并且利用图的算法进行推荐.基于邻域的模型也可以成为基于图的模型,因为基于邻域的模型都是基于图的模型的简单情况.我们可以用二元 ...

  10. BloomFilte布隆过滤器简介

    专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt+moviepy音视频剪辑实战 专栏:PyQt入门学习 老猿Python博文目录 老猿学5G博文目录 一. ...