Java的函数式接口以及Lambda表达式
一、介绍
在java
中,大家肯定使用过lambda
表达式吧,这是适用于函数式接口的一种便捷写法。
那么什么是函数式接口,简单点来说,一个接口中有且只有一个需要实现的方法,那么这个接口就是函数式接口。
如果一个接口,你想定义为函数式接口,建议加上注解@Functionionallnterface
,标注这个接口成为函数式接口,用来进行提示。
例如,多线程的Runnable
接口就是一个函数式接口,如下
1 2 3 4 5 6 7
| package java.lang;
@FunctionalInterface public interface Runnable { public abstract void run(); }
|
所以,我们在使用多线程时,可以使用lambda
表达式进行简化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| package com.banmoon.test;
import org.junit.jupiter.api.Test;
public class SomethingTest {
@Test public void test() { new Thread(new Runnable() { @Override public void run() { System.out.println("匿名内部类写法"); } }).start();
new Thread(() -> { System.out.println("lambda表达式写法"); }).start();
new Thread(() -> System.out.println("lambda表达式写法")).start(); }
}
|
二、常用的函数式接口
1)Function<T, R>
先看源码,发现里面居然有四个方法。又仔细一看,确实里面仅有一个apply
方法需要实现,所以Function
也是一个函数式接口。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| package java.util.function;
import java.util.Objects;
@FunctionalInterface 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; } }
|
这个函数式接口,接受有两个泛型,一个作为入参,一个作为出参。
我第一时间就想到了转换类型,来看这个,从Integer
转换为String
,且内部做了一定的处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| package com.banmoon.test;
import org.junit.jupiter.api.Test;
import java.util.ArrayList; import java.util.List; import java.util.function.Function; import java.util.stream.Collectors;
public class SomethingTest {
@Test public void test() { List<Integer> list = new ArrayList<Integer>(){{ add(7); add(5); add(1); add(2); add(8); add(4); add(3); add(6); add(3); add(6); add(3); add(6); }};
Function<Integer, String> myFunction = new Function<Integer, String>() { @Override public String apply(Integer i) { return "你好" + i; } }; List<String> stringList = list.stream().map(myFunction).collect(Collectors.toList()); System.out.println(stringList);
List<String> stringList1 = list.stream().map((i) -> { return "你好" + i; }).collect(Collectors.toList());
stringList1 = list.stream().map(i -> { return "你好" + i; }).collect(Collectors.toList()); stringList1 = list.stream().map(i -> "你好" + i).collect(Collectors.toList()); System.out.println(stringList1); }
}
|
看下stream
接口中的这个map
方法,需要我们传入一个Function
接口的实现类对象,使用lambda
表达式轻松实现对函数式接口的实现类对象的构建
1 2 3 4 5 6
| package java.util.stream;
public interface Stream<T> extends BaseStream<T, Stream<T>> { <R> Stream<R> map(Function<? super T, ? extends R> mapper); }
|
2)Predicate<T>
先看源码,泛型只需要指定一个,需要实现的方法一个入参,出参是boolean
,作用于判断的一个函数式接口。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| package java.util.function;
import java.util.Objects;
@FunctionalInterface 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); } }
|
来查看使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| package com.banmoon.test;
import org.junit.jupiter.api.Test;
import java.util.ArrayList; import java.util.List; import java.util.function.Predicate; import java.util.stream.Collectors;
public class SomethingTest {
@Test public void test() { List<Integer> list = new ArrayList<Integer>(){{ add(7); add(5); add(1); add(2); add(8); add(4); add(3); add(6); add(3); add(6); add(3); add(6); }};
Predicate<Integer> myPredicate = new Predicate<Integer>() { @Override public boolean test(Integer i) { return i>5; } };
List<Integer> filterList = list.stream().filter(myPredicate).collect(Collectors.toList()); System.out.println(filterList);
filterList = list.stream().filter(i -> i > 5).collect(Collectors.toList()); System.out.println(filterList); }
}
|
看下stream
接口中的这个filter
方法,需要我们传入一个Predicate
接口的实现类对象
1 2 3 4 5 6
| package java.util.stream;
public interface Stream<T> extends BaseStream<T, Stream<T>> { Stream<T> filter(Predicate<? super T> predicate); }
|
3)Consumer<T>
看类名也能看出来,这是一个消费型的函数式接口,有入参,但没有返回值
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| package java.util.function;
import java.util.Objects;
@FunctionalInterface public interface Consumer<T> {
void accept(T t);
default Consumer<T> andThen(Consumer<? super T> after) { Objects.requireNonNull(after); return (T t) -> { accept(t); after.accept(t); }; } }
|
使用如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| package com.banmoon.test;
import org.junit.jupiter.api.Test;
import java.util.ArrayList; import java.util.List; import java.util.Objects; import java.util.function.Consumer;
public class SomethingTest {
@Test public void test() { List<Integer> list = new ArrayList<Integer>(){{ add(7); add(5); add(1); add(2); add(8); add(4); add(3); add(6); add(3); add(6); add(3); add(6); }};
Consumer myConsumer = new Consumer() { @Override public void accept(Object o) { if(Objects.equals(o, 6)) return; System.out.print(o); } }; list.forEach(myConsumer);
System.out.println("\n========== 分割线 =========="); list.forEach(a -> { if(Objects.equals(a, 6)) return; System.out.print(a); }); }
}
|
查看forEach
方法的源码,需要我们传入一个Consumer
接口的实现类对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| package java.lang;
import java.util.Iterator; import java.util.Objects; import java.util.Spliterator; import java.util.Spliterators; import java.util.function.Consumer;
public interface Iterable<T> {
default void forEach(Consumer<? super T> action) { Objects.requireNonNull(action); for (T t : this) { action.accept(t); } }
}
|
总有人问,为什么forEach
方法不能使用break
和continue
。现在看了源码,你还有这样的疑问吗?
4)Supplier<T>
供给型接口,只有出参,没有入参。在使用上并不多见,先看源码
1 2 3 4 5 6 7 8
| package java.util.function;
@FunctionalInterface public interface Supplier<T> {
T get(); }
|
查看使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| package com.banmoon.test;
import lombok.AllArgsConstructor; import lombok.Data; import org.junit.jupiter.api.Test;
import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.function.Supplier;
public class SomethingTest {
@Test public void test() { List<User> list = new ArrayList<User>() {{ add(new User("半月1", 18, 90)); add(null); }};
Supplier<User> mySupplier = new Supplier() { @Override public Object get() { return new User("未知", 0, 0); } }; list.forEach(a -> { User user = Optional.ofNullable(a) .orElseGet(mySupplier); System.out.println(user); });
System.out.println("========== 分割线 =========="); list.forEach(a -> { User user = Optional.ofNullable(a) .orElseGet(() -> new User("未知", 0, 0)); System.out.println(user); }); }
}
@Data @AllArgsConstructor class User { private String name; private Integer age; private Integer score; }
|
查看Optional
的源码,这个方法主要作用是,当前对象为null
值后,将使用供给的对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| package java.util;
import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Predicate; import java.util.function.Supplier;
public final class Optional<T> {
private final T value;
public T orElseGet(Supplier<? extends T> other) { return value != null ? value : other.get(); }
}
|
三、最后
上面例举的四个函数式接口,是比较经典的,在很多简化的代码中都可以看到他们的身影。
在java8
之后,lambda
表达式出现,极大地提高了开发的效率,也使得java
复杂臃肿的代码得到了缓解。
可谁知道,java8
的发布时间在2013年9月份呢,距今都已经有9年的时间了,如果还不了解这上面这些接口,建议先使用Stream
流处理。一段时间后,你会明白这些接口的。
使用stream
的文章我也有写,可以参考进行学习,点击进行跳转
我是半月,祝你幸福!!!