4.2多线程--lambda表达式

一、概念理解

  • 避免内部类定义过多,只留下核心代码
  • 属于函数式变成的概念
    • (params) -> expression[表达式]
    • (params) -> statement[语句]
    • (params) -> {statements}
      a -> System.out.println("i like lambda-->"+a);
      new Thread(()->System.out.println("多线程学习。。。")).start();

二、条件

  • Functional Interface(函数式接口)
    • 任何接口,如果只包含唯一一个抽象方法,那么他就是一个函数是借口。
    • 可以通过lambda表达式创建该接口的对象
@FunctionalInterface//函数式接口注解,只能有一个抽象方法;
public interface Runnable{
  public abstract void run();
}

JAVA8 中增加了一个新特性:default ,接口中非强制实现的方法;

三、跟着代码走

1. lambda 表达式的由来

/*
传统的方式
 */
public class Demo01 {
    public static void main(String[] args) {
        //3、创建类的实例,并调用方法
        Like iLike = new ILike();
        iLike.lambda();
    }
}

//1、一个函数式接口
interface Like{
    void lambda();
}

//2、实现类
class ILike implements Like{
    @Override
    public void lambda(){
        System.out.println("i lile lambda");
    }
}
/*
进化一:静态内部类
 */
public class Demo02 {

    //2、实现类
    static class ILike implements Demo02Like{
        @Override
        public void lambda(){
            System.out.println("i lile lambda2");
        }
    }

    public static void main(String[] args) {
        //3、创建类的实例,并调用方法
        Demo02Like iLike = new ILike();
        iLike.lambda();
    }
}

//1、一个函数式接口
interface Demo02Like{
    void lambda();
}
/*
进化二:局部内部类
 */
public class Demo03 {

    public static void main(String[] args) {
        //2、实现类
        class ILike implements Demo03Like{
            @Override
            public void lambda(){
                System.out.println("i lile lambda3");
            }
        }

        //3、创建类的实例,并调用方法
        Demo03Like iLike = new ILike();
        iLike.lambda();
    }
}

//1、一个函数式接口
interface Demo03Like{
    void lambda();
}
/*
进化三:匿名内部类
 */
public class Demo04 {
    public static void main(String[] args) {
        //2、创建匿名内部类
        Demo04Like iLike = new Demo04Like(){
            @Override
            public void lambda() {
                System.out.println("i like lambda4");
            }
        };
        iLike.lambda();
    }
}

//1、一个函数式接口
interface Demo04Like{
    void lambda();
}
/*
进化四:lambda
 */
public class Demo05 {
    public static void main(String[] args) {
        Demo05Like iLike = ()->{
            System.out.println("i like lambda5");
        };
        iLike.lambda();
    }
}

//1、一个函数式接口
interface Demo05Like{
    void lambda();
}

2. lambda 表达式的简化

/*
简化带一个参数的lambda
 */
public class Demo06 {
    public static void main(String[] args) {
        Demo06Like iLike = null;
        iLike = (int a)->{
            System.out.println("i like "+ a);
        };
        iLike.like(1);

        //简化一(参数类型可以不写,JVM 编译器的“类型推断”)
        iLike = (a)->{
            System.out.println("i like "+ a);
        };
        iLike.like(2);
        // 类型推断:
        // String[] strs = {"aaa","bbb","ccc"}; 没问题
        // String[] strs;
        // strs = {"aaa","bbb","ccc"}; 有问题,推断不出来了;

        //简化二
        iLike = a->{
            System.out.println("i like "+ a);
        };
        iLike.like(3);

        //简化三
        iLike = a->System.out.println("i like "+ a);
        iLike.like(4);
    }
}

interface Demo06Like{
    void like(int a);
}
/*
简化带多个参数的lambda
 */
public class Demo07 {
    public static void main(String[] args) {
        Demo07Like iLike = null;
        iLike = (int a,int b)->{
            System.out.println("i like "+ a + "&"+b);
        };
        iLike.like(1,2);

        //简化一
        iLike = (a,b)->{
            System.out.println("i like "+ a + "&"+b);
        };
        iLike.like(3,4);

        //简化二
        iLike = (a,b)->System.out.println("i like "+ a + "&"+b);
        iLike.like(5,6);
    }
}

interface Demo07Like{
    void like(int a,int b);
}

3. 方法引用

