jdk8新特性-Lambda表达式及函数式接口

  1. 在多线程方面,Lambda表达式的使用
  • 不使用Lambda表达式的情况下,开启多线程的方式
/*
测试:开启多线程,打印数据
结论:不使用函数式编程带来冗余
 */
public class Demo01Runnable {
    public static void main(String[] args) {
        //使用Runnable的实现类,完成方法调用
        RunnableImpl r = new RunnableImpl();
        Thread t = new Thread(r);
        t.start();
        //使用匿名内部类简化编码
        Runnable r2 = new Runnable() {
            @Override
            public void run() {
                System.out.println("匿名内部类的方式开启多线程...run...");
            }
        };
        new Thread(r2).start();
        //进一步简化
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("匿名内部类的方式开启多线程2...run...");
            }
        }).start();
    }
}
  • 使用Lambda表达式实现多线程方法调用
/*
    Lambda表达式的标准格式:
        三部分组成:一些参数,一个箭头,一段代码
        格式:
            (参数列表)->{一些重写方法的代码}
 */
/*
    Lambda表达式是可推导,可省略的
    省略的内容:
        1.(参数列表):括号中的参数列表的数据类型可以省略
        2.(参数列表):若括号中参数只有一个,那么类型和()都可以省略
        3.{一些代码}:若{}中的代码只有一行,无论是否有返回值,都可以省略 {},return,分号
            注意:必须一起省略
 */
public class Demo02Lambda {
    public static void main(String[] args) {
        //使用匿名内部类的方式实现多线程
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("匿名内部类...run...");
            }
        }).start();
        //使用Lambda表达式实现多线程
        new Thread(()->{
            System.out.println("Lambda表达式...run...");
        }).start();
        //省略的Lambda表达式
        new Thread(()->System.out.println("Lambda表达式...run...")).start();
    }
}
  1. 自定义接口,并使用Lambda表达式的方式调用
  • 自定义接口
public interface Cook {
    public abstract void makeFood();
}
  • 使用Lambda表达式调用自定义接口
/*
    练习:给定一个Cook接口,内含唯一抽象方法makeFood,无参无返回值。
    使用Lambda的格式调用invokeCook方法,打印数据
 */
public class Demo01Cook {
    public static void main(String[] args) {
        //匿名内部类的方式
        invokeCook(new Cook() {
            @Override
            public void makeFood() {
                System.out.println("makeFood1...");
            }
        });
        //Lambda表达式
        invokeCook(()->{
            System.out.println("makeFood2...");
        });
        //省略的Lambda表达式
        invokeCook(()->System.out.println("makeFood3..."));
    }

    public static void invokeCook(Cook cook){
        cook.makeFood();
    }
}
  1. 实现使用Lambda表达式,对对象中某个属性进行排序的功能
  • 对象JavaBean
public class Person {
    private String name;
    private Integer age;

    public Person() {
    }

    public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
  • 使用Lambda表达式的方式对JavaBean进行排序
import java.util.Arrays;

/*
    Lambda表达式有参数有返回值练习:使用数组存储多个Person对象,
    对数组中的Person对象按照age升序(前-后)排序
 */
public class Demo01Arrays {
    public static void main(String[] args) {
        Person[] arr = {
                new Person("yorick",23),
                new Person("tom",12),
                new Person("jerry",16)
        };
        //使用匿名内部类的方式
       /* Arrays.sort(arr, new Comparator<Person>() {
            @Override
            public int compare(Person o1, Person o2) {
                return o1.getAge()-o2.getAge();
            }
        });*/
        //使用Lambda表达式
       /* Arrays.sort(arr,(Person o1,Person o2)->{
            return o1.getAge()-o2.getAge();
        });*/
        //省略的Lambda表达式
        Arrays.sort(arr,(o1,o2)->o1.getAge()-o2.getAge());
        for (Person person : arr) {
            System.out.println(person);
        }
    }
}
  1. 自定义接口,使用Lambda表达式调用,有参数的练习
  • 自定义接口
public interface Calculator {
    public abstract Integer calc(int a,int b);
}
  • 使用Lambda表达式,调用自定义接口
/*
    Lambda有参数有返回值练习:给定一个Calculator接口,内含抽象方法calc计算两数之和,
    使用Lambda表达式调用invokeCalc方法
 */
public class Demo01Calculator {
    public static void main(String[] args) {
        //使用匿名内部类
        invokeCalc(10, 20, new Calculator() {
            @Override
            public Integer calc(int a, int b) {
                return a+b;
            }
        });
        //使用Lambda表达式
        invokeCalc(120,130,(int a,int b)->{
            return a+b;
        });
        //简化的Lambda表达式
        invokeCalc(220,230,(a,b)->a+b);
    }

