lambda_lambdaquerywrapper - CSDN
lambda 订阅
希腊字母表中排序第十一位的字母,大写为Λ,英语名称为Lambda。 展开全文
希腊字母表中排序第十一位的字母,大写为Λ,英语名称为Lambda。
信息
外文名
Lambda
编程语言
编程语言 创建表达式目录树类型
游    戏
半条命科幻第一人称射击电子游戏
LaTeX表示
\lambda
半条命的进化
半条命(1998~2020)
中文名
兰木达
网络释义
IT专业英语词典-L等
流行符号
失意、无奈、孤独、低调等
希腊字母
是第十一个希腊字母
λ希腊字母
ΛLambda(大写Λ,小写λ)读音:lam (b) da(兰木达)['læmdə]是第十一个希腊字母大写Λ用于:粒子物理学上,Λ重子的符号小写λ用于:物理上的波长符号放射学的衰变常数线性代数中的特征值西里尔字母的 Л 是由 Lambda 演变而成代数中的康威常数【汽车】1.氧传感器的值0.1-0.95V⒉过量空气系数附录:希腊字母读音及科学方面应用
收起全文
精华内容
参与话题
  • lambda是Python编程语言中使用频率较高的一个关键字。那么,什么是lambda?它有哪些用法?网上的文章汗牛充栋,可是把这个讲透的文章却不多。这里,我们通过阅读各方资料,总结了关于Python中的lambda的“一个语法,...

    lambda是Python编程语言中使用频率较高的一个关键字。那么,什么是lambda?它有哪些用法?网上的文章汗牛充栋,可是把这个讲透的文章却不多。这里,我们通过阅读各方资料,总结了关于Python中的lambda的“一个语法,三个特性,四个用法,一个争论”。欢迎阅读和沟通(个人微信: slxiaozju)。

    由于文章是从我的公众号上复制过来的,因此排版不整齐,但是内容绝对充实,欢迎关注公众号[测试不将就],阅读原文

    一个语法

    在Python中,lambda的语法是唯一的。其形式如下:

     lambda argument_list: expression

    其中,lambda是Python预留的关键字,argument_list和expression由用户自定义。具体介绍如下。

    1. 这里的argument_list是参数列表,它的结构与Python中函数(function)的参数列表是一样的。具体来说,argument_list可以有非常多的形式。例如:

    • a, b
    • a=1, b=2
    •  *args
    •  **kwargs
    •  a, b=1, *args
    • ......

    2. 这里的expression是一个关于参数的表达式。表达式中出现的参数需要在argument_list中有定义,并且表达式只能是单行的。以下都是合法的表达式:

    • 1
    •  None
    • a + b
    • sum(a)
    • 1 if a >10 else 0
    •  ......

    3.  这里的lambda argument_list: expression表示的是一个函数。这个函数叫做lambda函数。

     

    三个特性

    lambda函数有如下特性:

    1. lambda函数是匿名的:所谓匿名函数,通俗地说就是没有名字的函数。lambda函数没有名字。

    2. lambda函数有输入和输出:输入是传入到参数列表argument_list的值,输出是根据表达式expression计算得到的值。

    3. lambda函数一般功能简单:单行expression决定了lambda函数不可能完成复杂的逻辑,只能完成非常简单的功能。由于其实现的功能一目了然,甚至不需要专门的名字来说明。

    下面是一些lambda函数示例:

    •       lambda x, y: x*y;函数输入是x和y,输出是它们的积x*y
    •      lambda:None;函数没有输入参数,输出是None
    •      lambda *args: sum(args); 输入是任意个数的参数,输出是它们的和(隐性要求是输入参数必须能够进行加法运算)
    •      lambda **kwargs: 1;输入是任意键值对参数,输出是1

     

    四个用法

     

    由于lambda语法是固定的,其本质上只有一种用法,那就是定义一个lambda函数。在实际中,根据这个lambda函数应用场景的不同,可以将lambda函数的用法扩展为以下几种:

    1. 将lambda函数赋值给一个变量,通过这个变量间接调用该lambda函数

      例如,执行语句add=lambda x, y: x+y,定义了加法函数lambda x, y: x+y,并将其赋值给变量add,这样变量add便成为具有加法功能的函数。例如,执行add(1,2),输出为3。

    2. 将lambda函数赋值给其他函数,从而将其他函数用该lambda函数替换

    例如,为了把标准库time中的函数sleep的功能屏蔽(Mock),我们可以在程序初始化时调用:time.sleep=lambda x:None。这样,在后续代码中调用time库的sleep函数将不会执行原有的功能。例如,执行time.sleep(3)时,程序不会休眠3秒钟,而是什么都不做。

          3. 将lambda函数作为其他函数的返回值,返回给调用者。

    函数的返回值也可以是函数。例如return lambda x, y: x+y返回一个加法函数。这时,lambda函数实际上是定义在某个函数内部的函数,称之为嵌套函数,或者内部函数。对应的,将包含嵌套函数的函数称之为外部函数。内部函数能够访问外部函数的局部变量,这个特性是闭包(Closure)编程的基础,在这里我们不展开。

          4. 将lambda函数作为参数传递给其他函数

    部分Python内置函数接收函数作为参数。典型的此类内置函数有这些。

    • filter函数。此时lambda函数用于指定过滤列表元素的条件。例如filter(lambda x: x % 3 == 0, [1, 2, 3])指定将列表[1,2,3]中能够被3整除的元素过滤出来,其结果是[3]。

    • sorted函数。此时lambda函数用于指定对列表中所有元素进行排序的准则。例如sorted([1, 2, 3, 4, 5, 6, 7, 8, 9], key=lambda x: abs(5-x))将列表[1, 2, 3, 4, 5, 6, 7, 8, 9]按照元素与5距离从小到大进行排序,其结果是[5, 4, 6, 3, 7, 2, 8, 1, 9]。

    • map函数。此时lambda函数用于指定对列表中每一个元素的共同操作。例如map(lambda x: x+1, [1, 2,3])将列表[1, 2, 3]中的元素分别加1,其结果[2, 3, 4]。

    • reduce函数。此时lambda函数用于指定列表中两两相邻元素的结合条件。例如reduce(lambda a, b: '{}, {}'.format(a, b), [1, 2, 3, 4, 5, 6, 7, 8, 9])将列表 [1, 2, 3, 4, 5, 6, 7, 8, 9]中的元素从左往右两两以逗号分隔的字符的形式依次结合起来,其结果是'1, 2, 3, 4, 5, 6, 7, 8, 9'。

    另外,部分Python库函数也接收函数作为参数,例如gevent的spawn函数。此时,lambda函数也能够作为参数传入。

     

    一个争议

    事实上,关于lambda在Python社区是存在争议的。Python程序员对于到底要不要使用lambda意见不一致。

    • 支持方认为使用lambda编写的代码更紧凑,更“pythonic”。

    • 反对方认为,lambda函数能够支持的功能十分有限,其不支持多分支程序if...elif...else...和异常处理程序try ...except...。并且,lambda函数的功能被隐藏,对于编写代码之外的人员来说,理解lambda代码需要耗费一定的理解成本。他们认为,使用for循环等来替代lambda是一种更加直白的编码风格。

    关于lambda的争执没有定论。在实际中,是否使用lambda编程取决于程序员的个人喜好。

    以上就是我们总结的关于Python中的lambda的“一个语法,三个特性,四个用法,一个争论”。如有纰漏之处,欢迎批评指正。

     

    作者:软件工程专家/全栈测试开发/技术写作者,欢迎添加作者微信(slxiaozju)交流。欢迎微信关注个人公号"测试不将就"(ID: awesometest),我们一起探讨高质量软件养成之道。

    展开全文
  • Java Lambda表达式入门

    万次阅读 多人点赞 2019-03-12 10:19:04
    原文链接:Start Using Java Lambda Expressions 下载示例程序 Examples.zip 。 原文日期: 2014年4月16日 翻译日期: 2014年4月27日 翻译人员: 铁锚 简介 (译者认为: 超过3行的逻辑就不适用Lambda表达式了。虽然看着...

    原文链接: Start Using Java Lambda Expressions

    下载示例程序 Examples.zip
    原文日期: 2014年4月16日

    翻译日期: 2014年4月27日
    翻译人员: 铁锚
    简介

    (译者认为: 超过3行的逻辑就不适用Lambda表达式了。虽然看着很先进,其实Lambda表达式的本质只是一个"语法糖",由编译器推断并帮你转换包装为常规的代码,因此你可以使用更少的代码来实现同样的功能。本人建议不要乱用,因为这就和某些很高级的黑客写的代码一样,简洁,难懂,难以调试,维护人员想骂娘.)
    Lambda表达式是Java SE 8中一个重要的新特性。lambda表达式允许你通过表达式来代替功能接口。 lambda表达式就和方法一样,它提供了一个正常的参数列表和一个使用这些参数的主体(body,可以是一个表达式或一个代码块)。
    Lambda表达式还增强了集合库。 Java SE 8添加了2个对集合数据进行批量操作的包: java.util.function 包以及 java.util.stream 包。 流(stream)就如同迭代器(iterator),但附加了许多额外的功能。 总的来说,lambda表达式和 stream 是自Java语言添加泛型(Generics)和注解(annotation)以来最大的变化。 在本文中,我们将从简单到复杂的示例中见认识lambda表达式和stream的强悍。
    环境准备
    如果还没有安装Java 8,那么你应该先安装才能使用lambda和stream(译者建议在虚拟机中安装,测试使用)。 像NetBeans 和IntelliJ IDEA 一类的工具和IDE就支持Java 8特性,包括lambda表达式,可重复的注解,紧凑的概要文件和其他特性。
    下面是Java SE 8和NetBeans IDE 8的下载链接:
    Java Platform (JDK 8): 从Oracle下载Java 8,也可以和NetBeans IDE一起下载
    NetBeans IDE 8: 从NetBeans官网下载NetBeans IDE
    Lambda表达式的语法
    基本语法:
    (parameters) -> expression

    (parameters) ->{ statements; }

    下面是Java lambda表达式的简单例子:

    // 1. 不需要参数,返回值为 5
    () -> 5
    
    // 2. 接收一个参数(数字类型),返回其2倍的值
    x -> 2 * x
    
    // 3. 接受2个参数(数字),并返回他们的差值
    (x, y) -> x – y
    
    // 4. 接收2个int型整数,返回他们的和
    (int x, int y) -> x + y
    
    // 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)
    (String s) -> System.out.print(s)

    基本的Lambda例子
    现在,我们已经知道什么是lambda表达式,让我们先从一些基本的例子开始。 在本节中,我们将看到lambda表达式如何影响我们编码的方式。 假设有一个玩家List ,程序员可以使用 for 语句 ("for 循环")来遍历,在Java SE 8中可以转换为另一种形式:

     

    String[] atp = {"Rafael Nadal", "Novak Djokovic",
           "Stanislas Wawrinka",
           "David Ferrer","Roger Federer",
           "Andy Murray","Tomas Berdych",
           "Juan Martin Del Potro"};
    List<String> players =  Arrays.asList(atp);
    
    // 以前的循环方式
    for (String player : players) {
         System.out.print(player + "; ");
    }
    
    // 使用 lambda 表达式以及函数操作(functional operation)
    players.forEach((player) -> System.out.print(player + "; "));
     
    // 在 Java 8 中使用双冒号操作符(double colon operator)
    players.forEach(System.out::println);

    正如您看到的,lambda表达式可以将我们的代码缩减到一行。 另一个例子是在图形用户界面程序中,匿名类可以使用lambda表达式来代替。 同样,在实现Runnable接口时也可以这样使用:

     

    // 使用匿名内部类
    btn.setOnAction(new EventHandler<ActionEvent>() {
              @Override
              public void handle(ActionEvent event) {
                  System.out.println("Hello World!"); 
              }
        });
     
    // 或者使用 lambda expression
    btn.setOnAction(event -> System.out.println("Hello World!"));
    

    下面是使用lambdas 来实现 Runnable接口 的示例:

     

    // 1.1使用匿名内部类
    new Thread(new Runnable() {
        @Override
        public void run() {
            System.out.println("Hello world !");
        }
    }).start();
    
    // 1.2使用 lambda expression
    new Thread(() -> System.out.println("Hello world !")).start();
    
    // 2.1使用匿名内部类
    Runnable race1 = new Runnable() {
        @Override
        public void run() {
            System.out.println("Hello world !");
        }
    };
    
    // 2.2使用 lambda expression
    Runnable race2 = () -> System.out.println("Hello world !");
     
    // 直接调用 run 方法(没开新线程哦!)
    race1.run();
    race2.run();


    Runnable 的 lambda表达式,使用块格式,将五行代码转换成单行语句。 接下来,在下一节中我们将使用lambdas对集合进行排序。
    使用Lambdas排序集合
    在Java中,Comparator 类被用来排序集合。 在下面的例子中,我们将根据球员的 name, surname, name 长度 以及最后一个字母。 和前面的示例一样,先使用匿名内部类来排序,然后再使用lambda表达式精简我们的代码。
    在第一个例子中,我们将根据name来排序list。 使用旧的方式,代码如下所示:

     

    String[] players = {"Rafael Nadal", "Novak Djokovic", 
        "Stanislas Wawrinka", "David Ferrer",
        "Roger Federer", "Andy Murray",
        "Tomas Berdych", "Juan Martin Del Potro",
        "Richard Gasquet", "John Isner"};
     
    // 1.1 使用匿名内部类根据 name 排序 players
    Arrays.sort(players, new Comparator<String>() {
        @Override
        public int compare(String s1, String s2) {
            return (s1.compareTo(s2));
        }
    });

    使用lambdas,可以通过下面的代码实现同样的功能:

     

    // 1.2 使用 lambda expression 排序 players
    Comparator<String> sortByName = (String s1, String s2) -> (s1.compareTo(s2));
    Arrays.sort(players, sortByName);
    
    // 1.3 也可以采用如下形式:
    Arrays.sort(players, (String s1, String s2) -> (s1.compareTo(s2)));


    其他的排序如下所示。 和上面的示例一样,代码分别通过匿名内部类和一些lambda表达式来实现Comparator :

     

    // 1.1 使用匿名内部类根据 surname 排序 players
    Arrays.sort(players, new Comparator<String>() {
        @Override
        public int compare(String s1, String s2) {
            return (s1.substring(s1.indexOf(" ")).compareTo(s2.substring(s2.indexOf(" "))));
        }
    });
    
    // 1.2 使用 lambda expression 排序,根据 surname
    Comparator<String> sortBySurname = (String s1, String s2) -> 
        ( s1.substring(s1.indexOf(" ")).compareTo( s2.substring(s2.indexOf(" ")) ) );
    Arrays.sort(players, sortBySurname);
    
    // 1.3 或者这样,怀疑原作者是不是想错了,括号好多...
    Arrays.sort(players, (String s1, String s2) -> 
          ( s1.substring(s1.indexOf(" ")).compareTo( s2.substring(s2.indexOf(" ")) ) ) 
        );
    
    // 2.1 使用匿名内部类根据 name lenght 排序 players
    Arrays.sort(players, new Comparator<String>() {
        @Override
        public int compare(String s1, String s2) {
            return (s1.length() - s2.length());
        }
    });
    
    // 2.2 使用 lambda expression 排序,根据 name lenght
    Comparator<String> sortByNameLenght = (String s1, String s2) -> (s1.length() - s2.length());
    Arrays.sort(players, sortByNameLenght);
    
    // 2.3 or this
    Arrays.sort(players, (String s1, String s2) -> (s1.length() - s2.length()));
    
    // 3.1 使用匿名内部类排序 players, 根据最后一个字母
    Arrays.sort(players, new Comparator<String>() {
        @Override
        public int compare(String s1, String s2) {
            return (s1.charAt(s1.length() - 1) - s2.charAt(s2.length() - 1));
        }
    });
    
    // 3.2 使用 lambda expression 排序,根据最后一个字母
    Comparator<String> sortByLastLetter = 
        (String s1, String s2) -> 
            (s1.charAt(s1.length() - 1) - s2.charAt(s2.length() - 1));
    Arrays.sort(players, sortByLastLetter);
    
    // 3.3 or this
    Arrays.sort(players, (String s1, String s2) -> (s1.charAt(s1.length() - 1) - s2.charAt(s2.length() - 1)));
    

    就是这样,简洁又直观。 在下一节中我们将探索更多lambdas的能力,并将其与 stream 结合起来使用。
    使用Lambdas和Streams
    Stream是对集合的包装,通常和lambda一起使用。 使用lambdas可以支持许多操作,如 map, filter, limit, sorted, count, min, max, sum, collect 等等。 同样,Stream使用懒运算,他们并不会真正地读取所有数据,遇到像getFirst() 这样的方法就会结束链式语法。 在接下来的例子中,我们将探索lambdas和streams 能做什么。 我们创建了一个Person类并使用这个类来添加一些数据到list中,将用于进一步流操作。 Person 只是一个简单的POJO类:

     

    public class Person {
    
    private String firstName, lastName, job, gender;
    private int salary, age;
    
    public Person(String firstName, String lastName, String job,
                    String gender, int age, int salary)       {
              this.firstName = firstName;
              this.lastName = lastName;
              this.gender = gender;
              this.age = age;
              this.job = job;
              this.salary = salary;
    }
    // Getter and Setter 
    // . . . . .
    }

    接下来,我们将创建两个list,都用来存放Person对象:

     

    List<Person> javaProgrammers = new ArrayList<Person>() {
      {
        add(new Person("Elsdon", "Jaycob", "Java programmer", "male", 43, 2000));
        add(new Person("Tamsen", "Brittany", "Java programmer", "female", 23, 1500));
        add(new Person("Floyd", "Donny", "Java programmer", "male", 33, 1800));
        add(new Person("Sindy", "Jonie", "Java programmer", "female", 32, 1600));
        add(new Person("Vere", "Hervey", "Java programmer", "male", 22, 1200));
        add(new Person("Maude", "Jaimie", "Java programmer", "female", 27, 1900));
        add(new Person("Shawn", "Randall", "Java programmer", "male", 30, 2300));
        add(new Person("Jayden", "Corrina", "Java programmer", "female", 35, 1700));
        add(new Person("Palmer", "Dene", "Java programmer", "male", 33, 2000));
        add(new Person("Addison", "Pam", "Java programmer", "female", 34, 1300));
      }
    };
    
    List<Person> phpProgrammers = new ArrayList<Person>() {
      {
        add(new Person("Jarrod", "Pace", "PHP programmer", "male", 34, 1550));
        add(new Person("Clarette", "Cicely", "PHP programmer", "female", 23, 1200));
        add(new Person("Victor", "Channing", "PHP programmer", "male", 32, 1600));
        add(new Person("Tori", "Sheryl", "PHP programmer", "female", 21, 1000));
        add(new Person("Osborne", "Shad", "PHP programmer", "male", 32, 1100));
        add(new Person("Rosalind", "Layla", "PHP programmer", "female", 25, 1300));
        add(new Person("Fraser", "Hewie", "PHP programmer", "male", 36, 1100));
        add(new Person("Quinn", "Tamara", "PHP programmer", "female", 21, 1000));
        add(new Person("Alvin", "Lance", "PHP programmer", "male", 38, 1600));
        add(new Person("Evonne", "Shari", "PHP programmer", "female", 40, 1800));
      }
    };

    现在我们使用forEach方法来迭代输出上述列表:

     

    System.out.println("所有程序员的姓名:");
    javaProgrammers.forEach((p) -> System.out.printf("%s %s; ", p.getFirstName(), p.getLastName()));
    phpProgrammers.forEach((p) -> System.out.printf("%s %s; ", p.getFirstName(), p.getLastName()));

    我们同样使用forEach方法,增加程序员的工资5%:

     

    System.out.println("给程序员加薪 5% :");
    Consumer<Person> giveRaise = e -> e.setSalary(e.getSalary() / 100 * 5 + e.getSalary());
    
    javaProgrammers.forEach(giveRaise);
    phpProgrammers.forEach(giveRaise);

    另一个有用的方法是过滤器filter() ,让我们显示月薪超过1400美元的PHP程序员:

     

    System.out.println("下面是月薪超过 $1,400 的PHP程序员:")
    phpProgrammers.stream()
              .filter((p) -> (p.getSalary() > 1400))
              .forEach((p) -> System.out.printf("%s %s; ", p.getFirstName(), p.getLastName()));

    我们也可以定义过滤器,然后重用它们来执行其他操作:

     

    // 定义 filters
    Predicate<Person> ageFilter = (p) -> (p.getAge() > 25);
    Predicate<Person> salaryFilter = (p) -> (p.getSalary() > 1400);
    Predicate<Person> genderFilter = (p) -> ("female".equals(p.getGender()));
    
    System.out.println("下面是年龄大于 24岁且月薪在$1,400以上的女PHP程序员:");
    phpProgrammers.stream()
              .filter(ageFilter)
              .filter(salaryFilter)
              .filter(genderFilter)
              .forEach((p) -> System.out.printf("%s %s; ", p.getFirstName(), p.getLastName()));
    
    // 重用filters
    System.out.println("年龄大于 24岁的女性 Java programmers:");
    javaProgrammers.stream()
              .filter(ageFilter)
              .filter(genderFilter)
              .forEach((p) -> System.out.printf("%s %s; ", p.getFirstName(), p.getLastName()));
    

    使用limit方法,可以限制结果集的个数:

     

    System.out.println("最前面的3个 Java programmers:");
    javaProgrammers.stream()
              .limit(3)
              .forEach((p) -> System.out.printf("%s %s; ", p.getFirstName(), p.getLastName()));
    
    
    System.out.println("最前面的3个女性 Java programmers:");
    javaProgrammers.stream()
              .filter(genderFilter)
              .limit(3)
              .forEach((p) -> System.out.printf("%s %s; ", p.getFirstName(), p.getLastName()));

    排序呢? 我们在stream中能处理吗? 答案是肯定的。 在下面的例子中,我们将根据名字和薪水排序Java程序员,放到一个list中,然后显示列表:

    // 静态引入

    import static java.util.stream.Collectors.toList;

     

    System.out.println("根据 name 排序,并显示前5个 Java programmers:");
    List<Person> sortedJavaProgrammers = javaProgrammers
              .stream()
              .sorted((p, p2) -> (p.getFirstName().compareTo(p2.getFirstName())))
              .limit(5)
              .collect(toList());
    
    sortedJavaProgrammers.forEach((p) -> System.out.printf("%s %s; %n", p.getFirstName(), p.getLastName()));
     
    System.out.println("根据 salary 排序 Java programmers:");
    sortedJavaProgrammers = javaProgrammers
              .stream()
              .sorted( (p, p2) -> (p.getSalary() - p2.getSalary()) )
              .collect( toList() );
    
    sortedJavaProgrammers.forEach((p) -> System.out.printf("%s %s; %n", p.getFirstName(), p.getLastName()));

    如果我们只对最低和最高的薪水感兴趣,比排序后选择第一个/最后一个 更快的是min和max方法:

     

    System.out.println("工资最低的 Java programmer:");
    Person pers = javaProgrammers
              .stream()
              .min((p1, p2) -> (p1.getSalary() - p2.getSalary()))
              .get()
    
    System.out.printf("Name: %s %s; Salary: $%,d.", pers.getFirstName(), pers.getLastName(), pers.getSalary())
    
    System.out.println("工资最高的 Java programmer:");
    Person person = javaProgrammers
              .stream()
              .max((p, p2) -> (p.getSalary() - p2.getSalary()))
              .get()
    
    System.out.printf("Name: %s %s; Salary: $%,d.", person.getFirstName(), person.getLastName(), person.getSalary())

    上面的例子中我们已经看到 collect 方法是如何工作的。 结合 map 方法,我们可以使用 collect 方法来将我们的结果集放到一个字符串,一个 Set 或一个TreeSet中:

     

    System.out.println("将 PHP programmers 的 first name 拼接成字符串:");
    String phpDevelopers = phpProgrammers
              .stream()
              .map(Person::getFirstName)
              .collect(joining(" ; ")); // 在进一步的操作中可以作为标记(token)   
    
    System.out.println("将 Java programmers 的 first name 存放到 Set:");
    Set<String> javaDevFirstName = javaProgrammers
              .stream()
              .map(Person::getFirstName)
              .collect(toSet());
    
    System.out.println("将 Java programmers 的 first name 存放到 TreeSet:");
    TreeSet<String> javaDevLastName = javaProgrammers
              .stream()
              .map(Person::getLastName)
              .collect(toCollection(TreeSet::new));
    

    Streams 还可以是并行的(parallel)。 示例如下:

     

    System.out.println("计算付给 Java programmers 的所有money:");
    int totalSalary = javaProgrammers
              .parallelStream()
              .mapToInt(p -> p.getSalary())
              .sum();

    我们可以使用summaryStatistics方法获得stream 中元素的各种汇总数据。 接下来,我们可以访问这些方法,比如getMax, getMin, getSum或getAverage:

     

    //计算 count, min, max, sum, and average for numbers
    List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
    IntSummaryStatistics stats = numbers
              .stream()
              .mapToInt((x) -> x)
              .summaryStatistics();
    
    System.out.println("List中最大的数字 : " + stats.getMax());
    System.out.println("List中最小的数字 : " + stats.getMin());
    System.out.println("所有数字的总和   : " + stats.getSum());
    System.out.println("所有数字的平均值 : " + stats.getAverage()); 

    OK,就这样,希望你喜欢它!
    总结
    在本文中,我们学会了使用lambda表达式的不同方式,从基本的示例,到使用lambdas和streams的复杂示例。 此外,我们还学习了如何使用lambda表达式与Comparator 类来对Java集合进行排序。

    展开全文
  • lambda

    千次阅读 2018-12-15 20:01:43
    一个用来构造函数的工具 基本上,Python的lambda是用于构造函数(或更精确地说,函数对象)的工具。这意味着,Python有两个构造函数的工具:def和lambda。 下面是一个例子。您可以以正常的方式用def构造一个函数,...

    一个用来构造函数的工具 基本上,Python的lambda是用于构造函数(或更精确地说,函数对象)的工具。这意味着,Python有两个构造函数的工具:def和lambda。

    下面是一个例子。您可以以正常的方式用def构造一个函数,就像

    def square_root(x):

           return math.sqrt(x)

    或者你可以用lambda

    square_root = lambda x: math.sqrt(x)

     

    参考原文:http://python.jobbole.com/80954/

    展开全文
  • Lambda表达式总结

    万次阅读 多人点赞 2019-02-05 16:05:59
    Lambda表达式总结 使用范例 使用范例 使用匿名内部类: Comparator&amp;amp;amp;amp;amp;amp;amp;amp;amp;lt;Integer&amp;amp;amp;amp;amp;amp;amp;amp;amp;gt;...

    Lambda表达式总结

    • 使用范例以及例子
    • Lambda表达式基础语法
    • 函数式接口
    • Lambda练习
    • Java8四大内置函数式接口
    • 方法引用和构造器引用

    使用范例以及例子

    使用匿名内部类:

    Comparator<Integer>com = new Comparator<Integer>() {
        @Override
        public int compare(Integer o1, Integer o2) {  //降序排列
            return Integer.compare(o2,o1);
        }
    };
    

    使用Lambda表达式:

     Comparator<Integer> com = (x, y) -> Integer.compare(y, x);
    

    下面给出一个例子来引入Lambda表达式。

    给出一个Employee类,有name、age、salary三个属性:

    public class Employee {
        private String name;
        private int age;
        private double salary;
    
        public Employee() {
        }
        public Employee(String name, int age, double salary) {
            this.name = name;
            this.age = age;
            this.salary = salary;
        }
        public String getName() {
            return name;
        }
        public int getAge() {
            return age;
        }
        public double getSalary() {
            return salary;
        }
    
        @Override
        public String toString() {
            return "name='" + name + '\'' +
                    ", age=" + age +
                    ", salary=" + salary;
        }
    }
    
    

    然后我们需要通过限制查询数据:

    • 比如查询年龄>25岁的所有员工的信息;
    • 再如查询工资>4000的员工信息;

    首先给出一个List集合类模拟数据库表:

    //将数组转换成集合的
    List<Employee> employees = Arrays.asList(
        new Employee("张三",23,3333.33),
        new Employee("李四",24,4444.44),
        new Employee("王五",25,5555.55),
        new Employee("赵六",26,6666.66),
        new Employee("田七",27,7777.77)
    );
    

    原始方法

    然后我们写分别查询出年龄大于25岁的员工信息和工资大于4000的员工信息,发现findEmployeesByAgefindEmployeesBySalary两个方法代码非常的相似,只有查询条件不同,所以这个方法是不太可取的。

    public void test3(){
        //年龄
        List<Employee> list = findEmployeesByAge(employees);
        for(Employee emp : list){
            System.out.println(emp);
        }
        //工资
        System.out.println("---------------------");
        List<Employee> list2 = findEmployeesBySalary(employees);
        for(Employee emp : list2){
            System.out.println(emp);
        }
    }
    
    //原始方法 : 查询出年龄大于25岁的(这个是最原始的方法)
    public List<Employee> findEmployeesByAge(List<Employee>list){
        List<Employee>emps = new ArrayList<>();
        for(Employee emp : list){
            if(emp.getAge() > 25){
                emps.add(emp);
            }
        }
        return emps;
    }
    
    //原始方法 : 查询出工资大于4000的(这个是最原始的方法)
    //和上面的方法唯一的差别只有年龄和工资的改动,代码冗余
    public List<Employee> findEmployeesBySalary(List<Employee>list){
        List<Employee>emps = new ArrayList<>();
        for(Employee emp : list){
            if(emp.getSalary() > 4000){
                emps.add(emp);
            }
        }
        return emps;
    }
    
    

    优化方式一-使用策略模式来优化

    策略模式需要行为算法族,于是我们创建查询行为的接口MyPredicate<T>:

    public interface MyPredicate <T>{
        public boolean test(T t);
    }
    

    并创建相关的实现类代表不同的算法行为: (分别是年龄> 25和工资> 4000的 ):

    public class FilterEmployeeByAge implements MyPredicate<Employee> {
        @Override
        public boolean test(Employee employee) {
            return  employee.getAge() > 25;
        }
    }
    
    public class FilterEmployeeBySalary implements MyPredicate<Employee>{
        @Override
        public boolean test(Employee employee) {
            return employee.getSalary()  >= 4000;
        }
    }
    

    这时我们可以只需要创建通用的方法: 具体的调用只需要传入具体的实现类(接口作为参数)

    public List<Employee> filterEmployees(List<Employee>list,MyPredicate<Employee>mp){
        List<Employee>emps = new ArrayList<>();
        for(Employee emp : list){
            if(mp.test(emp)){  //调用相应的过滤器
                emps.add(emp);
            }
        }
        return emps;
    }
    

    测试的时候就传入两个不同的类,来指定查询的行为

    //优化方式一 :  使用策略设计模式进行优化  下面的方法只要写一个
    public void test4(){
        List<Employee> list = filterEmployees(this.employees, new FilterEmployeeByAge());
        for(Employee emp : list){
            System.out.println(emp);
        }
        System.out.println("------------------------");
        List<Employee> list2 = filterEmployees(this.employees, new FilterEmployeeBySalary());
        for(Employee emp : list2){
            System.out.println(emp);
        }
    }
    

    优化方式二-使用匿名内部类优化

    这样的好处在于不需要创建接口的具体的实现类,(但是还是需要MyPredicate接口和filterEmployees()方法):

    //优化方式二 : 使用匿名内部类  这样的好处是不要创建一个额外的 策略类
    public void test5(){
        List<Employee> list = filterEmployees(this.employees, new MyPredicate<Employee>() {
            @Override
            public boolean test(Employee employee) {
                return employee.getSalary() > 4000;
            }
        });
        for (Employee emp:list) {
            System.out.println(emp);
        }
    }
    

    优化方式三-使用Lambda表达式

    省去匿名内部类的没用的代码,增强可读性:(注意还是需要那个filterEmployees方法)

    public void test6(){
        List<Employee> list = filterEmployees(this.employees, (e) -> e.getSalary() > 4000);
        list.forEach(System.out::println);
    }
    

    优化方式四-使用Stream-API

    使用StreamAPI完全不需要其他的代码,包括不需要filterEmployees()方法,代码很简洁:

    public void test7(){
        employees.stream().filter( (e) -> e.getSalary() < 4000 ).limit(2).forEach(System.out::println);
        System.out.println("------------------");
        employees.stream().map(Employee::getName).forEach(System.out::println); //打印所有的名字
    }
    

    Lambda表达式基础语法

    关于箭头操作符:

    • Java8中引入了一个新的操作符,"->",该操作符称为箭头操作符或者Lambda操作符,箭头操作符将Lambda表达式拆分成两部分;
    • 左侧: Lambda表达式的参数列表,对应的是接口中抽象方法的参数列表
    • 右侧: Lambda表达式中所需要执行的功能(Lambda),对应的是对抽象方法的实现;(函数式接口(只能有一个抽象方法))
    • Lambda表达式的实质是 对接口的实现

    语法格式:

    • (一) 接口中的抽象方法 : 无参数,无返回值;

    例如: Runnable接口中的run方法:

       public void test1(){
            /*final */int num = 2; //jdk1.7之前必须定义为final的下面的匿名内部类中才能访问
    
            Runnable r = new Runnable() {
                @Override
                public void run() {
                    System.out.println("Hello world!" + num); //本质还是不能对num操作(只是jdk自己为我们设置成了final的)
                }
            };
            r.run();
    
            System.out.println("----------使用Lambda输出-----------");
    
            Runnable r1 = () -> System.out.println("Hello world!" + num);
            r1.run();
        }
    
    • (二) 接口中的抽象方法 : 一个参数且无返回值; (若只有一个参数,那么小括号可以省略不写)
    public void test2(){
    //  Consumer<String>con = (x) -> System.out.println(x);
        Consumer<String>con = x -> System.out.println(x);
        con.accept("Lambda牛逼!");
    }
    
    • (三) 两个参数,有返回值,并且有多条语句 : 要用大括号括起来,而且要写上return
    public void test3(){
         Comparator<Integer>com = (x,y) -> {
             System.out.println("函数式接口");
             return Integer.compare(y,x); //降序
         };
         
         Integer[] nums = {4,2,8,1,5};
         Arrays.sort(nums,com);
         System.out.println(Arrays.toString(nums));
    }
    

    输出:

    函数式接口
    函数式接口
    函数式接口
    函数式接口
    函数式接口
    函数式接口
    函数式接口
    函数式接口
    函数式接口
    [8, 5, 4, 2, 1]
    
    • (四) 两个参数,有返回值,但是只有一条语句: 大括号省略,return省略
    public void test4(){
         Comparator<Integer>com = (x,y) -> Integer.compare(x,y);//升序
         Integer[] nums = {4,2,8,1,5};
         Arrays.sort(nums,com);
         System.out.println(Arrays.toString(nums));
     }
    

    输出:

    [1, 2, 4, 5, 8]
    
    • (五) Lambda表达式的参数列表的数据类型 可以省略不写,因为JVM编译器通过上下文推断出数据类型,即"类型推断", (Integer x,Integer y ) -> Integer.compare(x,y)可以简写成(x,y) -> Integer.compare(x,y)
    上联: 左右遇一括号省
    下联: 左侧推断类型省
    横批: 能省则省
    

    函数式接口

    • 若接口中只有一个抽象方法的接口称为函数式接口;
    • 可以使用注解@FunctionlInterface来标识,可以检查是否是函数式接口;

    例子: 对一个进行+-*/的运算:

    函数式接口:

    @FunctionalInterface //函数式接口
    public interface MyFunction {
        public Integer getValue(Integer num);
    }
    

    通用函数:

    public Integer operation(Integer num,MyFunction mf){
        return mf.getValue(num);
    }
    

    测试:

    public void test5(){
         Integer res = operation(200, (x) -> x * x);
         System.out.println(res);
     }
    

    Lambda练习

    练习一-Employee类中先按年龄比,年龄相同按照姓名比-都是升序

    先给出集合,模拟数据库表:

    List<Employee> employees = Arrays.asList(
            new Employee("田七",27,7777.77),
            new Employee("王五",24,5555.55),
            new Employee("张三",23,3333.33),
            new Employee("李四",24,4444.44),
            new Employee("赵六",26,6666.66)
    );
    
    public void test1(){
       Collections.sort(employees,(x,y) ->{
           if(x.getAge() == y.getAge()){
               return x.getName().compareTo(y.getName());
           }else{
               return Integer.compare(x.getAge(),y.getAge());
           }
       });
    
       for (Employee emp: employees) {
           System.out.println(emp);
       }
    }
    

    输出:

    name='张三', age=23, salary=3333.33
    name='李四', age=24, salary=4444.44
    name='王五', age=24, salary=5555.55
    name='赵六', age=26, salary=6666.66
    name='田七', age=27, salary=7777.77
    
    练习二-声明一个带两个泛型的接口,并且对两个Long型数值计算
    @FunctionalInterface
    public interface MyCalFunction<T,R> {
        public R getValue(T t1,T t2); 
    }
    

    对应函数和测试:

     public void test3(){
         op(200L,200L,(x,y) -> x + y);
         op(200L,200L,(x,y) -> x * y);
     }
     public void op(Long l1,Long l2,MyCalFunction<Long,Long>mc){//需求: 对于两个long型运算进行处理
         System.out.println(mc.getValue(l1, l2));
     }
    

    更多的例子: (取自<<Java8实战>>)
    在这里插入图片描述
    在这里插入图片描述
    (注意类型可以省略(类型推导))。
    在这里插入图片描述
    上图的Apple类:

    public class Apple {
        public String color;
        public int weight;
    
        public Apple() {
        }
        public Apple(String color, int weight) {
            this.color = color;
            this.weight = weight;
        }
    
        public String getColor() {
            return color;
        }
    
        public void setColor(String color) {
            this.color = color;
        }
    
        public int getWeight() {
            return weight;
        }
    
        public void setWeight(int weight) {
            this.weight = weight;
        }
    }
    

    Java8四大内置函数式接口

    我们发现,如果使用Lambda还要自己写一个接口的话太麻烦,所以Java自己提供了一些接口:

    • Consumer< T >con 消费性 接口: void accept(T t)
    • Supplier< T >sup供给型接口 : T get()
    • Function< T , R >fun 函数式接口 : R apply (T t)
    • Predicate< T >: 断言形接口 : boolean test(T t)

    Consumer< T >con消费性接口-void accept(T t)

    @Test
    public void test1(){
        apply(1000,(num) -> System.out.println("消费了" + num + "元!"));
    }
    public void apply(double num,Consumer<Double>con){
        con.accept(num);
    }
    

    Supplier< T >sup供给型接口-T get()

    例子: 产生指定个数的整数,并放入集合中;

    public void test2(){
        ArrayList<Integer> res = getNumList(10, () -> (int) (Math.random() * 100));
        System.out.println(res);
    }
    //需求,产生指定个数的整数,并放入集合中
    public ArrayList<Integer> getNumList(int num, Supplier<Integer>sup){
        ArrayList<Integer>list = new ArrayList<>();
        for(int i = 0; i < num; i++){
            Integer e = sup.get();
            list.add(e);
        }
        return list;
    }
    

    Function< T, R >fun函数式接口-R apply (T t)

    public void test3(){
        String newStr = strHandler("abc", (str) -> str.toUpperCase());
        System.out.println(newStr);
        newStr = strHandler("   abc  ", (str) -> str.trim());
        System.out.println(newStr);
    }
    public String strHandler(String str, Function<String,String>fun){
        return fun.apply(str);
    }
    

    Predicate< T >断言形接口-boolean test(T t)

    判断一些字符串数组判断长度>2的字符串:

    public void test4(){
        List<String> list = Arrays.asList("Hello", "atguiu", "lambda", "ok", "www", "z");
        List<String> res = filterStr(list, (str) -> str.length() > 2);
        System.out.println(res);
    }
    //需求
    public List<String> filterStr(List<String>list, Predicate<String>pre){
        ArrayList<String>res = new ArrayList<>();
        for(String str : list){
            if(pre.test(str)){
                res.add(str);
            }
        }
        return res;
    }
    

    方法引用和构造器引用

    方法引用

    使用前提: Lambda体中调用方法的参数列表和返回值类型,要和函数式接口中抽象方法的参数列表和返回值类型保持一致;

    • 语法格式(一) 对象::实例方法名
    public void test1(){
    	//普通写法
         PrintStream ps = System.out;
         Consumer<String>con = (x) -> ps.println(x);
         con.accept("hello !");
    
         System.out.println("----------------------");
    	//简写
         Consumer<String>con1 = ps::println;
         con1.accept("hello ! ");
    
         System.out.println("----------------------");
    	//更简单的写法
         Consumer<String>con2 = System.out::println;
         con2.accept("hello ! ");
    }
    

    注意,这样写的前提: Consumer中的accept()方法和println()方法的参数列表和返回类型要完全一致:
    这里写图片描述
    这里写图片描述
    再看一个例子:
    三种写法的效果是一样的:

    public class TestLambda {
    
        public static void main(String[] args) {
    
            // method 1
            Consumer<String> consumer = s -> System.out.println(s);
            useConsumer(consumer,"123");
    
            //method 2
            useConsumer(s -> System.out.println(s),"123");
    
            //method3   method reference (方法引用)
            useConsumer(System.out::println,"123"); //因为println和 accept 是同样的只有一个入参,没有返回值
        }
    
        public static <T> void useConsumer(Consumer<T> consumer,T t){
            consumer.accept(t);
        }
    }
    

    再看一个例子:

    public static void main(String[] args) {
        //都是输出 字符 'l'
        BiFunction<String,Integer,Character> bf = String::charAt; //这里第一个必须传入 String
        Character c = bf.apply("hello,", 2);
        System.out.println(c);
    
        //注意这里使用的是Function 接口
        String str = new String("hello");
        Function<Integer,Character> f = str::charAt; //这里不需要String
        Character c2 = f.apply(2);
        System.out.println(c2);
    }
    
    

    再看一个例子:

    public void test2(){
        Employee emp = new Employee("zx",23,5555);
    
        Supplier<String>sup = () -> emp.getName();
        System.out.println(sup.get());
    
        //简写
        Supplier<String>sup2 = emp::getName;
        System.out.println(sup2.get());
    }
    

    这里写图片描述这里写图片描述

    • 语法格式(二) 类名::静态方法
    public void test3(){
         Comparator<Integer>com = (x,y) -> Integer.compare(x,y);
    
         Comparator<Integer>com2 = Integer::compare;
    }
    

    Integer类中的
    这里写图片描述
    Comparator接口中的方法:
    这里写图片描述

    • 语法格式(三) 类::实例方法名

    使用注意: 若Lambda参数列表中的第一个参数是实例方法的第一个调用者,而第二个参数是实例方法的参数时,可以使用ClassName :: method

    public void test4(){
        BiPredicate<String,String>bp = (x,y) -> x.equals(y);
    
        BiPredicate<String,String>bp2 = String::equals;
    }
    

    这里写图片描述
    这里写图片描述

    构造器引用

    需要调用构造器的参数列表,要与函数式接口中的抽象方法的参数列表保持一致;

    public void test5(){
        Supplier<Employee>sup = () -> new Employee();
    
        Supplier<Employee>sup2 = Employee::new; //调用的是默认的
        System.out.println(sup2.get());
    }
    

    输出:

    name='null', age=0, salary=0.0
    

    这里写图片描述
    这里写图片描述
    再看构造器一个参数的:

    public void test6(){
        Function<String,Employee>fun = Employee::new;
        System.out.println(fun.apply("zx"));
    }
    

    输出:

    name='zx', age=0, salary=0.0
    

    这里写图片描述
    这里写图片描述
    如果想要匹配多个的,(两个的可以使用BiFunction),下面看一个三个的:
    例如想匹配这个:

    public class ComplexApple {
    
        private String name;
        private int weight;
        private String color;
    
        public ComplexApple() {
        }
    
        //匹配这个构造方法
        public ComplexApple(String name, int weight, String color) {
            this.name = name;
            this.weight = weight;
            this.color = color;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getWeight() {
            return weight;
        }
    
        public void setWeight(int weight) {
            this.weight = weight;
        }
    
        public String getColor() {
            return color;
        }
    
        public void setColor(String color) {
            this.color = color;
        }
    }
    
    

    自己建一个接口:

    @FunctionalInterface
    public interface ThreeFunction<A,B,C,R> {
        R apply(A a,B b,C c);
    }
    
    

    测试:

    
    public class Test {
    
        public static void main(String[] args) {
    
            ThreeFunction<String,Integer,String,ComplexApple> tf = ComplexApple::new;
    
            ComplexApple apple = tf.apply("蓝色", 12, "好苹果");
            
        }
    }
    
    
    展开全文
  • Lambda

    2020-09-11 14:25:55
    Lambda表达式 Lambda是一个匿名函数,我们可以把Lambda表达式理解为是一段可以传递的代码(将代码向数据一样进行传递),可以写出更简洁,更灵活的代码,作为一种更紧凑的代码风格,使Java的语言表达能力得到了提升...
  • '''Created on 2019-03-14Author:BinzhouProject:python中lambda filter map reduce函数使用总结'''#lambda匿名函数,格式lambda x,y:x+y 表示一个函数的参数是x,y,函数实现功能是x+y#filter[function,sequence]...
  • 1. lambda() lambda()的主体是一个表达式,起到一个函数速写的作用。 语法:lambda [arg1[, arg2, ... argN]]: expression 例如:实现1+2 &gt;&gt;&gt; fun = lambda x,y:x+y &gt;&gt;&...
  • lambda x,y:x+y #定义 #调用 f = lambda x,y:x+y print(f(1,2)) map 创建一个列表,其中包含对指定列包含的项执行制定函数返回的值 自己实现的map() list1 = [1,2,3,5,6] def list_h(a): ...
  • lambda在Python中相当于一个匿名函数,只能写一行,对于一些代码量极其简短的函数,lambda可以起到速写的作用。 代码如下: def sum(a, b): return a + b sum(1, 2) # 使用lambda函数 sum = lambda a, b: a ...
  • lambda创建匿名函数 在理解匿名函数之前,我们先来回顾下我们之前创建函数是怎么创建的: def 函数名(参数1,参数2[,……]): 函数主体 return 返回值 标标准准的函数构建方法,但是有...
  • Lambda架构

    万次阅读 多人点赞 2018-07-11 21:15:04
    转载:...Marz在Twitter工作期间开发了著名的实时大数据处理框架Storm,Lambda架构是其根据多年进行分布式大数据系统的经验总结提炼而成。Lambda架构的目标是设...
  • 深入理解Lambda

    万次阅读 多人点赞 2019-11-07 12:29:14
     Lambda是一个表达式,也可以说它是一个匿名函数。然而在使用它或是阅读Lambda代码的时候,却显得并不那么容易。因为它匿名,因为它删减了一些必要的说明信息(比如方法名)。下面就来说说Lambda是如何进行转换和...
  • Statement lambda can be replaced with expression lambda 的Warningwarning的全文如下 Statement lambda can be replaced with expression lambda less… (Ctrl+F1) This inspection reports lambda ...
  • Python中lambda表达式学习

    万次阅读 多人点赞 2013-04-07 16:41:19
    lambda只是一个表达式,函数体比def简单很多。 lambda的主体是一个表达式,而不是一个代码块。仅仅能在lambda表达式中封装有限的逻辑进去。 lambda表达式是起到一个函数速写的作用。允许在代码内嵌入一个函数的...
  • Python之lambda匿名函数使用if条件语句 1 C0LOR1 = "PapayaWhip" 2 COLOR2 = "Tan" 3 4 selectColor = lambda num: C0LOR1 if num % 2 == 0 else COLOR2 解析:当num的值是偶数时显示COLOR1,否则显示COLOR2 ...
  • Python之Lambda表达式和if not...else用法

    万次阅读 2019-11-04 15:45:47
    # -*- coding: utf-8 -*-print("*******if...else语句*********") #if 条件为真的时候返回if...exp1= lambda x:x+1 if 2==1 else 0 print(exp1(2))exp2 = lambda x:x+1 if 1==1 else 0 print(exp2(2))print("*******if
  • Lambda 表达式有何用处?如何使用? 从知乎上获取的一篇文章值得一看 https://www.zhihu.com/question/20125256/answer/324121308
  • Python lambda函数的用法

    万次阅读 多人点赞 2015-08-29 15:54:13
    匿名函数lambda的用法Python中,lambda函数也叫匿名函数,及即没有具体名称的函数,它允许快速定义单行函数,类似于C语言的宏,可以用在任何需要函数的地方。这区别于def定义的函数。 lambda与def的区别: 1)def...
  • python中lambda()的用法

    万次阅读 2016-11-09 14:04:09
    在python中有一个匿名函数lambda,匿名函数顾名思义就是指:是指一类无需定义标识符(函数名)的函数或子程序。在C++11和C#中都有匿名函数的存在。下面看看在python中匿名函数的使用。1.lambda只是一个表达式,函数...
  • python中lambda的用法

    万次阅读 多人点赞 2016-03-25 11:25:18
    一、lambda函数也叫匿名函数,即,函数没有具体的名称。先来看一个最简单例子: def f(x): return x**2 print f(4) Python中使用lambda的话,写成这样 g = lambda x : x**2 print g(4) 二、lambda和...
1 2 3 4 5 ... 20
收藏数 289,361
精华内容 115,744
关键字:

lambda