Java8特性1 - lambda表达式&函数式接口

引子

要求创建一个线程,线程中输出hello world

没学Lambda前的画风:

1
2
3
4
5
6
7
8
//写法1
class myThread implements Runnable{
@Override
public void run() {
System.out.println("hello world!");
}
}
new Thread(new myThread()).start();
1
2
3
4
5
6
7
//写法2
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("hello world!");
}
}).start();

当你学会Lambda表达式之后,画风是这样的:

1
new Thread(() -> System.out.println("hello world!")).start();

是不是有种打开新世界大门的感觉,一起来看下Java8的新特性之一Lambda表达式

函数式接口:接口中只有一个抽象方法的接口

这种接口都可以用lambda表达式来实现

JDK内置四大基础函数式接口

  • Consumer#accept(Object)
    • void accept(T t); 消费型接口,接受一个参数,无返回
  • Supplier#get()
    • T get(); 供给型接口,无参数,但有返回值
  • Function#apply(Object)
    • R apply(T t); 函数型接口,接收参数T,返回一个R
  • Predicate#test(Object)
    • boolean test(T t); 断定型接口,接收参数T,判断其是否满足某一约束,返回一个boolean值

从源码中可以看到这四个基础接口都有注解@FunctionalInterface,他们都有一个特点:

有且仅有一个抽象方法

下面通过以前的写法、Java8的lambda写法进行对比学习

Consumer

消费型接口,接收一个参数,但无返回值

其接口核心源码如下:

1
2
3
4
5
6
7
8
9
/**
* 接受单个输入参数且不返回结果的操作
* @param <T>输入参数的类型
* @since 1.8
*/
@FunctionalInterface
public interface Consumer<T> {
void accept(T t);
}

写一个小示例:

1
2
3
4
5
6
7
8
9
10
11
12
//Java8以前的写法
Consumer<String> consumer1 = new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
};
consumer1.accept("接收1个参数,无返回值的函数式接口实现");

//Lambda表达式写法
Consumer<String> consumer2 = s -> System.out.println(s);
consumer2.accept("接收1个参数,无返回值的lambda表达式");

Supplier

供给型接口,无参数,但有返回值

其接口核心源码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14

/**
* 代表了结果的提供者
* @param <T> 该接口对外提供的返回结果类型
* @since 1.8
*/
@FunctionalInterface
public interface Supplier<T> {
/**
* 获取一个结果
* @return 返回结果
*/
T get();
}

写一个小示例:

1
2
3
4
5
6
7
8
9
10
11
12
Supplier<Integer> supplier1 = new Supplier<Integer>() {
@Override
public Integer get() {
return new Random().nextInt(100);
}
};
System.out.println("supplier接口原始写法获取随机数:" +supplier1.get());

System.out.println("----------------------");

Supplier<Integer> supplier2 = () -> new Random().nextInt(100);
System.out.println("supplier接口Lambda表达式写法获取随机数:" +supplier2.get());

Function

函数型接口,接收参数T,返回一个R

其核心源码如下:

1
2
3
4
5
6
7
8
9
10
/**
* 接收一个参数并返回一个结果的函数
* @param <T> 函数(方法)的参数类型
* @param <R> 函数(方法)的返回值类型
* @since 1.8
*/
@FunctionalInterface
public interface Function<T, R> {
R apply(T t);
}

新老用法对比例子

1
2
3
4
5
6
7
8
9
10
11
12
Function<Integer, String> function1 = new Function<Integer, String>() {
@Override
public String apply(Integer integer) {
return "接收整型参数:" + integer;
}
};
System.out.println(function1.apply(100));

System.out.println("----------------------");

Function<Integer, String> function2 = i -> "接收整型参数:" + i;
System.out.println(function2.apply(1000));

Predicate

断定型接口,接收参数T,判断其是否满足某一约束,返回一个boolean值

核心源码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* 接收参数T,判断其是否满足某一约束,返回一个boolean值
* @param <T> 方法参数类型
* @since 1.8
*/
@FunctionalInterface
public interface Predicate<T> {
/**
* 根据给定的参数进行自定义实现的判断,返回一个布尔值
*
* @param t 输入参数
* @return {@code true} 判断通过,返回true
* otherwise {@code false} 判断不通过,返回false
*/
boolean test(T t);
1
2
3
4
5
6
7
8
9
10
11
12
Predicate<Integer> predicate1 = new Predicate<Integer>() {
@Override
public boolean test(Integer integer) {
return integer > 100;
}
};
System.out.println("大于100 ? " + predicate1.test(101));

System.out.println("----------------------");

Predicate<Integer> predicate2 = integer -> integer>100;
System.out.println("大于100 ? " + predicate2.test(99));
---------- 😏本文结束  感谢您的阅读😏 ----------
评论