1、简介

     Java 8是Java自Java 5(发布于2004年)之后的最重要的版本。这个版本包含语言、编译器、库、工具和JVM等方面的十多个新特性。在本文中我们一起来学习引入的一个新特性-流

2、Lambda表达式

    在学习流之前,我们先来了解下java8中引入的Lambda表达式,它作为流很重要的一部分。Lambda表达式个构成如下所示:

2.1  有效的Lambda表达式

()-> 42

(Apple a) -> { return a.getWeight() > 150; }

 //对于函数只有一行代码的,可以去掉大括号{}以及return关键字
(String s)-> s.length() (Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight())

2.2  方法引用

     当你需要使用方法引用时,目标放在分隔符::前,方法的名称放在后面。例如:Apple::getWeight就是引用了Apple类中定义的方法getWeight。请记住,不需要括号,因为你

没有实际调用这个方法。方法引用就是Lambda表达式(Apple a) -> a.getWeight的快捷写法。

Lambda及其等效方法引用的列子:

方法引用主要有三类:

  • 指向静态方法的方法引用(例如Integer的parseInt方法,写作Integer::parseInt)
  • 指向任意类型实例方法的方法引用(例如String的length方法,写作String::length)
  • 指向现有对象的实例方法的方法引用(假设你有一个局部变量expensiveTransaction用于存放Transaction类型的对象,它支持实例方法getValue,那么你就可以写成expensiveTransaction::getValue)

第二种和第三种方法引用可能乍看起来有点儿晕。类似于String::length的第二种方法引用的思想就是你在引用一个对象的方法,而这个对象本身是Lambda的一个参数。例如,Lambda表达

式(String s) ->
s.toUppeCase()可以写作String::toUpperCase。但第三种方法引用指的是,你在Lambda中调用一个已经存在的外部对象中的方法。例如,Lambda表达式()->expensiveTransaction.getValue()可

以写作expensiveTransaction::getValue。

2.3  构造函数引用

Supplier<Apple> c1 = Apple::new;     // 构造函数引用指向默认的Apple()构造函数
Apple apple = c1.get(); // 调用Supplier的get方法将产生一个新的Apple Function<Integer, Apple> c2 = Apple::new; // 指向Apple(Integer weight)的构造函数引用
Apple apple2 = c2.apply(110); // 调用该Function函数的apply方法,并给出要求的重量,将产生一个Apple

在下面的代码中,一个Integer构成的List中的每个元素都通过我们前面定义的类的map方法传递给了Apple的构造函数,得到了一个具有不同重量苹果的List:

private static void test() {
List<Integer> weights = Arrays.asList(7, 3, 4, 10);
List<Apple> apples = map(weights, Apple::new);
apples.stream().map(Apple::getWeight).forEach(System.out::println);
} public static List<Apple> map(List<Integer> list, Function<Integer, Apple> f) {
List<Apple> result = new ArrayList<>();
for (Integer e : list) {
result.add(f.apply(e));
}
  return result;
}

  3、引入流

     3.1流简介

     流是一系列数据项,一次只生成一项。程序可以从输入流中一个一个读取数据项,然后以同样的方式将数据项写入输出流。一个程序的输出流很可能是另一个程序的输入流。就想汽车组装流水线一

  样,汽车排队进入加工站,每个加工站会接收、修改汽车,然后将之传递给下一站做进一步的处理。尽管流水线实际上是一个序列,但不同加工站的运行一般是并行的。

   基于此,Java8可以透明的把输入的不想管部分拿到几个CPU内核上去分别执行你的Stream操作流水线——这是几乎免费的并行,用不着费劲搞Thread了。

3.2流操作

            流操作包含3个部分:数据源、中间操作、终端操作

  数据源:集合、数组

      中间操作:可以连接起来的流操作,流程一条流水线

      终端操作:关闭流的操作

    

    中间操作和终端操作,如下图所示:

    

3.3 使用流

        筛选和切片:filter()、distinct()、limit()、skip()

映射:map()

     查找和匹配:anyMatch()、allMatch()、noneMatch()、findAny()、findFirst()

     归约:reduce()

   3.3.1 筛选和切片

              filter():筛选过滤。会接受一个谓词(一个返回boolean的函数)作为参数,并返回一个包括所有符合谓词的元素的流。

    distinct():去重。它会返回一个元素各异(根据流所生成元素的hashCode和equals方法实现)的流

    limit(n):截断。它会返回一个不超过给定长度的流,如果流是有序的,则最多返回前n个元素

    skip(n):跳过。返回一个扔掉了前n个元素的流

