Java Lambda表达式学习摘要

一 内部类

二 匿名内部类

给匿名内部类传递参数的时候,若该形参需要被内部类使用,则该形参必须是final类型的。

参考:http://www.cnblogs.com/chenssy/p/3390871.html

三 函数式编程

相对于命令式编程关注解决问题的步骤,函数式编程式面向数学的抽象,关心数据(代数结构)之间的映射关系。

函数式编程中的函数,不是指命令式编程中的函数(C++中的函数本质上是一段子程序),而是指数学中的函数,即自变量的映射(一种东西与另一种东西的映射关系)。也就是说,一个函数的值仅取决于函数参数的值,而不依赖于其他状态。

在函数式语言中,函数被称为一等函数,与其他数据类型一样,处于平等地位。可以在任何地方定义,函数内或函数外;可以赋值给其他变量;可以作为参数,传入另一个函数,或者作为别的函数的返回值。

四 java Lambda表达式

引用: https://www.cnblogs.com/snowInPluto/p/5981400.html

4.1简介

Java8的最大变化是引入了Lambda表达式,一种紧凑,传递行为的方式。
先看一个示例:

button.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent event) {
        System.out.println("button clicked");
    }
});

使用 Lambda 表达式,我们就可以简写为

button.addActionListener(event -> System.out.println("button clicked"));

4.2 Lambda 表达式

示例:

ActionListener oneArgument = event -> System.out.println("button clicked");
BinaryOperator<Long> add = (x, y) -> x + y;
BinaryOperator<Long> addExplicit = (Long x, Long y) -> x + y;

4.3 函数接口

上面的例子中提到了ActionListener接口,我们看一下它的代码:

public interface ActionListener extends EventListener {

    /**
     * Invoked when an action occurs.
     */
    public void actionPerformed(ActionEvent e);

}

ActionListener 只有一个抽象方法,该接口也继承自一个没有任何方法的父接口:eventListener.
写为匿名内部类的形式。

jdk8里面提供了一些常用的函数接口,

接口 参数 返回类型 描述
Predicate T boolean 用于判别一个对象。比如求一个人是否为男性
Consumer T void 用于接收一个对象进行处理但没有返回,比如接收一个人并打印他的名字
Function T R 转换一个对象为不同类型的对象
Supplier None T 提供一个对象
UnaryOperator T T 接收对象并返回同类型的对象
BinaryOperator (T, T) T 接收两个同类型的对象,并返回一个原类型对象

其中 Cosumer 与 Supplier 对应,一个是消费者,一个是提供者。

Predicate 用于判断对象是否符合某个条件,经常被用来过滤对象。

Function 是将一个对象转换为另一个对象,比如说要装箱或者拆箱某个对象。

UnaryOperator 接收和返回同类型对象,一般用于对对象修改属性。BinaryOperator 则可以理解为合并对象

五 主要应用场景

5.1 stream 简介

在程序中,集合的处理是很普遍从操作。JDK8 中,引入了流的概念,这与IO中的流并不相同。所以继承自Collection的接口都可以转变为Stream.
举例示意:
假设我们有一个 List 包含一系列的 Person,Person 有姓名 name 和年龄 age 连个字段。现要求这个列表中年龄大于 20 的人数。
以往写法:

long count = 0;
for (Person p : persons) {
    if (p.getAge() > 20) {
        count ++;
    }
}

现在的写法:

long count = persons.stream()
                    .filter(person -> person.getAge() > 20)
                    .count();
5.2 Stream 常用操作

Stream 的方法分为两类。一类叫惰性求值,一类叫及早求值。
判断一个操作是惰性求值还是及早求值很简单:只需看它的返回值。如果返回值是 Stream,那么是惰性求值。其实可以这么理解,如果调用惰性求值方法,Stream 只是记录下了这个惰性求值方法的过程,并没有去计算,等到调用及早求值方法后,就连同前面的一系列惰性求值方法顺序进行计算,返回结果。
通用形式为:

