900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > Java8之函数式接口及常用函数式接口

Java8之函数式接口及常用函数式接口

时间:2018-08-18 11:13:47

相关推荐

Java8之函数式接口及常用函数式接口

目录

函数式接口1.概念2.@FunctionalInterface3.函数式接口使用方式常用函数式接口1.JDK提供的函数式接口举栗2.Supplier3.Consumer4.Predicate5.Function6.常用函数式接口相关扩展接口a.Supplier相关拓展接口sumer相关拓展接口c.Predicate相关拓展接口d.Function相关的接口

函数式接口

1.概念

函数式接口(Functional Interface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。

函数式接口可以被隐式转换为 lambda 表达式。

Lambda 表达式和方法引用(实际上也可认为是Lambda表达式)上。

2.@FunctionalInterface

@FunctionalInterfacepublic interface Runnable {/*** When an object implementing interface <code>Runnable</code> is used* to create a thread, starting the thread causes the object's* <code>run</code> method to be called in that separately executing* thread.* <p>* The general contract of the method <code>run</code> is that it may* take any action whatsoever.** @seejava.lang.Thread#run()*/public abstract void run();}

我们常用的Runnable接口就是个典型的函数式接口,我们可以看到它有且仅有一个抽象方法run。并且可以看到一个注解@FunctionalInterface,这个注解的作用是强制你的接口只有一个抽象方法。如果有多个话直接会报错,如图:

idea错误提示:

编译时错误提示:

这里当你写了第二个方法时,编译就无法通过,idea甚至在编码阶段就行了提示。

3.函数式接口使用方式

我们直接上代码,首先定义一个函数式接口

@FunctionalInterfacepublic interface SingleAbstraMethodInterface {public abstract void singleMethod();}

我们定一个test类,封装一个方法,将SingleAbstraMethodInterface当做参数传入方法,并打印一句话

public class Test {public void testMethod(SingleAbstraMethodInterface single){System.out.println("即将执行函数式接口外部定义方法");single.singleMethod();}public static void main(String[] args) {Test test = new Test();test.testMethod(new SingleAbstraMethodInterface() {@Overridepublic void singleMethod() {System.out.println("执行函数式接口定义方法");}});}}

执行结果:

即将执行函数式接口外部定义方法

执行函数式接口定义方法

是不是和我们预期结果一样。这个过程是不是有的同学已经发现,怎么这么像jdk里面的一些接口的使用,比如常用的Runnable接口。我们来看看代码。

public static void main(String[] args) {new Thread(new Runnable() {@Overridepublic void run() {System.out.println("run方法执行了");}}).start();}

再看下Runnable接口源码,是不是一样😜😜😜

@FunctionalInterfacepublic interface Runnable {public abstract void run();}

这时,有的同学会说,我用Runnable接口可不是这么用的,我的写法比你优雅,我是这么写的。

没错函数式接口,函数式编程,我们可以使用lambda表达式的写法,可以让代码更优雅,具体可以参照我的前一篇帖子。Java8之Lambda表达式

public static void main(String[] args) {new Thread(()-> {System.out.println("run方法执行了");}).start();}

常用函数式接口

1.JDK提供的函数式接口举栗

java.lang.Runnable,

java.awt.event.ActionListener,

parator,

java.util.concurrent.Callable

java.util.function包下的接口,如Consumer、Predicate、Supplier等

其实,jdk中给我们提供了很多的函数式接口,我们平时都会用到,只不过大家没有注意到而已,这里我结合实际代码讲解几个常用的函数式接口。想想大家平时常常用到stream流的各种方法来处理list。我看去stream类中看一下它提供的方法。可以看到有几个出镜率较高的函数式接口

SupplierComsumerPredicateFunction

2.Supplier

@FunctionalInterfacepublic interface Supplier<T> {/*** Gets a result.* @return a result*/T get();}

Supplier接口的get方法没有入参,返回一个泛型T对象。我们来看几个使用 的实例。先写一个实验对象girl,我们定义一个方法,创建对象,我们使用lambda的方式来调用并创建对象。

@Data@AllArgsConstructor@NoArgsConstructorpublic class Girl {private String name;private Double size;private Double price;public static Girl create(final Supplier<Girl> supplier) {return supplier.get();}public static void main(String[] args) {//创建对象Girl girl1 = Girl.create(Girl::new);Girl girl2 = Girl.create(()-> new Girl("lily",33d,1700d));Girl girl = null;//orElseGetGirl girl3 = Optional.ofNullable(girl).orElseGet(Girl::new);}}

需要注意的是,我没每调用一次get方法,都会重新创建一个对象。orElseGet方法入参同样也是Supplier,这里对girl实例进行判断,通过Supplier实现了懒加载,也就是说只有当判断girl为null时,才会通过orElseGet方法创建新的对象并且返回。不得不说这个设计是非常的巧妙。

3.Consumer

源码如下:

@FunctionalInterfacepublic interface Consumer<T> {/*** Performs this operation on the given argument.** @param t the input argument*/void accept(T t);/*** Returns a composed {@code Consumer} that performs, in sequence, this* operation followed by the {@code after} operation. If performing either* operation throws an exception, it is relayed to the caller of the* composed operation. If performing this operation throws an exception,* the {@code after} operation will not be performed.** @param after the operation to perform after this operation* @return a composed {@code Consumer} that performs in sequence this* operation followed by the {@code after} operation* @throws NullPointerException if {@code after} is null*/default Consumer<T> andThen(Consumer<? super T> after) {Objects.requireNonNull(after);return (T t) -> {accept(t); after.accept(t); };}}

可以看到accept方法接受一个对象,没有返回值。那么我们来实战,首先使用Lambda表达式声明一个Supplier的实例,它是用来创建Girl实例;再使用Lambda表达式声明一个Consumer的实例,它是用于打印出Girl实例的toString信息;最后Consumer消费了Supplier生产的Girl。我们常用的forEach方法入参也是Consumer。使用代码如下:

Supplier<Girl> supplier = ()-> new Girl("lucy",33d,1700d);Consumer<Girl> consumer = (Girl g)->{System.out.println(g.toString());};consumer.accept(supplier.get());ArrayList<Integer> list = Lists.newArrayList(1, 2, 3, 4, 5);list.forEach(System.out::println);

4.Predicate

@FunctionalInterfacepublic interface Predicate<T> {/*** Evaluates this predicate on the given argument.** @param t the input argument* @return {@code true} if the input argument matches the predicate,* otherwise {@code false}*/boolean test(T t);}

可以看到test方法接受一个对象,返回boolean类型,这个函数显然是用来判断真假。那么我们用这个接口来构造一个判断女孩子条件的示例,还有我们常用的stream流中,filter的入参也是Predicate,代码如下:

Supplier<Girl> supplier = ()-> new Girl("lucy",33d,1700d);Predicate<Girl> girl36d = (Girl g)-> Objects.equals(g.getSize(),36d);Predicate<Girl> girl33d = (Girl g)-> Objects.equals(g.getSize(),33d);boolean test33 = girl33d.test(supplier.get());boolean test36 = girl36d.test(supplier.get());System.out.println(supplier.get().getName() +"是否为[36d] :"+test36);System.out.println(supplier.get().getName() +"是否为[33d] :"+test33);

结果为:

lucy是否为[36d] :false

lucy是否为[33d] :true

ArrayList<Girl> list = Lists.newArrayList();list.add(new Girl("露西", 33d, 2000d));list.add(new Girl("格蕾丝", 36d, 3000d));list.add(new Girl("安娜", 28d, 1500d));list.add(new Girl("克瑞斯", 31d, 1800d));Predicate<Girl> greaterThan30d = (Girl g)-> g.getSize()>=30d;list.stream().filter(greaterThan30d).forEach(System.out::println);

结果如下:

Girl(name=露西, size=33.0, price=2000.0)

Girl(name=格蕾丝, size=36.0, price=3000.0)

Girl(name=克瑞斯, size=31.0, price=1800.0)

5.Function

@FunctionalInterfacepublic interface Function<T, R> {/*** Applies this function to the given argument.** @param t the function argument* @return the function result*/R apply(T t);}

这个看到apply接口接收一个泛型为T的入参,返回一个泛型为R的返回值,所以它的用途和Supplier还是略有区别。还是一样我们举个栗子用代码来说明:

Supplier<Girl> supplier = ()-> new Girl("lucy",33d,1700d);Function<Girl,String> girlMark = (Girl g)-> g.getName()+"的尺寸是"+g.getSize()+",每次能赚"+g.getPrice()+"。";System.out.println(girlMark.apply(supplier.get()));

我们可以看到funtion接口接收Girl对象实例,对girl的成员变量进行拼接,返回girl的描述信息。其基本用法就是如此。

lucy的尺寸是33.0,每次能赚1700.0。

6.常用函数式接口相关扩展接口

这里我列举一些Supplier相关接口

a.Supplier相关拓展接口

sumer相关拓展接口

c.Predicate相关拓展接口

d.Function相关的接口

就到这里啦,点赞收藏富婆包养!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。