List<Integer> numbers = Arrays.asList(1, 2, 1, 3, 3, 2, 4,5, 6);
numbers.stream()
.filter(i -> i % 2 == 0) //筛选出能被2整除的
.distinct() //去重
.limit(3) //取前3个元素
.skip(1) //扔掉第一个元素
.forEach(System.out::println);

  3.3.2 映射

    map():映射。它会接受一个函数作为参数。这个函数会被应用到每个元素上,并将其映射成一个新的元素

    例如,下面的代码,提取菜单中菜的名字

List<String> nameList = menu.stream()
  .map(Dish::getName)
  .collect(Collectors.toList())

  3.3.4 查找和匹配

    anyMatch():流中是否有一个元素能匹配给定的谓词

List<Integer> numbers = Arrays.asList(6, 5, 4, 8, 1, 2, 3, 4, 2, 5, 6, 8, 10);
numbers.stream().anyMatch(d -> d % 3 == 0) ; //true

    allMatch():流中的元素是否都能匹配给定的谓词

numbers.stream().allMatch(d -> d % 3 == 0);      //false

    noneMatch():与allMatch()相对,流中没有任何元素与给定的谓词匹配

numbers.stream().noneMatch(d -> d % 7 == 0);       //true

    findAny():返回当前流中的任意元素。不过该方法返回的是Optional<T>容器类,其方法包括

          1、isPresent() 将在Optional包含值的时候返回true,否者返回false

          2、T get() 会在值存在时返回值,否则抛出一个NoSuchElement异常

Optional<Integer> nums = numbers.stream().filter(d -> d % 4 == 0).findAny();
nums.isPresent(); //true
nums.get(); //

    findFirst():找到第一个元素,工作方式类似于findAny()

  3.3.5 归约

    把一个流中的元素组合起来,使用reduce操作来表达更复杂的查询,比如“计算菜单中的总卡路里”或“菜单中卡路里最高的菜是哪一个”。此类查询需要将流中所有元素反复结合起来,得

  到一个值,比如一个Integer。这样的查询可以被归类为归约操作(将流归约成一个值)

    元素累加、累乘

List<Integer> numbers = Arrays.asList(4, 5, 3, 9);

//有初始值:
numbers.stream().reduce(0, (a, b) -> a + b); //21
numbers.stream().reduce(0, Integer::sum); //21
numbers.stream().reduce(1, (a, b) -> a * b); //540 //无初始值:
Optional<Integer> sum = numbers.stream().reduce((a, b) -> (a + b));
//对于无初始值的归约,reduce操作无法返回其和,只能将结果包裹在一个Optional对象里,以表明可能不存在
sum.get(); //

    最大值、最小值

List<Integer> numbers = Arrays.asList(4, 5, 3, 9);

Optional<Integer> max = numbers.stream().reduce(Integer::max);    //最大值
max.get(); //9 Optional<Integer> min = numbers.stream().reduce(Integer::min); //最小值
min.get(); //

  求和、平均数

int total = menu.stream().collect(Collectors.summingInt(Dish::getCalories));     //统计总数
double avg = menu.stream().collect(Collectors.averagingInt(Dish::getCalories)); // 求平均数
long count = menu.stream().count(); //个数 IntSummaryStatistics summ = menu.stream().collect(Collectors.summarizingInt(Dish::getCalories)); summ.getAverage(); //平均数
summ.getCount(); //个数
summ.getMax(); //最大值
summ.getMin(); //最小值
summ.getSum(); //和

 3.4 用流收集数据

  收集器(collect):是一个将数据流缩减为一个值的高级归约操作,这个值可以是集合、映射、或者一个值对象。你可以使用collect达到以下目的:

    1、将数据流缩减为一个单一值

    2、将一个数据流中的元素进行分组

    3、分割一个流中的元素

public List<String> getList(List<Task> tasks) {        //将数据收集进一个列表
return tasks.stream().map(Task::getTitle).collect(Collectors.toList());
}
public Set<String> getSet(List<Task> tasks) { //将数据收集进一个集合
return tasks.stream().map(Task::getTitle).collect(Collectors.toSet());
}
private static Map<String, Task> taskMap(List<Task> tasks) { //将数据收集进一个映射
return tasks.stream().collect(Collectors.toMap(Task::getTitle, task -> task));
}
private static Map<TaskType, List<Task>> groupTasksByType(List<Task> tasks) { //分组
return tasks.stream().collect(Collectors.groupingBy(Task::getType));
}

其它参照资源:http://blog.csdn.net/u013291394/article/details/52662761

Java8新特性--流(Stream)的更多相关文章

  1. 乐字节-Java8新特性之Stream流(上)

    上一篇文章,小乐给大家介绍了<Java8新特性之方法引用>,下面接下来小乐将会给大家介绍Java8新特性之Stream,称之为流,本篇文章为上半部分. 1.什么是流? Java Se中对于 ...

  2. 【Java8新特性】- Stream流

    Java8新特性 - Stream流的应用 生命不息,写作不止 继续踏上学习之路,学之分享笔记 总有一天我也能像各位大佬一样 一个有梦有戏的人 @怒放吧德德 分享学习心得,欢迎指正,大家一起学习成长! ...

  3. Java8 新特性之Stream API

    1. Stream 概述 Stream 是Java8中处理集合的关键抽象概念,可以对集合执行非常复杂的查找,过滤和映射数据等操作; 使用 Stream API 对集合数据进行操作,就类似于使用 SQL ...

  4. 【Java8新特性】Stream API有哪些中间操作?看完你也可以吊打面试官!!

    写在前面 在上一篇<[Java8新特性]面试官问我:Java8中创建Stream流有哪几种方式?>中,一名读者去面试被面试官暴虐!归根结底,那哥儿们还是对Java8的新特性不是很了解呀!那 ...

  5. java8新特性之stream流

    Stream 流是 Java 8 提供给开发者一套新的处理集合的API,他把我们将要处理的集合作为流,就像流水线一样,我们可以对其中的元素进行筛选,过滤,排序等中间操作,只不过这种操作更加简洁高效. ...

  6. Java8新特性之Stream流(含具体案例)

    一.概述   Stream 流是 Java 8 新提供给开发者的一组操作集合的 API,将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选.排序.聚合等.元素 ...

  7. java8 新特性入门 stream/lambda

    Java 8 中的 Stream 是对集合(Collection)对象功能的增强,它专注于对集合对象进行各种非常便利.高效的聚合操作(aggregate operation),或者大批量数据操作 (b ...

  8. Java8 新特性 Lambda & Stream API

    目录 Lambda & Stream API 1 Lambda表达式 1.1 为什么要使用lambda表达式 1.2 Lambda表达式语法 1.3 函数式接口 1.3.1 什么是函数式接口? ...

  9. 【Java8新特性】Stream(分类+案例)

    一.Stream概述 什么是Stream? Stream是Java8引入的全新概念,它用来处理集合中的数据,可以让你以一种声明的方式处理数据. Stream 使用一种类似用 SQL 语句从数据库查询数 ...

随机推荐

  1. python——回文函数(reversed)

    回文数:正向排列与反向排列所得结果是相等的(即从左到右和从右到左的结果是相等的),例如:“123321”,“0000”等. reversed函数:反转一个序列对象,将其元素从后向前颠倒构建成一个新的迭 ...

  2. Windows10 家庭版添加【本地组策略编辑器】

    Windows10 家庭版默认没有[本地组策略编辑器],添加方法: 新建记事本复制以下内容 @echo off pushd "%~dp0" dir /b C:\Windows\se ...

  3. wpf expender 展开动画

    非原创,网上下载的,觉得还可以,记录一下以便以后查看学习 <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2 ...

  4. The service definition selected is invalid

    吐槽下 最近在学Java 听闻Java生态很好 社区很多 但实际操作起来确实另一番风景 不多说了 说正事 添加WebService服务Client时有密码认证得服务 Eclipse抛出 The ser ...

  5. 在MUI框架中使用video.js插件,并在暂停的时候利用Asp.net将观看时长保存到sqlserver数据库

    本次保存数据的情况有三种: 在视频播放的时候点击暂停,将本视频的进度保存到数据库 利用mui内部的控件,返回上一页操作时,进行保存 安卓手机触发返回键的时候,进行保存 示例一: 在video标签上面添 ...

  6. Android Source 源码已下载但 Android Studio 找不到的解决办法

    Android Studio 2.1 reporting in: solved the issue by resetting SDK. Preferences -> Appearance &am ...

  7. ASP.NET Core获取客户端IP地址

    1.在ConfigureServices注入IHttpContextAccessor // ASP.NET Core 2.1的注入方式 //services.AddHttpContextAccesso ...

  8. java入门——第一个java程序

    来源:https://course.tianmaying.com/java-basic%2Bjava-hello-world# java的基础特征 1 Java是一种大小写敏感的语言 2 程序的文件名 ...

  9. AGC002F Leftmost Ball

    题目传送门 Description \(n\)种颜色的球,每种\(k\)个,\((n,k\leq 2000)\)将\(n\cdot k\)个球排成一排,把每种颜色最左边的那个涂成白色(初始不含白色), ...

  10. jzoj5913

    這道題我們可以套路的設置f[i]為當前節點為根的滿足條件方案數,然後枚舉根,計算必須包含當前根的方案 但是似乎很難計算 所以我們可以搞一個前綴和,將聯通塊的最大數和最小數相減<=k的方案和< ...