简介

14年,Oracle公司如期发布了Java 8正式版,Java8提供了强大的流式处理及函数式接口编程

函数式接口编程,相信很多人在javascript中都使用过,比如回调函数,如今Java8也吸收了诸多的其它语言优点。

线程创建(8以前的写法)

        Thread thread = new Thread(new Runnable() {
@Override
public void run() {
System.out.printf(Thread.currentThread().getName());
}
});
thread.start();

Java8的函数式接口写法


//1Java8 lambda表达式写法
Thread thread = new Thread(() -> {
System.out.printf(Thread.currentThread().getName());
});
//对于{}里面只有一条语句的写法
Thread thread1 = new Thread(() -> System.out.println(Thread.currentThread().getName())); //这种写法,不知道各位看官看着是什么感想
Student student = new Student("yang", 2);
new Thread(student::getName);

对比一下


List<Student> list = new ArrayList<>();
list.add(new Student("yang", 20));
list.add(new Student("hehe", 25));
list.add(new Student("jiana", 18));
//对集合进行排序,以前的写法
Collections.sort(list, new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
return o1.getAge() - o2.getAge(); }
}); //Java8 lambda表达式的写法
Collections.sort(list, (o1, o2) -> o1.getAge()-o2.getAge());

Java8函数式编程可以使用lambda表达式,让代码更加简洁高效,当然对于许多如果刚接触的小伙伴来说,如果没有经过学习lambda式的写法,看起来也会云里雾里的,毕竟写法是高效了,但可读性确实要差一些了,对于改bug的同鞋来讲,难度是否又增加许多?

JDK 1.8 API包含了很多内建的函数式接口,在老Java中常用到的比如Comparator或者Runnable接口,这些接口都增加了@FunctionalInterface注解以便能用在lambda上。

标注为FunctionalInterface的接口被称为函数式接口,该接口只能有一个自定义方法,但是可以包括从object类继承而来的方法。如果一个接口只有一个方法,则编译器会认为这就是一个函数式接口。是否是一个函数式接口,需要注意的有以下几点:

1.该注解只能标记在”有且仅有一个抽象方法”的接口上。

2.JDK8接口中的静态方法和默认方法,都不算是抽象方法。

3.接口默认继承java.lang.Object,所以如果接口显示声明覆盖了Object中方法,那么也不算抽象方法。

4.该注解不是必须的,如果一个接口符合”函数式接口”定义,那么加不加该注解都没有影响。加上该注解能够更好地让编译器进行检查。如果编写的不是函数式接口,但是加上了@FunctionInterface,那么编译器会报错。

5.在一个接口中定义两个自定义的方法,就会产生Invalid ‘@FunctionalInterface’ annotation; FunctionalInterfaceTest is not a functional interface错误.

现如今,我们则从Function常用函数入口,真正了解一下。

1.Function:接受一个对象,返回一个对象

  /**
* @param <T> the type of the input to the function
* @param <R> the type of the result of the function
* @since 1.8
*/
@FunctionalInterface
public interface Function<T, R> {
/**
* Applies this function to the given argument.
*
* @param t the function argument
* @return the function result
*/
R apply(T t);
}

Function 内部有一个有一个apply(待子类实现)的方法,调用apply,回传R结果,通过泛型保证apply函数的入参入及返回值的类型。

基本使用:

对数据进行处理将String类型转换成double类型,代码如下:

        //先定义好这个函数功能
Function<String, Double> stringToDouble = ((string) -> Double.parseDouble(string)); //再使用函数功能
System.out.println(stringToDouble.apply("20.25"));

异步回调处理

//将student的名字,通过回调的方式放入name变量中,name变量必须是Atomica类型的,因为交给别人,别人可以用线程来做
public class MainTest {
public static void main(String[] args) {
Student student2 = new Student("yanchuanbin", 25);
AtomicReference<String> name = new AtomicReference<>("");
String otherParams = "";
new Operator(student2).handler(otherParams, (student) -> {
System.out.println("here1 = " + Thread.currentThread().getName());
name.set(student.getName());
return null;
});
}
}
class Operator {
Student student;
public Operator(Student student) {
this.student = student;
}
public void handler(String otherParams, Function<Student, Void> callback) {
System.out.println("here2 = " + Thread.currentThread().getName());
ThreadFactory threadFactory;
ExecutorService executorService = Executors.newSingleThreadExecutor();
executorService.submit(() -> callback.apply(student));
}
}

