java 8新特性学习系列(1):函数式接口

函数式接口

Java8 引入的一个核心概念是函数式接口(Function Interfaces). 通过在接口里面添加一个抽象方法,这些方法可以直接从接口中运行.如果一个接口定义一个唯一的抽象方法,那么这个接口就称为函数式接口.同时,引入了一个新的注解: @FunctionInterface. 可以把它放在一个接口前,表示这个接口是一个函数式接口.这个注解是非必须的,只要接口只包含一个方法,虚拟机会自动判断,不过最好添加注解进行声明,声明之后只允许有一个抽象方法,否则编译器会报错.

java.lang.Runnable 就是一个函数式接口.

@FunctionalInterface
public 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.
     *
     * @see     java.lang.Thread#run()
     */
    public abstract void run();
}

声明一个接口:

 @FunctionalInterface
   public interface  func{
    }

编译报错,no target method ,增加一个方法:

@FunctionalInterface
   public interface  func{
        void dosome();
    }

这就是一个函数式接口,如果再加一个方法??

 @FunctionalInterface
   public interface  func{
        void dosome();
        void doanother();
    }

会报错,因为声明函数式接口只能有一个抽象方法.

 @FunctionalInterface
   public interface  func{
        @Override
        boolean equals(Object o);
        void dosome();
    }

这种包含两个方法的也是可以的.因为equals方法是Object的public方法,但是只能增加Object的public方法,其他方法是不行的.例如:

 @FunctionalInterface
   public interface  func{
        @Override
        Object clone();
        void dosome();
    }

会报错,因为需要Object的public方法,但是clone方法是protected的.

函数式接口,有且只能有一个抽象方法,Object的public方法除外.

package com.lxq;

/**
 * Hello world!
 *
 */
public class App
{
    public static void main(String args[]){
        App tester = new App();

        // 带有类型声明的表达式
        MathOperation addition = (int a, int b) -> a + b;

        // 没有类型声明的表达式
        MathOperation subtraction = (a, b) -> {return a - b;};

        // 带有大括号、带有返回语句的表达式
        MathOperation multiplication = (int a, int b) -> { return a * b; };

        // 没有大括号和return语句的表达式
        MathOperation division = (int a, int b) -> a / b;

        // 输出结果
        System.out.println("10 + 5 = " + tester.operate(10, 5, addition));
        System.out.println("10 - 5 = " + tester.operate(10, 5, subtraction));
        System.out.println("10 x 5 = " + tester.operate(10, 5, multiplication));
        System.out.println("10 / 5 = " + tester.operate(10, 5, division));

        // 没有括号的表达式
        GreetingService greetService1 = message ->
                System.out.println("Hello " + message);

        // 有括号的表达式
        GreetingService greetService2 = (message) ->
                System.out.println("Hello " + message);

        // 调用sayMessage方法输出结果
        greetService1.sayMessage("Shiyanlou");
        greetService2.sayMessage("Classmate");
    }

    // 下面是定义的一些接口和方法
    @FunctionalInterface
    interface MathOperation {
        int operation(int a, int b);
    }
    @FunctionalInterface
    interface GreetingService {
        void sayMessage(String message);
    }

    private int operate(int a, int b, MathOperation mathOperation){
        return mathOperation.operation(a, b);
    }

}

输出结果:

10 + 5 = 15
10 - 5 = 5
10 x 5 = 50
10 / 5 = 2
Hello Shiyanlou
Hello Classmate

四大内置核心接口

  • Predicate 函数式接口
  • Function 函数式接口
  • Consumer 函数式接口
  • Supplier 函数式接口

(1)Predicate 函数式接口

1.Predicate的基本使用

public class Main{

   @Test
    public void test(){
        List<String> list = Arrays.asList("hEOs","AJssS","dsddss","ww");
        List<String> strlist = filterStr(list,(s)->s.length()>3);
    }

    // 需求:将满足条件的字符串放到集合中
    public List<String> filterStr(List<String> list, Predicate<String> pre){
        List<String> strlist = new ArrayList<>();

        for(String str:list){
            if(pre.test(str)){
                strlist.add(str);
            }
        }
        return strlist;
    }
}

2. Predicate的默认方法and、or、negate(取反)

public class Main{

    public static void main(String[] args){
        Predicate<Integer> p1 = age -> age>18;
        Predicate<Integer> p2 = age -> age<30;
        //其实就是表达式(age -> age>18)&&(age -> age<30)赋值给and
        Predicate<Integer> and = p1.and(p2);   
        boolean test1 = and.test(20);  //返回p1和p2的与结果
        out.println(test1);    //输出true
    }
}  

(2)Function 函数式接口

1.Function基本使用

public class Main{

   @Test
    public void test(){
        String newStr = steHandler("这个是  测试  的..",(str)-> str.trim());
        System.out.print(newStr);

        String newStr1 = steHandler("这个是测试的",(str)-> str.substring(0,3));
        System.out.print(newStr1);
    }

    // 需求:用于处理字符串
    public String steHandler(String str, Function<String,String> fun){
        return fun.apply(str);
    }
}  

2.Function的默认方法andThen(协作)

public class Main{

    public static void main(String[] args){
        //f1参数为String,结果为Boolean
        Function<String,Boolean> f1 = s1 -> s1!=null;   
        Function<Boolean,Integer> f2 = b -> b?1:0;

        //将f1的布尔值结果作为f2函数式接口的参数来传递
        //所以stringIntegerFunction接收值为f1的参数类型String,返回值类型为f2的返回类型Integer
        Function<String,Integer> stringIntegerFunction = f1.andThen(f2);

        Integer apply = stringIntegerFunction.apply("111");
        out.println(apply);  //输出1
    }
} 

(3)Consumer 函数式接口

1.Consumer的基本使用

public class ConsumerTest {
    public static void main(String[] args) {
        Consumer<Integer> consumer = (x) -> {
            int num = x * 5;
            System.out.println(num);
        };
        Consumer<Integer> consumer1 = (x) -> {
            int num = x * 6;
            System.out.println(num);
        };
        consumer.andThen(consumer1).accept(10);
    }
}

(4) Supplier函数式接口

1.supplier的基本使用

public class Main{

   @Test
    public void test(){
        List<Integer> list = getNumList(10,()->(int)Math.random()*100);
    }

    // 需求:产生指定个数的整数,并放入集合中
    public List<Integer> getNumList(int num, Supplier<Integer> sup){
        List<Integer> list = new ArrayList<>();

        for(int i=0;i<num;i++){
            Integer e = sup.get();
            list.add(e);
        }
        return list;
    }
}  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值