day16 jdk1.8新特性-1

函数式接口

函数式接口是指有且只有一个抽象方法,但是可以有多个非抽象方法的接口

格式

修饰符	interface 接口名称{
	public abstract 返回值类型 (参数列表);
	//其他非抽象方法的内容
	
}

@FunctionalInterface注解

与 @Override 注解的作用类似,Java 8中专门为函数式接口引入了一个新的注解: @FunctionalInterface 。该注 解可用于一个接口的定义上:

@FunctionalInterface 
public interface MyFunctionalInterface { 
	void myMethod();      
}

一旦使用该注解来定义接口,编译器将会强制检查该接口是否确实有且仅有一个抽象方法,否则将会报错。需要注 意的是,即使不使用该注解,只要满足函数式接口的定义,这仍然是一个函数式接口,使用起来都一样。

函数式接口可以作为方法的参数和返回值

public class Demo09FunctionalInterface {     
	// 使用自定义的函数式接口作为方法参数      
	private static void doSomething(MyFunctionalInterface inter) {      
		inter.myMethod(); // 调用自定义的函数式接口方法          
	}           
	public static void main(String[] args) {      
	// 调用使用函数式接口的方法          
		doSomething(()> System.out.println("Lambda执行啦!"));          
	}      
}

Lambda表达式的性能优化

Lambda的特点:延迟加载
Lambda的使用前提,必须存在函数式接口

定义一个函数式接口

@FunctionalInterface
public interface MessageBuilder{
	//定义一个抽象方法来返回字符串的信息
	public abstract String builderMessage();
}

使用Lambda优化日志案例

public class Demo02Lambda {
    //定义一个显示日志的方法,方法的参数传递日志的等级和
    // MessageBuilder接口
    public static void showLog(int level, MessageBuilder mb){
        //对日志的等级进行判断,如果是1级,则调用MessageBuilder接口中的builderMessage方法
        if(level==1){
            System.out.println(mb.builderMessage());
        }
    }
	public static void main(String[] args) {
        //定义三个日志信息
        String msg1 = "Hello";
        String msg2 = "World";
        String msg3 = "Java";
		/*
		使用Lambda表达式作为参数传递,仅仅是把参数传递到showLog方法中
		只有满足条件,日志的等级是1级
		才会调用接口MessageBuilder中的方法builderMessage
		才会进行字符串的拼接
		如果条件不满足,日志的等级不是1级
		那么MessageBuilder接口中的方法builderMessage也不会执行
		所以拼接字符串的代码也不会执行
		所以不会存在性能的浪费
		*/
			showLog(1,()->{
            System.out.println("不满足条件不执行");
            //返回一个拼接好的字符串
            return  msg1+msg2+msg3;
        });
    }
}

常用的函数式接口

Supplier接口

java.util.function.Supplier接口仅包含一个无参的方法:T get()。
用来获取一个泛型参数指定类型的对象数据。

Supplier接口被称之为生产型接口,指定接口的泛型是什么类型,那么接口中的get方法就会生产什么类型的数据

public class Demo01Supplier {
    //定义一个方法,方法的参数传递Supplier<T>接口,泛型执行String,get方法就会返回一个String
    public static String getSupplier(Supplier<String> sup){
        return sup.get();
    }
    public static void main(String[] args) {
        //调用getSupplier方法,因为参数是Supplier接口,所以可以使用Lambda表达式
        String s1=getSupplier(()->{
            return "小明";
        });
        //优化Lambda表达式
        String s2 = getSupplier(() -> "小美");
        System.out.println(s1+s2);
    }
}

Consumer接口

java.util.function.Consumer接口则正好与Supplier接口相反,它不是生产一个数据,而是消费一个数据,其数据类型由泛型决定。

Consumer接口中包含抽象方法

  • void accept(T t),意为消费一个指定泛型的数据。

Consumer接口是一个消费型接口,泛型执行什么类型,就可以使用accept方法消费什么类型的数据
至于具体怎么消费(使用),需要自定义(输出,计算…)