    public static void invokeCalc(int a,int b,Calculator calculator){
        int result = calculator.calc(a,b);
        System.out.println(result);
    }
}

常用函数式接口

  1. Supplier接口
  • Supplier接口的简单使用
/*
    Supplier<T>接口仅包含一个无参方法:T get() 用于获取一个泛型参数指定类型的对象数据。
    用处:
        该接口称为生产型接口,指定接口的泛型,get方法就会生成什么类型的数据
 */
public class Demo01Supplier {
    public static void main(String[] args) {
        String result = getString(()->"你好");
        System.out.println(result);
    }

    public static String getString(Supplier<String> supplier){
        return supplier.get();
    }
}
  • 使用Supplier接口的案例
import java.util.function.Supplier;

/*
    练习:使用Supplier接口求数组元素的最大值
 */
public class Demo02SupplierGetMax {
    public static void main(String[] args) {
        //定义一组数据
        Integer[] arr = {10,23,-10,0,66};
        //调用getMax方法,方法的参数Supplier是一个函数式接口
        Integer result = getMax(()->{
            int max = arr[0];
            for (Integer i : arr) {
                if(i>max){
                    max = i;
                }
            }
            return max;
        });
        System.out.println(result);
    }

    public static Integer getMax(Supplier<Integer> supplier){
        return supplier.get();
    }
}
  1. Consumer接口
  • Consumer接口简单使用
import java.util.function.Consumer;

/*
    Consumer<T>接口与Supplier接口相反,包含抽象方法 void accept(T t),用于消费一个指定泛型的数据
    用途:
        Consumer是一个消费型接口,泛型是什么类型就可以通过accept方法消费什么类型的数据,
        如何消费可以自己在Lambda表达式中定义
 */
public class Demo01Consumer {
    public static void main(String[] args) {
        method("yorick",(String name)->{
            System.out.println(name);
            //反转字符串
            String reName = new StringBuffer(name).reverse().toString();
            System.out.println(reName);
        });
    }

    public static void method(String name,Consumer<String> consumer){
        consumer.accept(name);
    }
}
  • Consumer的andThen默认方法使用
import java.util.function.Consumer;

/*
    Consumer的默认方法andThen
    作用:需要两个Consumer接口,把两个Consumer接口组合到一起,再对数据进行消费
       若con1连接con2,则con1先消费数据,con2再消费数据
 */
public class Demo02andThen {
    public static void main(String[] args) {
        method("Yorick",
                (name)->{
                    System.out.println(name.toUpperCase());
                },
                (name)->{
                    System.out.println(name.toLowerCase());
                });
    }

    public static void method(String name, Consumer<String> consumer1,Consumer<String> consumer2){
        //不使用andThen方法
        /*consumer1.accept(name);
        consumer2.accept(name);*/
        //使用andThen方法
        //consumer1.andThen(consumer2).accept(name);
        //使用andThen方法 先消费consumer2
        consumer2.andThen(consumer1).accept(name);
    }
}
  • 使用Consumer接口的案例
import java.util.function.Consumer;

/*
    练习:
        使用Consumer接口,将字符串数组中多条信息按照"姓名:xx,性别:xx"的格式打印
 */
public class Demo03StringSplit {
    public static void main(String[] args) {
        //定义一个字符串数组
        String[] arr = {"yorick,boy","tom,boy","lucy,girl"};
        //Lambda表达式实现功能
        method(arr,
                (message)->{
                    String name = message.split(",")[0];
                    System.out.print("姓名:"+name);
                },
                (message)->{
                    String gender = message.split(",")[1];
                    System.out.println(",性别:"+gender);
                });
    }