输出

here2 = main
here1 = pool-1-thread-1

2.Supplier:生产者,无参数,只有返回值

Supplier生产者,提前定义好生产方法,通过get()获取返回值,源码如下

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

作为生产者,基本使用

//        Supplier<Student> supplier2 = new Supplier() {
// @Override
// public Student get() {
// return new Student("aa",new Random().nextInt(20);
// }
// };
Supplier<Student> supplier = () -> new Student("yanchuanbin", 2);
Student student = supplier.get();

3.Consumer:消费者,有入参,但无返回值

Consumer消费者,传入一个参数,消费后无返回值,源码如下

@FunctionalInterface
public interface Consumer<T> { /**
* Performs this operation on the given argument.
*
* @param t the input argument
*/
void accept(T t);

基本使用

        Student student = new Student("yanchuanbin", 25);
//旧写法
// Consumer<Student> consumer = new Consumer<Student>() {
// @Override
// public void accept(Student student) {
// System.out.println(student.getAge());
// }
// };
//lambad写法
Consumer<Student> consumer = (student1 -> System.out.println(student1.getAge()));
consumer.accept(student);

4.Predicate:断言,有参数T,返回固定类型boolean

断言式接口其参数是<T,boolean>,源码如下

@FunctionalInterface
public 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);

基本使用

     Predicate<Student> studentEqualsPredicate = (student) -> student.getAge() > 10;
Student student = new Student("yanchuanbin", 25);
System.out.println(studentEqualsPredicate.test(student));

输出

true

5.UnaryOperator:接收T对象,返回T对象

对对象进行处理,处理后,将原来的对象返回,入参和返回值都是T,源码如下:

@FunctionalInterface
public interface UnaryOperator<T> extends Function<T, T> {
/**
* Returns a unary operator that always returns its input argument.
* @param <T> the type of the input and output of the operator
* @return a unary operator that always returns its input argument
*/
static <T> UnaryOperator<T> identity() {
return t -> t;
}
}

基本使用

     UnaryOperator<Student> identity = (x -> {
return new Student(x.getName(), x.getAge()+1);
}); //生产一个大一岁的哥出来,名字是一样的
Student student1 = identity.apply(student);

6.BinaryOperator:传入两个T对象,返回T对象

继承自BiFunction,传入两个T类型的对象,返回一个T类型的对象,源码如下

   * @param <T> the type of the operands and result of the operator
*
* @see BiFunction
* @see UnaryOperator
* @since 1.8
*/
@FunctionalInterface
public interface BinaryOperator<T> extends BiFunction<T,T,T> {

BiFunction源码如下

@FunctionalInterface
public interface BiFunction<T, U, R> {
/**
* @param t the first function argument
* @param u the second function argument
* @return the function result
*/
R apply(T t, U u);

基本使用

        //传入两个学生,返回两个学生中年龄较大的学生对象
BinaryOperator<Student> getMaxAgeStudentHandler =
(student1, student2) -> student1.getAge() > student2.getAge() ? student1 : student2; Student student1 = new Student("ya",20);
Student student2 = new Student("wa",25); Student maxAgeStudent = getMaxAgeStudentHandler.apply(student1,student2);

java8 API 函数式接口的更多相关文章

  1. [译]Java8的函数式接口

    Java8引入了 java.util.function 包,他包含了函数式接口,具体的描述在以下api说明文档中: 函数式接口为lambda表达式和方法引用提供目标类型.每个函数式接口有一个单独的抽象 ...

  2. java8的函数式接口

    函数式接口 就是在java8里允许你为一个接口(只有一个实现的,声明为FunctionalInterface注解的)实现一个匿名的对象,大叔感觉它与.net平台的委托很类似,一个方法里允许你接收一个方 ...

  3. JAVA8之函数式接口

    由于JDK8已经发布一段时间了,也开始逐渐稳定,未来使用JAVA语言开发的系统会逐渐升级到JDK8,因为为了以后工作需要,我们有必要了解JAVA8的一些新的特性.JAVA8相对JAVA7最重要的一个突 ...

  4. Java8 Functional(函数式接口)

