lamba表达式

概念:

面向对象是对数据进行抽象,函数式编程是对行为进行抽象。紧凑的、传递行为的方式。
核心:
思考问题是,对象是 不可变值和函数,函数对每一个值进行处理,应射成另一个值。

用途:

  • 不用使用匿名内部类。
  • 让函数方便地传递。

下面是数中例子的解释:


lamba表达式_第1张图片
image.png
lamba表达式_第2张图片
image.png

思考内部类,我们只想传行为,不想传对象。
看一个对比:

//普通的回调
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 add = (x, y) -> x + y;   

BinaryOperator addExplicit = (Long x, Long y) -> x + y;

Lambda 表达式也可以表示包含多个参数的方法。这时就有必要思考怎样去阅 读该 Lambda 表达式。这行代码并不是将两个数字相加,而是创建了一个函数,用来计算 两个数字相加的结果。变量 add 的类型是 BinaryOperator,它不是两个数字的和, 而是将两个数字相加的那行代码。

Lambda的闭包。指的是Lambda内部可以引用外部的变量,但是只能引用final的。其实也就是Lambda是无状态的。

lamba表达式_第3张图片
image.png

常用的函数接口


lamba表达式_第4张图片
image.png

类型推断:

//根据参数的类型去推断
useHashmap(new HashMap<>());
private void useHashmap(Map values);
lamba表达式_第5张图片
image.png

Predicate接口示例

Predicate 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 collected = Stream.of("a", "b", "c")   .collect(Collectors.toList());  
assertEquals(Arrays.asList("a", "b", "c"), collected);  

map 解释:如果有一个函数可以将一种类型的值转换成另外一种类型,map 操作就可以 使用该函数,将一个流中的值转换成一个新的流。

List collected = Stream.of("a", "b", "hello")
.map(string -> string.toUpperCase())  
                                    .collect(toList());

collect是一个及早求值,来返回一个集合。

filter 遍历集合,并过滤,只留下剩余的元素。

flatMap 方法可用 Stream 替换值,然后将多个 Stream 连接成一个 Stream。

lamba表达式_第6张图片
image.png
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页的例子,贼好。

高阶函数

接收另一个函数作为参数,返回一个函数的函数。

你可能感兴趣的:(lamba表达式)