常用的函数式接口
常用的函数式接口
jdk提供了大量常用的函数式接口以丰富lambda的典型使用场景,它们主要在java.util.function包中被提高。
1.Supplier接口
java.util.function.Supplier<T>被称为为生产型接口,该接口仅包含一个无参的方法:T get();。用来获取一个泛型指定类型的对象数据。
public class TestSupplier {
public static int getmessge(Supplier<Integer> supplier){
return supplier.get();
}
public static void main(String[] args) {
int[] array = {11,22,404,33,77};
//使用lambda表达式获取数组中最大的值
int maxValue = getmessge(() -> {
int max = array[0];
for (int i : array) {
if (i > max) {
max = i;
}
}
return max;
});
System.out.println(maxValue);
}
}
/*print:404*/
2.Consumer接口
java.util.function.Consumer<T>接口与sipplier正好相反,他不是生产数据,而是消费数据,没有返回值,其数据类型由泛型决定。其抽象方法void accept(T t),还包含一个默认方法:
default Consumer<T> andThen(Consumer<? super T> after) {
Objects.requireNonNull(after);
return (T t) -> { accept(t); after.accept(t); };
}
用来对数据多次消费
public class TestConsumer {
public static void consumer(String s, Consumer<String> con1,Consumer<String> con2){
con1.andThen(con2).accept(s);
}
public static void main(String[] args) {
String message="talk is cheap";
consumer(message,(s)->{
String s1 = s.toUpperCase();
System.out.println(s1);
},(s)->{
String s2 = s.substring(8);
System.out.println(s2);
});
}
}
/* TALK IS CHEAP */
/* cheap */
Consumer还有多个其他的接口,具体有以下几种,在使用函数式接口时,若有提供具体类型的接口,就尽量使用此接口,因为具体的类型指定可以避免装箱拆箱时所带来的额外资源消耗
BiConsumer 接收两个参数
IntConsumer 接收一个int参数
LongConsumer 接收一个long参数
DoubleConsumer 收一个double参数
ObjIntConsumer 接收两个参数 T,int
ObjLongConsumer 接收两个参数 T,long
ObjDoubleConsumer 接收两个参数 T,,double
3.Predicate接口
java.util.function.Predicate<T>可以对某种数据类型的数据进行判断,从而得到一个boolean值结果。抽象方法为void test(T t),包含三个默认方法:
default Predicate<T> and(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) && other.test(t);
}
default Predicate<T> or(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) || other.test(t);
}
default Predicate<T> negate() {
return (t) -> !test(t);
}
分别对应逻辑判断的“&&”,“||”,“!”
int[] numbers= {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
List<Integer> list=new ArrayList<>();
for(int i:numbers) {
list.add(i);
}
Predicate<Integer> p1=i-> i>5;
Predicate<Integer> p2=i-> i<20;
Predicate<Integer> p3=i-> i%2==0;
List test=list.stream().filter(p1.and(p2).and(p3)).collect(Collectors.toList());
System.out.println(test.toString());
/* print:[6, 8, 10, 12, 14]*/
我们定义了三个断言p1,p2,p3。现在有一个从1~15的list,我们需要过滤这个list。上述的filter是过滤出所有大于5小于20,并且是偶数的列表。
假如突然我们的需求变了,我们现在需要过滤出奇数。那么我不可能直接去改Predicate,因为实际项目中这个条件可能在别的地方也要使用。那么此时我只需要更改filter中Predicate的条件。
List test=list.stream().filter(p1.and(p2).and(p3.negate())).collect(Collectors.toList());
/* print:[7, 9, 11, 13, 15]*/
4.Function接口
java.util.function.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));
}
andThen跟compose正相反,先执行当前的逻辑,再执行传入的逻辑。
public void test(){
Function<Integer,Integer> A=i->i+1;
Function<Integer,Integer> B=i->i*i;
System.out.println("F1:"+B.apply(A.apply(5)));
System.out.println("F1:"+B.compose(A).apply(5));
System.out.println("F2:"+A.apply(B.apply(5)));
System.out.println("F2:"+B.andThen(A).apply(5));
}
/* F1:36 */
/* F1:36 */
/* F2:26 */
/* F2:26 */

浙公网安备 33010602011771号