Java如何支持函数式编程?
阿里妹导读:Java是面向对象的语言,无法直接调用一个函数。Java 8开始,引入了函数式编程接口与Lambda表达式,便于开发者写出更少更优雅的代码。什么是函数式编程?函数式编程的特点是什么?本文通过代码实例,从Stream类、Lambda表达式和函数接口这三个语法概念来分享Java对函数式编程的支持。
文末福利:Java微服务沙箱体验挑战。
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("do something...");
}
};
// 一行即可
Runnable runnable = () -> System.out.println("do something...");
// 有状态函数: 执行结果依赖b的值是多少,即便入参相同,
// 多次执行函数,函数的返回值有可能不同,因为b值有可能不同。
int b;
int increase(int a) {
return a + b;
}
// 无状态函数:执行结果不依赖任何外部变量值
// 只要入参相同,不管执行多少次,函数的返回值就相同
int increase(int a, int b) {
return a + b;
}
public class Demo {
public static void main(String[] args) {
Optional<Integer> result = Stream.of("a", "be", "hello")
.map(s -> s.length())
.filter(l -> l <= 3)
.max((o1, o2) -> o1-o2);
System.out.println(result.get()); // 输出2
}
}
add(multiply(subtract(3,1),2),5);
subtract(3,1).multiply(2).add(5);
public class Demo {
public static void main(String[] args) {
Optional<Integer> result = Stream.of("f", "ba", "hello") // of返回Stream<String>对象
.map(s -> s.length()) // map返回Stream<Integer>对象
.filter(l -> l <= 3) // filter返回Stream<Integer>对象
.max((o1, o2) -> o1-o2); // max终止操作:返回Optional<Integer>
System.out.println(result.get()); // 输出2
}
}
// Stream类中map函数的定义:
public interface Stream<T> extends BaseStream<T, Stream<T>> {
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
//...省略其他函数...
}
// Stream类中map的使用方法示例:
Stream.of("fo", "bar", "hello").map(new Function<String, Integer>() {
public Integer apply(String s) {
return s.length();
}
});
// 用Lambda表达式简化后的写法:
Stream.of("fo", "bar", "hello").map(s -> s.length());
(a, b) -> { 语句1;语句2;...; return 输出; } //a,b是输入参数
Optional<Integer> result = Stream.of("f", "ba", "hello")
.map(s -> s.length())
.filter(l -> l <= 3)
.max((o1, o2) -> o1-o2);
// 还原为函数接口的实现方式
Optional<Integer> result2 = Stream.of("fo", "bar", "hello")
.map(new Function<String, Integer>() {
public Integer apply(String s) {
return s.length();
}
})
.filter(new Predicate<Integer>() {
public boolean test(Integer l) {
return l <= 3;
}
})
.max(new Comparator<Integer>() {
public int compare(Integer o1, Integer o2) {
return o1 - o2;
}
});
Lambda就是为了优化匿名内部类而生,Lambda要比匿名类简洁的多得多。
Lambda仅适用于函数式接口,匿名类不受限。
即匿名类中的this是“匿名类对象”本身;Lambda表达式中的this是指“调用Lambda表达式的对象”。
一个函数式接口只有一个抽象方法(single abstract method);
Object类中的public abstract method不会被视为单一的抽象方法;
函数式接口可以有默认方法和静态方法;
函数式接口可以用@FunctionalInterface注解进行修饰。
public interface Comparator<T> {
/**
* single abstract method
* @since 1.8
*/
int compare(T o1, T o2);
/**
* Object类中的public abstract method
* @since 1.8
*/
boolean equals(Object obj);
/**
* 默认方法
* @since 1.8
*/
default Comparator<T> reversed() {
return Collections.reverseOrder(this);
}
/**
* 静态方法
* @since 1.8
*/
public static <T extends Comparable<? super T>> Comparator<T> reverseOrder() {
return Collections.reverseOrder();
}
//省略...
}
规规矩矩的写一个实现了Comparator接口的Java类去封装排序逻辑。若业务需要多种排序方式,那就得写多个类提供多种实现,而这些实现往往只需使用一次。
另外一种聪明一些的做法无外乎就是在需要的地方搞个匿名内部类,比如:
public class Test {
public static void main(String args[]) {
List<Person> persons = new ArrayList<Person>();
Collections.sort(persons, new Comparator<Person>(){
public int compare(Person o1, Person o2) {
return Integer.compareTo(o1.getAge(), o2.getAge());
}
});
}
}
Comparator<Person> comparator = (p1, p2) -> Integer.compareTo(p1.getAge(), p2.getAge());
public interface Function<T, R> {
R apply(T t); // 只有这一个未实现的方法
default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
Objects.requireNonNull(before);
return (V v) -> apply(before.apply(v));
}
default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
Objects.requireNonNull(after);
return (T t) -> after.apply(apply(t));
}
static <T> Function<T, T> identity() {
return t -> t;
}
}
public interface Predicate<T> {
boolean test(T t); // 只有这一个未实现的方法
default Predicate<T> and(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) && other.test(t);
}
default Predicate<T> negate() {
return (t) -> !test(t);
}
default Predicate<T> or(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) || other.test(t);
}
static <T> Predicate<T> isEqual(Object targetRef) {
return (null == targetRef)
? Objects::isNull
: object -> targetRef.equals(object);
}
}
Java微服务沙箱体验挑战
10分钟搭建一个Task Manager任务管理器
使用阿里云Java工程脚手架一键生成你的代码框架,并通过场景体验,学习使用微服务构建一套简单的分布式应用,最终实现一款代办事项管理软件。完成4个实验,通过Java基础和体验相关知识自测还可领取start.aliyun.com x IntelliJ联名小礼物!
点击“阅读原文”,立即去挑战吧!