# 函数方编程思想
# 概念
面向对象思想需要关注用什么对象完成什么事情,而函数式编程思想类似数学中的函数。主要关注运用函数完成对数据的操作
# 优点
- 代码简洁,快速开发
- 易于并发编程
# Lambda 表达式
Java Lambda 表达式的一个重要用法是简化某些匿名内部类( Anonymous Classes
)的写法。实际上 Lambda 表达式并不仅仅是匿名内部类的语法糖,JVM 内部是通过 invokedynamic 指令来实现 Lambda 表达式的。
Lambda 表达式并不能取代所有的匿名内部类,只能用来取代函数接口( Functional Interface
)的简写
能够使用 Lambda 的依据是必须有相应的函数接口(函数接口,是指内部只有一个抽象方法的接口)。这一点跟 Java 是强类型语言吻合,也就是说你并不能在代码的任何地方任性的写 Lambda 表达式。实际上 Lambda 的类型就是对应函数接口的类型。Lambda 表达式另一个依据是类型推断机制,在上下文信息足够的情况下,编译器可以推断出参数表的类型,而不需要显式指名。
例如:无参函数的简写
如果需要新建一个线程,一种常见的写法是这样:
new Thread(new Runnable(){// 接口名 | |
@Override | |
public void run(){// 方法名 | |
System.out.println("Thread run()"); | |
} | |
}).start(); |
简化为如下形式:
new Thread( | |
() -> System.out.println("Thread run()")// 省略接口名和方法名 | |
).start(); |
# stream 流
# 创建流
单列集合: 集合对象.stream()
List<Author>() authors = getAuthors(); | |
authors.stream(); |
数组: Arrays.stream(数组)
或者 Stream.of
创建
双列集合: 转化成单列结合后再创建
Map<String,Integer> map = new HashMap<>(); | |
map.put("夏日重现",12); | |
map.put("间谍过家家",13); | |
map.put("辉夜大小姐",14); | |
Stream<Map.Entry<String,Integer>> stream = map.entrySet().stream(); |
# 操作流
# filter()
过滤
通过 filter()
方法可以从流中筛选出我们想要的元素。
public class FilterStreamDemo { | |
public static void main(String[] args) { | |
List<String> list = new ArrayList<>(); | |
list.add("周杰伦"); | |
list.add("王力宏"); | |
list.add("陶喆"); | |
list.add("林俊杰"); | |
Stream<String> stream = list.stream().filter(element -> element.contains("王")); | |
stream.forEach(System.out::println); | |
} | |
} |
filter () 方法接收的是一个 Predicate(Java 8 新增的一个函数式接口,接受一个输入参数返回一个布尔值结果)类型的参数,因此,我们可以直接将一个 Lambda 表达式传递给该方法,比如说 element -> element.contains ("王") 就是筛选出带有 “王” 的字符串。
forEach () 方法接收的是一个 Consumer(Java 8 新增的一个函数式接口,接受一个输入参数并且无返回的操作)类型的参数,类名::方法名是 Java 8 引入的新语法,System.out 返回 PrintStream 类,println 方法你应该知道是打印的。
# map()
映射
如果想通过某种操作把一个流中的元素转化成新的流中的元素,可以使用 map()
方法。
public class MapStreamDemo { | |
public static void main(String[] args) { | |
List<String> list = new ArrayList<>(); | |
list.add("周杰伦"); | |
list.add("王力宏"); | |
list.add("陶喆"); | |
list.add("林俊杰"); | |
Stream<Integer> stream = list.stream().map(String::length); | |
stream.forEach(System.out::println); | |
} | |
} |
map()
方法接收的是一个 Function(Java 8 新增的一个函数式接口,接受一个输入参数 T,返回一个结果 R)类型的参数,此时参数 为 String 类的 length 方法,也就是把 Stream<String>
的流转成一个 Stream<Integer>
的流。
# 其他
distinct
去重sorted
排序limit
skip
# 终止操作
foreach()
对流中的元素进行遍历操作,我们通过传入的参数去指定对遍历到的元素执行具体的操作count()
获取当前流中的个数,返回一个 long 型结果max & min
返回一个 optional 对象collection
把流中的元素收集成新的集合
# 方法引用
简单地说,就是一个 Lambda 表达式。在 Java 8 中,我们会使用 Lambda 表达式创建匿名方法,但是有时候,我们的 Lambda 表达式可能仅仅调用一个已存在的方法,而不做任何其它事,对于这种情况,通过一个方法名字来引用这个已存在的方法会更加清晰,Java 8 的方法引用允许我们这样做。方法引用是一个更加紧凑,易读的 Lambda 表达式,注意方法引用是一个 Lambda 表达式,其中方法引用的操作符是双冒号 "::"。
# 什么场景适合使用方法引用
当一个 Lambda 表达式调用了一个已存在的方法,且没有别的代码
什么场景不适合使用方法引用
需要往引用的方法传参数的时候不适合: