在java
中,大家肯定使用过lambda
表达式吧,这是适用于函数式接口的一种便捷写法。
那么什么是函数式接口,简单点来说,一个接口中有且只有一个需要实现的方法,那么这个接口就是函数式接口。
如果一个接口,你想定义为函数式接口,建议加上注解@Functionionallnterface
,标注这个接口成为函数式接口,用来进行提示。
例如,多线程的Runnable
接口就是一个函数式接口,如下
package java.lang;
@FunctionalInterface
public interface Runnable {
public abstract void run();
}
所以,我们在使用多线程时,可以使用lambda
表达式进行简化
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();
// lambda表达式,小括号是入参,大括号是函数式接口中唯一方法的实现
new Thread(() -> {
System.out.println("lambda表达式写法");
}).start();
// 方法实现只有单行时,可以再简写,省略大括号
new Thread(() -> System.out.println("lambda表达式写法")).start();
}
}
Function<T, R>
先看源码,发现里面居然有四个方法。又仔细一看,确实里面仅有一个apply
方法需要实现,所以Function
也是一个函数式接口。
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
,且内部做了一定的处理
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);
// 使用lambda表达式
List<String> stringList1 = list.stream().map((i) -> {
return "你好" + i;
}).collect(Collectors.toList());
// 再简写,当参数仅有一个时,小括号可以省略
stringList1 = list.stream().map(i -> {
return "你好" + i;
}).collect(Collectors.toList());
// 再简写,当实现的方法仅有一行语句时,大括号及return可以省略
stringList1 = list.stream().map(i -> "你好" + i).collect(Collectors.toList());
System.out.println(stringList1);
}
}
看下stream
接口中的这个map
方法,需要我们传入一个Function
接口的实现类对象,使用lambda
表达式轻松实现对函数式接口的实现类对象的构建
package java.util.stream;
public interface Stream<T> extends BaseStream<T, Stream<T>> {
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
}
Predicate<T>
先看源码,泛型只需要指定一个,需要实现的方法一个入参,出参是boolean
,作用于判断的一个函数式接口。
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);
}
}
来查看使用
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);
// lambda表达式简化
filterList = list.stream().filter(i -> i > 5).collect(Collectors.toList());
System.out.println(filterList);
}
}
看下stream
接口中的这个filter
方法,需要我们传入一个Predicate
接口的实现类对象
package java.util.stream;
public interface Stream<T> extends BaseStream<T, Stream<T>> {
Stream<T> filter(Predicate<? super T> predicate);
}
Consumer<T>
看类名也能看出来,这是一个消费型的函数式接口,有入参,但没有返回值
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); };
}
}
使用如下
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);
// lambda表达式简化
System.out.println("\n========== 分割线 ==========");
list.forEach(a -> {
if(Objects.equals(a, 6))
return;
System.out.print(a);
});
}
}
查看forEach
方法的源码,需要我们传入一个Consumer
接口的实现类对象
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
。现在看了源码,你还有这样的疑问吗?
Supplier<T>
供给型接口,只有出参,没有入参。在使用上并不多见,先看源码
package java.util.function;
@FunctionalInterface
public interface Supplier<T> {
T get();
}
查看使用
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("========== 分割线 ==========");
// lambda表达式简化
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
值后,将使用供给的对象
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
的文章我也有写,可以参考进行学习。
我是半月,祝你幸福!!!
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有