public class Demo01Consumer {
    /*
        定义一个方法
        方法的参数传递一个字符串的姓名
        方法的参数传递Consumer接口,泛型使用String
        可以使用Consumer接口消费字符串的姓名
     */
    public static void method(String name, Consumer<String> con){
        con.accept(name);
    }

    public static void main(String[] args) {
        //调用method方法,传递字符串姓名,方法的另一个参数是Consumer接口,是一个函数式接口,所以可以传递Lambda表达式
        method("赵丽颖",(String name)->{
            //对传递的字符串进行消费
            //消费方式:直接输出字符串
            //System.out.println(name);

            //消费方式:把字符串进行反转输出
            String reName = new StringBuffer(name).reverse().toString();
            System.out.println(reName);
        });
    }
}

知识点:

  1. Consumer接口中泛型用的什么数据类型,其中的accept方法就消费什么数据类型,具体怎么消费要看具体的情况,以上代码数据类型是字符串,使用消费方式是直接输出
  2. 因为方法参数传递的是Consumer函数式接口,所以可以使用Lambda表达式
  3. StringBuffer类线程安全,可变的字符序列。 字符串缓冲区就像一个String ,但可以修改。 在任何时间点,它包含一些特定的字符序列,但可以通过某些方法调用来更改序列的长度和内容。
    字符串缓冲区可以安全地被多个线程使用。
    构造方法
    -StringBuffer(String str) 构造一个初始化为指定字符串内容的字符串缓冲区。
    成员方法
    -StringBuffer reverse() 导致该字符序列被序列的相反代替。
    -String toString() 返回表示此顺序中的数据的字符串。

Consumer接口的默认方法andThen
作用:需要两个Consumer接口,可以把两个Consumer接口组合到一起,在对数据进行消费

例如:
Consumer con1
Consumer con2
String s = “hello”;
con1.accept(s);
con2.accept(s);
连接两个Consumer接口 再进行消费
con1.andThen(con2).accept(s); 谁写前边谁先消费

Predicate接口

java.util.function.Predicate接口
作用:对某种数据类型的数据进行判断,结果返回一个boolean值

Predicate接口中包含一个抽象方法:

  • boolean test(T t):用来对指定数据类型数据进行判断的方法
    结果:
    符合条件,返回true
    不符合条件,返回false

方法and()、or()和negate()

逻辑表达式:可以连接多个判断的条件
&&:与运算符,有false则false
||:或运算符,有true则true
!:非(取反)运算符,非真则假,非假则真

需求:判断一个字符串,有两个判断的条件
1.判断字符串的长度是否大于5
2.判断字符串中是否包含a
两个条件必须同时满足,我们就可以使用&&运算符连接两个条件

Predicate接口中有一个方法and,表示并且关系,也可以用于连接两个判断条件
源码

default Predicate<T> and(Predicate<? super T> other) {
	Objects.requireNonNull(other);
	return (t) -> this.test(t) && other.test(t);
}

方法内部的两个判断条件,也是使用&&运算符连接起来的

Predicate接口中有一个方法or,表示或者关系,也可以用于连接两个判断条件
源码

default Predicate<T> or(Predicate<? super T> other) {
	Objects.requireNonNull(other);
	return (t) -> test(t) || other.test(t);
}

方法内部的两个判断条件,也是使用||运算符连接起来的

Predicate接口中有一个方法negate,也表示取反的意思

default Predicate<T> negate() {
    return (t) -> !test(t);
}

Function<T,R>接口

java.util.function.Function<T,R>接口用来根据一个类型的数据得到另一个类型的数据,
前者称为前置条件,后者称为后置条件。
Function接口中最主要的抽象方法为:

  • R apply(T t),根据类型T的参数获取类型R的结果。
    使用的场景例如:将String类型转换为Integer类型。
    Function接口中的默认方法
  • andThen:用来进行组合操作
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值