Stream.惰性求值.惰性求值. ... .惰性求值.及早求值

5.2.1 collect(toList())

collect(toList()) 方法由 Stream 里的值生成一个列表,是一个及早求值操作。可以理解为 Stream 向 Collection 的转换。
注意这边的 toList() 其实是 Collectors.toList(),因为采用了静态倒入,看起来显得简洁。

List<String> collected = Stream.of("a", "b", "c")
                               .collect(Collectors.toList());
assertEquals(Arrays.asList("a", "b", "c"), collected);

5.2.2 map

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

List<String> collected = Stream.of("a", "b", "hello")
                               .map(string -> string.toUpperCase())
                               .collect(toList());
assertEquals(asList("A", "B", "HELLO"), collected);

5.2.3 filter

List<String> beginningWithNumbers = 
        Stream.of("a", "1abc", "abc1")
              .filter(value -> isDigit(value.charAt(0)))
              .collect(toList());
assertEquals(asList("1abc"), beginningWithNumbers);

5.2.4 flatMap

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

List<Integer> together = Stream.of(asList(1, 2), asList(3, 4))
                               .flatMap(numbers -> numbers.stream())
                               .collect(toList());
assertEquals(asList(1, 2, 3, 4), together);
5.2.5 max和min

Stream 上常用的操作之一是求最大值和最小值。Stream API 中的 max 和 min 操作足以解决这一问题。

List<Integer> list = Lists.newArrayList(3, 5, 2, 9, 1);
int maxInt = list.stream()
                 .max(Integer::compareTo)
                 .get();
int minInt = list.stream()
                 .min(Integer::compareTo)
                 .get();
assertEquals(maxInt, 9);
assertEquals(minInt, 1);

这里有 2 个要点需要注意:
1 max 和 min 方法返回的是一个 Optional 对象(对了,和 Google Guava 里的 Optional 对象是一样的)。Optional 对象封装的就是实际的值,可能为空,所以保险起见,可以先用 isPresent() 方法判断一下。Optional 的引入就是为了解决方法返回 null 的问题。
2 Integer::compareTo 也是属于 Java 8 引入的新特性,叫做 方法引用(Method References)。在这边,其实就是 (int1, int2) -> int1.compareTo(int2) 的简写。

5.2.6 reduce

reduce 操作可以实现从一组值中生成一个值。在上述例子中用到的 count、min 和 max 方法,因为常用而被纳入标准库中。事实上,这些方法都是 reduce 操作

int result = Stream.of(1, 2, 3, 4)
                   .reduce(0, (acc, element) -> acc + element);
assertEquals(10, result);
int result = Stream.of(1, 2, 3, 4)
                   .reduce(1, (acc, element) -> acc * element);
assertEquals(24, result);

六 数据并行化操作

Stream 的并行化也是 Java 8 的一大亮点。数据并行化是指将数据分成块,为每块数据分配单独的处理单元。这样可以充分利用多核 CPU 的优势。

nt sumSize = Stream.of("Apple", "Banana", "Orange", "Pear")
                    .parallel()
                    .map(s -> s.length())
                    .reduce(Integer::sum)
                    .get();
assertEquals(sumSize, 21);

七 其他

Stream 转换为 List 是很常用的操作,其他 Collectors 还有很多方法,可以将 Stream 转换为 Set, 或者将数据分组并转换为 Map,并对数据进行处理。也可以指定转换为具体类型,如 ArrayList, LinkedList 或者 HashMap。甚至可以自定义 Collectors,编写自己的收集器。

7.2 元素排序
List<Integer> list = Lists.newArrayList(3, 5, 1, 10, 8);
List<Integer> sortedList = list.stream()
                               .sorted(Integer::compareTo)
                               .collect(Collectors.toList());
assertEquals(sortedList, Lists.newArrayList(1, 3, 5, 8, 10));

http://zh.lucida.me/blog/java-8-lambdas-insideout-language-features/ ?????????????????????????????????

猜你喜欢

转载自blog.csdn.net/secure2/article/details/80986518
今日推荐