Lamda表达式

Lamda表达式

基础介绍

Lamda表达式,读作λ表达式,它实质属于函数式编程的概念,要理解函数式编程的产生目的,就要先理解匿名内部类。

场景:在使用时,再实现具体的业务逻辑;

先来看看传统的匿名内部类调用方式:

interface MyInterface{

    void lMethod();
}
public class Main {

    public static void test(MyInterface myInterface){
        myInterface.lMethod();
    }

    public static void main(String[] args) {
        test(new MyInterface() {
            @Override
            public void lMethod() {
                System.out.println("Hello World!");
            }
        });
    }
}

在主类中的这么几行代码,嵌套几层就为了输出一个Hello World!是不是很麻烦?但是由于java结构的完整性,我们还不得不那么做,现在JDK1.8来了。

再来看看使用Lamda表达式改写上面的代码:

interface MyInterface{

    void lMethod();
}
public class Main {

    public static void test(MyInterface myInterface){
        myInterface.lMethod();
    }

    public static void main(String[] args) {
        test(()->System.out.println("Hello World!"));
    }
}

这就是Lamda表达式语言,为了解决匿名内部类繁杂的操作而出现。

Lamda语法有三种形式:

(参数) ->单行语句;
(参数) ->{多行语句};
(参数) ->表达式;
括号()可以大致理解为就是方法,里面是参数变量,在上面的例子中()->System.out.println(“Hello World!”) 前面的()代表void lMethod()方法,它没有入参,所以为空,->后面是一个单行语句;

如果->后面是多行语句,需要用{ }装起来,每条语句后需要有分号;

->后面也可以是一个表达式,如:a+b等。


(参数) ->单行语句:

interface MyInterface{

    void lMethod(String str);
}
public class Main {

    public static void test(MyInterface myInterface){
        myInterface.lMethod("Hello World!");//设置参数内容
    }

    public static void main(String[] args) {
        //首先在()中定义此表达式里面需要接收变量s,后面的单行语句中就可以使用该变量了
        test((s)->System.out.println(s));
    }
}

(参数) ->{多行语句}:

interface MyInterface{

    void lMethod(String str);
}
public class Main {

    public static void test(MyInterface myInterface){
        myInterface.lMethod("Hello World!");//设置参数内容
    }

    public static void main(String[] args) {
        //首先在()中定义此表达式里面需要接收变量s,后面的多行语句中就可以使用该变量了。注意:多行语句别少“;”号
        test((s)->{
            s=s+s;
            System.out.println(s);
        });
    }
}

(参数) ->表达式:

interface MyInterface{

    int lMethod(int a,int b);
}
public class Main {

    public static void test(MyInterface myInterface){
        int result=myInterface.lMethod(1,2);//设置参数内容,接收返回参数
        System.out.println(result);
    }
    public static void main(String[] args) {

        test((x,y)-> x*y );//调用方法
        //相当于
//        test((x,y)-> {return  x*y;});
    }
}

这样,Lamda表达式就看起来很简单了,有不有!

匿名内部类,我们比较常用的地方在哪儿?线程类Thread,以前我们可能这样写:

new Thread(new Runnable() {
    @Override
    public void run() {
        System.out.println("线程操作!");
    }
});

现在,使用Lamda表达式,简单写为:

new Thread(()->System.out.println("线程操作!"));

总结:利用Lamda表达式是为了避免匿名内部类定义过多无用的操作。

package com.cyou.joinactivity.cust.weekly.controller;

/**
 * @create 2020-08-21 10:47
 */
public class LamdaTest {
    public static void main(String[] args) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("内部类实现");
            }
        }).run();

        new Thread(() -> System.out.println("lamda实现")).run();
    }
}


进阶

建立简单Bean类,方面后面的测试

import java.util.ArrayList;
import java.util.List;
 
public class Human {
    private String name;
    private int age;
 
    public Human() {
    }
 
    public Human(String name, int age) {
        this.name = name;
        this.age = age;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public int getAge() {
        return age;
    }
 
    public void setAge(int age) {
        this.age = age;
    }
 
    @SuppressWarnings("serial")
    public static List<Human> getAInitHumanList() {
        return new ArrayList<Human>() {
            {
                add(new Human("guorao", 10));
                add(new Human("mako", 12));
                add(new Human("hel", 30));
                add(new Human("lin", 28));
            }
        };
    }
 
}
简单的排序方法

1、利用实现Comparator接口方式

public class HumanComparetor implements Comparator<Human> {
    @Override
    public int compare(Human h1, Human h2) {
        if (h1.getAge() > h2.getAge()) {
            return 1;
        } else if (h1.getAge() == h2.getAge()) {
            return 0;
        } else {
            return -1;
        }
    }
}
public static void main(String[] args) {
     List<Human> humans = Human.getAInitHumanList();
     Collections.sort(humans, new HumanComparetor());
     System.out.println(humans);
}

2、利用内部类

public static void main(String[] args) {
    List<Human> humans = Human.getAInitHumanList();
    //方法内-局部类
    class HumanComparetor implements Comparator<Human> {
        @Override
        public int compare(Human h1, Human h2) {
            return h1.getAge() - h2.getAge();
        }
    }
    Collections.sort(humans, new HumanComparetor());
    System.out.println(humans);
}
利用新特性

1、利用lamdba方式