3.1 普通方法引用
/*
方法引用:
1. 可以快速将一个 lambda 表达式的实现指向一个已经实现的方法;
2. 语法:方法的隶属者::方法名  (隶属者:静态方法--类、非静态方法--实例);
               类::静态方法;
               实例::非静态方法;
               类::非静态方法;(这种有前提,两个参数,第一个参数是方法调用者,第二个参数是方法的参数);
               例子:BiPredicate<String,String> bp = (x,y) -> s.equals(y);
                          BiPredicate<String,String> bp = String::equals;
注意:
1. 参数数量和类型 要与 接口中抽象方法的一致;
2. 返回值的类型 要与 接口中抽象方法的一致;
 */
public class Demo08 {
    public static void main(String[] args) {
        Demo07Like iLike = null;

        Demo08Change demo08Change = (a,b)->sum(a,b);
        int result = demo08Change.change(1,2);
        System.out.println(result);

        Demo08Change demo08Change1 = Demo08::sum;
        int result1 = demo08Change1.change(3,2);
        System.out.println(result1);
    }

    public static int sum(int a,int b){
        return a + b;
    }
}

@FunctionalInterface
interface Demo08Change{
    int change(int a, int b);
}
3.2 构造方法引用
/*
方法引用--构造方法:
 */
public class Demo09 {
    public static void main(String[] args) {
        PersonFactory1 person1 = Person::new;
        person1.getPerson();

        PersonFactory2 person2 = Person::new;
        person2.getPerson("张三",10);
    }
}
@FunctionalInterface
interface PersonFactory1{
    Person getPerson();
}
@FunctionalInterface
interface PersonFactory2{
    Person getPerson(String name,Integer age);
}
class Person{
    String name;
    Integer age;

    Person(){
        System.out.println("Person 类的无参构造方法执行了");
    }

    Person(String name,Integer age){
        this.name = name;
        this.age = age;
        System.out.println("Person 类的有参构造方法执行了");
    }
}
3.3 数组引用
Function<Integer,String[]> fun = (x) -> new String[x];
String[] strs = fun.apply(10);

Function<Integer,String[]> fun1 = String[]::new;
String[] strs1 = fun1.apply(20);

四、综合案例

案例一:集合排序,ArrayList
public class Demo01 {
    public static void main(String[] args) {
        ArrayList<Person> list = new ArrayList<>();
        list.add(new Person("小红",1));
        list.add(new Person("小明",4));
        list.add(new Person("小王",3));
        list.add(new Person("小李",6));
        list.add(new Person("小张",2));
        list.add(new Person("老王",7));
        list.add(new Person("老李",4));
        list.add(new Person("老张",7));
        list.add(new Person("张总",9));
        list.add(new Person("王副总",10));
        // 方式1
        list.sort(new Comparator<Person>() {
            @Override
            public int compare(Person o1, Person o2) {
                return o2.age - o1.age;
            }
        });
        // 方式2
        list.sort((o1,o2)->o2.age -o1.age);
        // 方式3
        Collections.sort(list,(o1,o2) -> o2.age - o1.age);

        System.out.println(list);
    }

    static class Person{
        String name;
        Integer age;

        Person(){
            System.out.println("Person 类的无参构造方法执行了");
        }
        Person(String name,Integer age){
            this.name = name;
            this.age = age;
            System.out.println("Person 类的有参构造方法执行了");
        }
        @Override
        public String toString() {
            return "Person{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    }
}
// 案例二:集合排序,TreeSet
public class Demo02 {
    public static void main(String[] args) {
        TreeSet<Person> set = new TreeSet<>();
        set.add(new Person("小红",1));

        System.out.println(set);
    }
}
这样写会报异常:
Exception in thread "main" java.lang.ClassCastException: Thread.lambda.excise.Person cannot be cast to java.lang.Comparable
改1:
public class Demo02 {
    public static void main(String[] args) {
        TreeSet<Person> set = new TreeSet<>((o1,o2) -> o2.age - o1.age);
        set.add(new Person("小红",1));
        set.add(new Person("小明",4));
        set.add(new Person("小王",3));
        set.add(new Person("小李",6));
        set.add(new Person("小张",2));
        set.add(new Person("老王",7));
        set.add(new Person("老李",4));
        set.add(new Person("老张",7));

        System.out.println(set);
    }
}
这样写,最后会把 age 重复的给去重,return 0 的去重
改2:
public class Demo02 {
    public static void main(String[] args) {
        TreeSet<Person> set = new TreeSet<>((o1,o2) -> {
            if(o2.age >= o1.age){
                return 1;
            } else {
                return -1;
            }
        });
        set.add(new Person("小红",1));
        set.add(new Person("小明",4));
        set.add(new Person("小王",3));
        set.add(new Person("小李",6));
        set.add(new Person("小张",2));
        set.add(new Person("老王",7));
        set.add(new Person("老李",4));
        set.add(new Person("老张",7));

        System.out.println(set);
    }
}
//案例三:集合遍历,ArrayList
public class Demo03 {
    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<>();
        Collections.addAll(list,5,8,7,4,9,6,1,2,0,3);
        
        list.forEach(System.out::println);

        System.out.println("==================================");
        list.forEach(ele -> {
            if(ele%2 ==0){
                System.out.println(ele);
            }
        });

        System.out.println("==================================");
        list.forEach(new Util()::accept);
    }

    static class Util implements Consumer {
        @Override
        public void accept(Object o) {
            System.out.println("XXX"+o);
        }
    }
}
/*
案例四:删除集合中的特定元素
 */
public class Demo04 {
    public static void main(String[] args) {
        ArrayList<Person> list = new ArrayList<>();

        list.add(new Person("小红",1));
        list.add(new Person("小明",4));
        list.add(new Person("小王",3));
        list.add(new Person("小李",6));
        list.add(new Person("小张",2));
        list.add(new Person("老王",7));
        list.add(new Person("老李",4));
        list.add(new Person("老张",7));

        //删除集合中 age > 5 的元素
        list.removeIf(ele -> ele.age > 5);
        
        list.forEach(System.out::println);
    }
}
/*
案例五:创建线程
 */
public class Demo05 {
    public static void main(String[] args) {
        Thread thread = new Thread(() -> {
            for (int i = 0; i < 100; i++) {
                System.out.println(i);
            }
        });
        thread.start();
    }
}

五、系统内容的函数式接口

        //Predicate<T>           : 参数T  返回值boolean
        //    IntPredicate       : int    -> boolean
        //    LongPredicate      : Long   -> boolean
        //    DoublePredicate    : Double -> boolean

        //Consumer<T>            : 参数T 返回值void
        //    IntConsumer        : int    -> void
        //    LongConsumer       : Long   -> void
        //    DoubleConsumer     : Double -> void

        //Function<T,R>              : 参数T 返回值R
        //    IntFunction<R>         : int    -> R
        //    LongFunction<R>        : Long   -> R
        //    DoubleFunction<R>      : Double -> R
        //    IntToLongFunction      : int    -> Long
        //    IntToDoubleFunction    : int    -> Double
        //    LongToIntFunction      : Long   -> int
        //    LongToDoubleFunction   : Long   -> Double
        //    DoubleToIntFunction    : Double -> int
        //    DoubleToLongFunction   : Double -> Long

        //Supplier<T>        : 参数无   返回值T
        //UnaryOperator      : 参数T    返回值T
        //BinaryOperator<T>  : 参数T,T 返回值T
        //BiFunction<T,U,R>  : 参数T,U  返回值R
        //BiPredicate<T,U>   : 参数T,U  返回值boolean
        //BiConsumer<T,U>    : 参数T,U  返回值void

        //常用的:
        //Predicate<T>    Consumer<T>    Function<T,R>   Supplier<T>
        //Predicate<T>     :  boolean test<T>  :  断言型接口
        //Consumer<T>    :  void accept<T>   :  消费型接口
        //Supplier<T>       :  void get<T>         :  供给型接口
        //Function<T,R>   :  R apply<T>          :  函数型接口

六、闭包问题

public class Demo01 {
    public static void main(String[] args) {
        int a = getNumber().get();
        System.out.println(a);

        int b = 10;// jdk1.8 后 默认是 final 类型;(在局部内部类中,引用了同级别的局部变量时,该变量默认为 final)
        Runnable r = () -> System.out.println("xxxx:"+b);
        new Thread(r).start();
    }

    public static Supplier<Integer> getNumber(){
        int num = 10;
        return () -> {
            return num;
        };
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 7月20日知识点 今天的主要内容——线程 线程线程的基本概念线程与进程的区别线程的两种创建方式(掌握)注意线程两种...
    须臾之北阅读 14,718评论 0 4
  • Java 8 lambda 表达式10个示例 Java 8 发布于4年前,日期是2014年3月18日,这次开创性的...
    认真期待阅读 5,245评论 2 6
  • 例1、用lambda表达式实现Runnable我开始使用Java 8时,首先做的就是使用lambda表达式替换匿名...
    偷懒的扫地僧阅读 1,193评论 0 0
  • 参考ImportNew - lemeilleur 翻译自javarevisited 用例1、用lambda表达式实...
    mulinsentt阅读 3,644评论 0 1
  • 行为参数化 为了应对多变的需求,难道我们就要因为客户每提出一个需求,我们就要写一个方法去实现吗? 显然这样做很冗余...
    uzip柚子皮阅读 4,344评论 0 1

友情链接更多精彩内容