    Functional 函数式(Functional)接口 只包含一个抽象方法的接口,称为函数式接口. 你可以通过 Lambda 表达式来创建该接口的对象.(若 Lambda 表达式抛出一个受检异常(即 ...

  5. java8 常用函数式接口

    public static void main(String[] args) { // TODO Auto-generated method stub //函数式接口 Function<Inte ...

  6. Java8常见函数式接口总结

    函数式接口 函数式接口:有且仅有一个抽象方法的接口. 使用@FunctionalInterface注解来标记.如果接口不是函数式接口就会编译出错 满足条件的接口即使不加上注解,那也是函数式接口 函数式 ...

  7. JDK1.8新特性(一) ----Lambda表达式、Stream API、函数式接口、方法引用

    jdk1.8新特性知识点: Lambda表达式 Stream API 函数式接口 方法引用和构造器调用 接口中的默认方法和静态方法 新时间日期API default   Lambda表达式     L ...

  8. 乐字节-Java8核心特性实战之函数式接口

    什么时候可以使用Lambda?通常Lambda表达式是用在函数式接口上使用的.从Java8开始引入了函数式接口,其说明比较简单:函数式接口(Functional Interface)就是一个有且仅有一 ...

  9. java8学习之Supplier与函数式接口总结

    Supplier接口: 继续学习一个新的函数式接口--Supplier,它的中文意思为供应商.提供者,下面看一下它的javadoc: 而具体的方法也是相当的简单,就是不接受任何参数,返回一个结果: 对 ...

  10. java代码之美(14)---Java8 函数式接口

    Java8 函数式接口 之前写了有关JDK8的Lambda表达式:java代码之美(1)---Java8 Lambda 函数式接口可以理解就是为Lambda服务的,它们组合在一起可以让你的代码看去更加 ...

随机推荐

  1. 基于容器服务 ACK 发行版打造 CNStack 社区版

    ​简介:本文将介绍如何使用 ACK Distro 作为基础镜像打造 CNStack 社区版以及CNStack 社区版中的容器服务 ACK 敏捷版产品如何帮助用户更好的使用容器平台能力. 作者:临石 C ...

  2. KubeVela 1.0 :开启可编程式应用平台的未来

    简介: 如果你对云原生领域不太关注,可能对 KubeVela 还没有做过太深入的了解.别着急,本文就借着 v1.0 发布之际,为你详细的梳理一次 KubeVela 项目的发展脉络,解读它的核心思想和愿 ...

  3. [Caddy2] The Caddy Web Server 常见 Caddyfile 模式

    Caddyfile 是 JSON 配置的易用写法,支持通常用的功能,完整功能还是需要 JSON 配置的. 以下适用于 Caddy2 版本的配置. 静态文件服务器 example.com root * ...

  4. WPF 已知问题 dotnet 6 设置 InvariantGlobalization 之后将丢失默认绑定转换导致 XAML 抛出异常

    在设置了 InvariantGlobalization 为 true 之后,将会发现原本能正常工作的 XAML 可能就会抛出异常.本文将告诉大家此问题的原因 这是有开发者在 WPF 仓库上给我报告的 ...

  5. 推荐一款轻量级堡垒机系统让你防护“rm -rf 删库跑路”

    大家好,我是 Java陈序员. 我们在开发工作中,会经常与服务器打交道,而服务器的资源又是十分宝贵,特别是服务器里面的数据资源. 但是,偶尔会经常因为疏忽而导致服务器数据资源丢失,给自己和公司带来巨大 ...

  6. 05.Java 方法详解

    1.方法的定义及调用 设计方法的原则:一个方法只完成一个功能,有利于后期的扩展 方法的定义: 修饰符(可选) 返回值类型 方法名(参数类型 参数名(可选)){ 方法体 return 返回值; } 2. ...

  7. Linux中的find

    find命令在硬盘上进行文件的查找,比起whereis与locate会比较耗时. 与时间有关的选项 在Linux当中一个文件有mtime,ctime,atime,find在搜索时可以配置这3种时间. ...

  8. String.split()遇到空字符串不解析的情况

    1.split的api说明 stringObj.split([separator,[limit]]) stringObj:要被分解的 String separator:字符串或正则表达式对象 limi ...

  9. 微信小程序关于小说类使用官方阅读器

    https://doc.weixin.qq.com/doc/w3_AAcAYAbdAFwpM63n1R5SIat3aa4cX?scode=AJEAIQdfAAoYHVCBbdAG4A1QYmAFQ 上 ...

  10. 小程序 image 高度自适应及裁剪问题

    在做微信小程序的商品详情页,商品的详情是图片集合,渲染完成后发现图片加载的很不自然,后来我把样式设置宽度 100%,并对 image 组件添加属性 mode="widthFix"解 ...