    public static void method(String[] arr, Consumer<String> consumer1,Consumer<String> consumer2){
        for (String message : arr) {
            consumer1.andThen(consumer2).accept(message);
        }
    }
}
  1. Predicate接口
  • Predicate接口简单使用
import java.util.function.Predicate;

/*
    Predicate<T>接口,包含一个抽象方法 boolean test(T t) 用来对指定数据类型数据进行判断的方法
       作用:对某种数据类型的数据进行判断,结果返回一个boolean值
            结果:符合条件,true;不符合条件,false
 */
public class Demo01Predicate {
    public static void main(String[] args) {
        String str = "yorick";
        /*Boolean result = checkString(str,(String s)->{
            return s.length()>5;
        });*/
        //简化
        Boolean result = checkString(str,s->s.length()>5);
        System.out.println(result);
    }

    public static Boolean checkString(String str, Predicate<String> predicate){
        return predicate.test(str);
    }
}
  • Predicate接口的默认方法and的使用
import java.util.function.Predicate;

/*
    案例:
        使用and连接两个Predicate
        满足:1.长度大于5
             2.包含字母y
 */
public class Demo02PredicateAnd {
    public static void main(String[] args) {
        String str = "yorick";
        Boolean result = checkString(str,
                (String s)->{
                    //长度大于5
                    return s.length()>5;
                },(String s)->{
                    //包含字母y
                    return s.contains("y");
                });
        System.out.println(result);
    }

    public static Boolean checkString(String str, Predicate<String> predicate1,Predicate<String> predicate2){
        return predicate1.and(predicate2).test(str);//等价于 return predicate1.test(str) && predicate2.test(str);
    }
}
  • 使用Predicate接口的案例
import java.util.ArrayList;
import java.util.function.Predicate;

/*
    练习:集合信息筛选,通过Predicate接口实现对字符串数组进行筛选的功能,
    需要同时满足的条件:
        1.必须为male
        2.姓名字母5个以上
 */
public class Demo03PracticeTest {
    public static void main(String[] args) {
        //定义一个字符串数组
        String[] str = {"yorick,male","tom,male","torasa,female","jackson,male"};
        //调用方法进行筛选
        ArrayList<String> list = filter(str, (String s) -> {
            return s.split(",")[0].length() > 5;
        }, (String s) -> {
            return s.split(",")[1].equals("male");
        });
        //遍历结果
        for (String s : list) {
            System.out.println(s);
        }
    }
    public static ArrayList<String> filter(String[] str, Predicate<String> pre1,Predicate<String> pre2){
        ArrayList<String> result = new ArrayList<>();
        for (String s : str) {
            boolean flag = pre1.and(pre2).test(s);
            if(flag == true){
                result.add(s);
            }
        }
        return result;
    }
}
  1. Function接口
  • Function接口的简单使用
import java.util.function.Function;

/*
    Function<T,R>接口用来根据一个类型的数据得到另一个类型的数据。
    前者称为前置条件,后者称为后置条件
    Function接口的主要抽象方法为:R apply(T t) 根据类型T的参数获取类型R的结果
 */
//将String类型转换为Integer类型
public class Demo01Function {
    public static void main(String[] args) {
        StringToInteger("233",s->Integer.parseInt(s));
    }
    public static void StringToInteger(String s, Function<String,Integer> fun){
        Integer result = fun.apply(s);
        System.out.println(result);
    }
}
  • Function接口的默认方法andThen使用
import java.util.function.Function;

/*
    Function接口的默认方法andThen用来进行组合操作

    需求:把String类型的"233"转换为Integer类型并结果+10,
    把增加之后的Integer类型的数据再转换为String类型
 */
public class Demo02AndThen {
    public static void main(String[] args) {
        /*change("233",(String s)->{
            return Integer.parseInt(s)+10;
        },(Integer i)->{
            return i+"";
        });*/
        //简化Lambda表达式
        change("233",s->Integer.parseInt(s)+10,i->i+"");
    }

    public static void change(String s, Function<String,Integer> fun1,Function<Integer,String> fun2){
        String result = fun1.andThen(fun2).apply(s);
        System.out.println(result);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

攻城老湿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值