概念:
面向对象是对数据进行抽象,函数式编程是对行为进行抽象。紧凑的、传递行为的方式。
核心:
思考问题是,对象是 不可变值和函数,函数对每一个值进行处理,应射成另一个值。
用途:
- 不用使用匿名内部类。
- 让函数方便地传递。
下面是数中例子的解释:
思考内部类,我们只想传行为,不想传对象。
看一个对比:
//普通的回调
button.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent event) {
System.out.println("button clicked");
}
});
//使用lambda
button.addActionListener(event -> System.out.println("button clicked"));
其中
event是参数名,-> 将参数和lambda分开。内部类需要声明event,lambda中不用声明event,javac编译器自己去找。
几个lambda实例,注意点
1.箭头左边为函数参数,可以用括号括起来。
2.箭头右边是函数操作,可以用大括号,而使用普通java操作。
Runnable noArguments = () -> System.out.println("Hello World");
ActionListener oneArgument = event -> System.out.println("button clicked");
Runnable multiStatement = () -> {
System.out.print("Hello");
System.out.println(" World");
};
BinaryOperator<Long> add = (x, y) -> x + y;
BinaryOperator<Long> addExplicit = (Long x, Long y) -> x + y;
Lambda 表达式也可以表示包含多个参数的方法。这时就有必要思考怎样去阅 读该 Lambda 表达式。这行代码并不是将两个数字相加,而是创建了一个函数,用来计算 两个数字相加的结果。变量 add 的类型是 BinaryOperator<Long>,它不是两个数字的和, 而是将两个数字相加的那行代码。
Lambda的闭包。指的是Lambda内部可以引用外部的变量,但是只能引用final的。其实也就是Lambda是无状态的。
常用的函数接口
类型推断:
//根据参数的类型去推断
useHashmap(new HashMap<>());
private void useHashmap(Map<String, String> values);
Predicate接口示例
Predicate<Integer> p = x -> x > 5;
不管lambda表达式中做什么,他要返回一个boolean
重点
Lambda表达式是一个匿名方法,可以将lambda传递给一个函数
对核心类库的改进包括:
- 集合类API
- Stream类,使用函数式编程方式在集合类上进行复杂操作的工具。
都是对集合进行操作。
//统计来自伦敦的艺术家的人数
long count = allArtists.stream()
.filter(artist -> artist.isFrom("London"))
.count();
上面的操作只会迭代一次。
Stream中的一个方法,代表一个对集合的操作:
filter:指的是,只保留满足条件的对象。返回boolean值
filter没做实质性的工作,filter只刻画出了Stream,没有产生新集合。像这种只做描述,不产生集合或者值得方法,叫做惰性求值方法。
像count这样会产生值得方法叫做及早求值方法。
区分惰性求值和及早求值,看函数的返回值,返回Stream,则为惰性,返回空或者其他,为及早。
介绍常用的流操作:
collect(toList)
List<String> collected = Stream.of("a", "b", "c") .collect(Collectors.toList());
assertEquals(Arrays.asList("a", "b", "c"), collected);
map 解释:如果有一个函数可以将一种类型的值转换成另外一种类型,map 操作就可以 使用该函数,将一个流中的值转换成一个新的流。
List<String> collected = Stream.of("a", "b", "hello")
.map(string -> string.toUpperCase())
.collect(toList());
collect是一个及早求值,来返回一个集合。
filter 遍历集合,并过滤,只留下剩余的元素。
flatMap 方法可用 Stream 替换值,然后将多个 Stream 连接成一个 Stream。
Collectors.toList() //注意不是Collections
max和min
//注意这个Comparator.comparing是专门给lambda的方法。Function接口
Track shortestTrack = tracks.stream()
.min(Comparator.comparing(track -> track.getLength()))
.get();
max和min返回一个Optional对象,get方法,取出对象中的值。
reduce模式
是啥样子的呢,特征,开始时,记录初始值,然后遍历集合,对集合中的每个元素调用combine函数,参数是初始值和当前值,最后初始值的引用就代表最后的结果。
Object accumulator = initialValue; for(Object element : collection) {
accumulator = combine(accumulator, element);
}
解释:reduce 操作可以实现从一组值中生成一个值。
上面的max,count,min,都是reduce操作。
将一个循环,重构为lambda,每一步都进行单元测试:
28页的例子,贼好。
高阶函数
接收另一个函数作为参数,返回一个函数的函数。