    public static void main(String[] args) {
        List<Human> humans = Human.getAInitHumanList();
        //lamdba 表达式 ->
        Collections.sort(humans, (Human h1, Human h2) -> h1.getAge() - h2.getAge());
        System.out.println(humans);
    }

2、利用Comparator和lamdba表达式多条件排序

public static void main(String[] args) {
    List<Human> humans = Human.getAInitHumanList();
    lamdba 表达式 ::
    Collections.sort(humans, Comparator.comparing(Human::getAge).thenComparing(Human::getName));
    System.out.println(humans);
}

3、用Comparator接口方式多条件排序

public static void main(String[] args) {
    List<Human> humans = Human.getAInitHumanList();
    //直接用list.sort
    humans.sort(Comparator.comparing(Human::getAge).thenComparing(Human::getName));
    System.out.println(humans);
}
解释:Comparable和Comparator
  • 1、Comparable为内部比较类,是实现的对象自身与其他对象进行比较
object.compareTo(object2)
  • 2、Comparator为外部比较类,是实现某种对象之间的属性、值之间的比较方式;
    其实Comparator就是一种典型的策略模式;
ComparatorImpl comparator = new ComparatorImpl();
comparator.compare(object1, object2)

练习题

    Trader raoul = new Trader("Raoul", "Cambridge");
    Trader mario = new Trader("Mario","Milan");
    Trader alan = new Trader("Alan","Cambridge");
    Trader brian = new Trader("Brian","Cambridge");
 
    List<Transaction> transactions = Arrays.asList(
            new Transaction(brian, 2011, 300),
            new Transaction(raoul, 2012, 1000),
            new Transaction(raoul, 2011, 400),
            new Transaction(mario, 2012, 710),
            new Transaction(mario, 2012, 700),
            new Transaction(alan, 2012, 950)
    );
  1. 找出2011年发生的所有交易,并按交易额排序

  2. 交易员在哪些不同的城市工作过

  3. 查找所有来自剑桥的交易员,并按姓名排序

  4. 返回所有交易员的姓名字符串,并按字母顺序排序

  5. 有没有交易员在米兰工作的?

  6. 打印生活在剑桥的交易员的所有交易额

  7. 所有交易中,最高的交易额是多少

  8. 找到交易额最小的交易

下面是两个实体的类定义




public class Trader {


    private String name;
    private String city;

    public Trader(String n, String c) {
        this.name = n;
        this.city = c;
    }

    public String getName() {
        return this.name;
    }


    public String getCity() {
        return this.city;
    }


    public void setCity(String newCity) {
        this.city = newCity;
    }


    public String toString() {
        return "Trader:" + this.name + " in " + this.city;
    }
}




public class Transaction {

    private Trader trader;
    private int year;
    private int value;

    public Transaction(Trader trader, int year, int value) {
        this.trader = trader;
        this.year = year;
        this.value = value;
    }

    public Trader getTrader() {
        return this.trader;
    }

    public int getYear() {
        return this.year;

    }

    public int getValue() {
        return this.value;
    }

    public String toString() {
        return "{" + this.trader + ", " +

                "year: " + this.year + ", " +

                "value:" + this.value + "}";
    }

}

答案



import java.util.Arrays;
import java.util.Comparator;
import java.util.List;

/**
 * @author 孙灵通【sunlingtong@cyou-inc.com】
 * @create 2020-08-21 11:42
 */
public class LambdaTest2 {
    public static void main(String[] args) {
        Trader raoul = new Trader("Raoul", "Cambridge");
        Trader mario = new Trader("Mario","Milan");
        Trader alan = new Trader("Alan","Cambridge");
        Trader brian = new Trader("Brian","Cambridge");

        List<Transaction> transactions = Arrays.asList(
                new Transaction(brian, 2011, 300),
                new Transaction(raoul, 2012, 1000),
                new Transaction(raoul, 2011, 400),
                new Transaction(mario, 2012, 710),
                new Transaction(mario, 2012, 700),
                new Transaction(alan, 2012, 950)
        );

//        1. 找出2011年发生的所有交易,并按交易额排序
        System.out.println(" 1. 找出2011年发生的所有交易,并按交易额排序");
        transactions.stream().filter(o -> o.getYear() == 2011).sorted(Comparator.comparing(Transaction::getValue)).forEach(System.out::println);
//        2. 交易员在哪些不同的城市工作过
        System.out.println(" 2. 交易员在哪些不同的城市工作过");
        transactions.stream().map(o->o.getTrader().getCity()).distinct().forEach(System.out::println);
//        3. 查找所有来自剑桥的交易员,并按姓名排序
        System.out.println(" 3. 查找所有来自剑桥的交易员,并按姓名排序");
        transactions.stream().map(Transaction::getTrader).filter(trader->trader.getCity().equals("Cambridge")).sorted(Comparator.comparing(o->o.getName())).distinct().forEach(System.out::println);
//        4. 返回所有交易员的姓名字符串,并按字母顺序排序
        System.out.println(" 4. 返回所有交易员的姓名字符串,并按字母顺序排序");
        transactions.stream().map(Transaction::getTrader).map(Trader::getName).sorted().distinct().forEach(System.out::println);
//        5. 有没有交易员在米兰工作的?
        System.out.println(" 5. 有没有交易员在米兰工作的?");
        transactions.stream().map(Transaction->Transaction.getTrader()).filter(o->o.getCity().equals("Milan")).distinct().forEach(System.out::println);
//        6. 打印生活在剑桥的交易员的所有交易额
        System.out.println(" 6. 打印生活在剑桥的交易员的所有交易额");
        Integer cambridge = transactions.stream().filter(o -> o.getTrader().getCity().equals("Cambridge")).map(Transaction::getValue).reduce(Integer::sum).get();
        System.out.println("交易额 = " + cambridge);
//        7. 所有交易中,最高的交易额是多少
        System.out.println(" 7. 所有交易中,最高的交易额是多少" + transactions.stream().map(Transaction::getValue).max(Integer::max).get());
        System.out.println("transactions.stream().max((t1,t2)->Integer.compare(t1.getValue(),t2.getValue())).get() = " + transactions.stream().max((t1, t2) -> Integer.compare(t1.getValue(), t2.getValue())).get());
//        8. 找到交易额最小的交易
        System.out.println(" 8. 找到交易额最小的交易= " + transactions.stream().min((t1, t2) -> Integer.compare(t1.getValue(), t2.getValue())).get());

    }
}

联系题总结:

Java中的双冒号写法::

此种写法是Java8 Lambda表达式
双冒号运算就是Java中的方法引用 method references
[方法引用]的格式是 类名::方法名
举例:

1.表达式:

person -> person.getName();
可以替换成:
Person::getName

2.表达式:

() -> new HashMap<>();
可以替换成:
HashMap::new

image-20200821145815229

练习题2

 private static void lambdaTest2() {
        /**建立一个数组1, 23, 4, 4, 22, 34, 45, 11, 33
         * 使用 lambda 求出数组中的最小数将数组去重,
         * 并将去重后数组的每个元素乘以 2,再求出乘以 2 后的数组的和,
         * 比如数组1,2,3,3,去重后为1,2,3,乘以 2 后为2,4,6,最后的和为12。*/
        int[] ints = {2, 23, 4, 4, 22, 34, 45, 11, 33};
        int[] ints1 = {1,2,3,3};
        System.out.println("数组中的最小数 =" + Arrays.stream(ints).min().getAsInt());
        System.out.println("去重后数组的每个元素乘以 2,再求出乘以 2 后的数组的和 = " + Arrays.stream(ints).distinct().map(a -> a * 2).sum());
    }
 private static void lambdaTest2() {
        /**建立一个数组1, 23, 4, 4, 22, 34, 45, 11, 33
         * 使用 lambda 求出数组中的最小数将数组去重,
         * 并将去重后数组的每个元素乘以 2,再求出乘以 2 后的数组的和,
         * 比如数组1,2,3,3,去重后为1,2,3,乘以 2 后为2,4,6,最后的和为12。*/
        int[] ints = {2, 23, 4, 4, 22, 34, 45, 11, 33};
        int[] ints1 = {1,2,3,3};
        System.out.println("数组中的最小数 =" + Arrays.stream(ints).min().getAsInt());
        System.out.println("去重后数组的每个元素乘以 2,再求出乘以 2 后的数组的和 = " + Arrays.stream(ints).distinct().map(a -> a * 2).sum());
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值