您的位置:首页 > 编程语言 > Java开发

Java8 Lambda表达式入门

2015-04-23 22:52 761 查看
Lambda表达式的实质就是一个匿名函数。C#3.0引入了Lambda表达式,Java8也不甘示弱。Java8发布很久了,今天安装了JDK体验了Java8中的Lambda表达式。

首先看一个不适用Lambda表达式的例子。

比如我们要对一组字符串进行排序。

public class Hello {
public static void main(String[] args) {
List<String> names = Arrays.asList("Tan", "Zhen", "Yu");
Collections.sort(names, new Comparator<String>() {
@Override
public int compare(String a, String b) {
return a.compareTo(b);
}
});
for (String name : names) {
System.out.println(name);
}
}
}


运行结果:

Tan
Yu
Zhen


同样的例子看一下使用Lambda表达式的代码:

public class Hello {
public static void main(String[] args) {
List<String> names = Arrays.asList("Tan", "Zhen", "Yu");
Collections.sort(names, (String a, String b) -> a.compareTo(b));
Stream<String> stream = names.stream();
stream.forEach(System.out::println);
}
}


是不是简洁很多。

下面详细介绍下Java8中的Lambda表达式。

(String a, String b) -> a.compareTo(b)就是一个Lambda表达式。前面括号中是函数的参数列表,->符号后面的是函数体。所以Lambda表示的写法是前面使用小括号列出函数参数,然后是用->符号指向函数体,函数体一般使用花括号{}括起来。

上面函数体a.compareTo(b)其实是一种简写。完整的写法应该是

(String a, String b) -> {
returen a.compareTo(b);
}


因为函数体只有一句,一般可以省略大括号和return关键字。

Java中每一个Lambda表达式都对应一个类型,通常是接口类型,使用@FunctionalInterface进行注解。这种“函数式接口”是指仅仅只包含一个抽象方法的接口,每一个该类型的Lambda表达式都会被匹配到这个抽象方法。即就是说每一个Lambda表达式对应函数式接口中的那个抽象方法。

此外,Java 8允许我们给接口添加一个非抽象的方法实现,只需要使用 default关键字即可,这个特征又叫做扩展方法,。所以函数式接口中只能有一个抽象方法,其它的只能是扩展方法。下面是Java8中的Comparator接口,compare是抽象方法,此外还有一些扩展方法。

@FunctionalInterface
public interface Comparator {
int compare(T o1, T o2);
......
}


在上面的示例代码中stream.forEach(System.out::println)一句的作用是使用Stream API输出每个字符串,下面进行详细解释。

Java 8引入了全新的Stream API。这里的Stream和I/O流不同,它更像具有Iterable的集合类,但行为和集合类又有所不同。Stream API引入的目的在于弥补Java函数式编程的缺陷。对于很多支持函数式编程的语言,map()、reduce()基本上都内置到语言的标准库中了(比如像Python和JavaScript这些语言)。

创建一个Stream有很多方法,最简单的方法是把一个Collection变成Stream,像上面的Stream<String> stream = names.stream()。

集合类新增的stream()方法用于把一个集合变成Stream,然后,通过filter()、map()等实现Stream的变换。Stream还有一个forEach()来完成每个元素的迭代。

这是forEach方法的签名void forEach(Consumer<? super T> action)。Consumer<? super T>也是一个函数式接口,所以我们应该传入一个函数。

Java 8 允许你使用 :: 关键字来传递方法或者构造函数引用,像上面的System.out::println是对println函数的引用。如果引用构造函数可以使用对象::new的形式。

个人感觉Java8中的函数式接口的作用和C#中的代理类型(delegate)比较像,或者说作用比较类似。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: