精华内容
下载资源
问答
  • 本文将引导你完成一系列从传统的命令式代码重构到Java 8函数代码,要从本文中获得最大收益,你应该具备Java 8函数的一些实践经验。1)优先于匿名Lambda的命名函数为了热身,让我们从简单的任务开始,将一些用户的详细...

    本文将引导你完成一系列从传统的命令式代码重构到Java 8函数代码,要从本文中获得最大收益,你应该具备Java 8函数的一些实践经验。

    1)优先于匿名Lambda的命名函数

    为了热身,让我们从简单的任务开始,将一些用户的详细信息带到UI。我们将从实体列表的开始,将User 转换到 UserDto:

    public List getAllUsers() {

    List users = userRepo.findAll();

    List dtos = new ArrayList<>();

    for (User user : users) {

    UserDto dto = new UserDto();

    dto.setUsername(user.getUsername());

    dto.setFullName(user.getFirstName() + " "+ user.getLastName().toUpperCase());

    dto.setActive(user.getDeactivationDate() == null);

    dtos.add(dto);

    }

    return dtos;

    }

    但是,我对这段代码并不感到自豪,因为我很可能会为许多用例重复编写类似的代码。那么,让我们使用Java 8:

    public List getAllUsers() {

    return userRepo.findAll().stream()

    .map(user -> {

    UserDto dto = new UserDto();

    dto.setUsername(user.getUsername());

    dto.setFullName(user.getFirstName() + " "+ user.getLastName().toUpperCase());

    dto.setActive(user.getDeactivationDate() == null);

    return dto;

    })

    .collect(toList());

    虽然不错,但是,我仍然不满意。我写的这个lambda演示了一个“匿名函数”。作为一个干净的代码疯子,我有一个问题 - 我想要富有表现力的名字。所以,我很快将lambda内容提取到一个单独的方法中:

    public List getAllUsers() {

    return userRepo.findAll().stream().map(this::toDto).collect(toList());

    }

    private UserDto toDto(User user) {

    UserDto dto = new UserDto();

    dto.setUsername(user.getUsername());

    dto.setFullName(user.getFirstName() + " "+ user.getLastName().toUpperCase());

    dto.setActive(user.getDeactivationDate() == null);

    return dto;

    }

    代码比在之前的版本中更简单,但现在它稍微好一些。

    这种User到DTO的逻辑转换可以直接放在DTO构造函数中:

    public class UserFacade {

    private UserRepo userRepo;

    public List getAllUsers() {

    return userRepo.findAll().stream().map(UserDto::new).collect(toList());

    }

    }

    public class UserDto {

    private String username;

    private String fullName;

    private boolean active;

    public UserDto(User user) {

    username = user.getUsername();

    fullName = user.getFirstName() + " "+ user.getLastName().toUpperCase();

    active = user.getDeactivationDate() == null;

    }

    ...

    }

    现在,让我们假设这个转换需要一些其他组件的帮助,我们希望使用Spring,Guice,CDI等注入。但是,在我们实例化的类中注入依赖项需要非常复杂的代码。如果这个转换过于复杂,我们应该将它移到一个单独的UserMapper类并从那里引用它:

    @Service

    public class UserFacade {

    @Autowired

    private UserRepo userRepo;

    @Autowired

    private UserMapper mapper;

    public List getAllUsers() {

    return userRepo.findAll().stream().map(mapper::toDto).collect(toList());

    }

    }

    @Component

    public class UserMapper {

    @Autowired

    private OtherClass otherClass;

    public UserDto toDto(User user) {

    UserDto dto = new UserDto();

    dto.setUsername(user.getUsername());

    ... // code using otherClassreturn dto;

    }

    }

    关键点是:始终将复杂的lambda提取到具有表达名称的函数中,然后可以使用以下四点(::)来引用:

    如在同一个类,使用this::;

    在另外一个类似于(mapper::);

    一些静态助手方法(SomeClass::);

    Stream 中条目类型(Item::);

    甚至一些构造函数(),如果它足够简单;UserDto::new

    记住,不要使用匿名类型。

    在这个GitHub存储库中提交了练习的每个阶段,所以请随意浏览存储库以查看所有内容。

    展开全文
  • Java中的lambda匿名函数使用lambda匿名函数的使用是为了满足某些情况下需要临时定义函数,或者事先定义,需要时才使用。在python里面,lambda表达式的表达方式为:lambda 参数: 表达式,例如,需要对一个列表的每项...

    Java中的lambda匿名函数使用

    lambda匿名函数的使用是为了满足某些情况下需要临时定义函数,或者事先定义,需要时才使用。在python里面,lambda表达式的表达方式为:lambda 参数: 表达式,例如,需要对一个列表的每项元素进行加1操作,我们就可以这样:list(map(lambda x: x+1, range(10)),上述表达式中:list(iterables)是将括号里的参数转换成列表样式,参数要求是可迭代对象;map(func, iterables)则是将iterables可迭代对象中的每个元素都调用函数func;lambda x: x+1则是一个匿名函数,参数为x,对x进行加1操作;range(10)则是生成一个[0,1,2,3,4,5,6,7,8,9]的列表,也就是Java中的数组。

    一下是python中的map函数的源码解释

    04e7438ad8c8d49225ec1b110f621484.png

    回到我们的Java,Java中的lambda表达式则有一点不一样,语法为(参数1,参数2) -> statements/block,当不需要参数时,就可以直接写为() -> statement/block,比如说() -> System.out.println("I use lambda")。其实现当时需要一个函数接口,函数接口形如public static void func(Interface action) { statements;},关于函数接口,就是定义一个函数,参数为一个接口类型,里面的语句就是调用接口中定义的方法。因为接口只是定义了,并没有实现方法,所以说当我们将一个形如lambda函数的函数引用传入时,该函数就会直接实现传入的函数。比如说:

    public interface interfaceTest { //定义一个函数接口

    void test();

    }

    public class test {

    public static void main(String[] args) {

    tt(()-> System.out.println("调用lambda"));

    }

    public static void tt(interfaceTest action){

    action.test(); //调用函数接口中未实现的方法

    }

    }

    另外一个带参数的例子:

    public interface interfaceTest { //定义一个函数接口

    void test(int value); //

    }

    public class test {

    public static void main(String[] args) {

    tt(10;(i)-> System.out.println(i+1)); // lambda语句的意思为给参数实行+1操作

    }

    public static void tt(int n,interfaceTest action){

    for (int i=0;i

    action.test(i);

    }

    }

    }

    函数引用。lambda表达式实则上一个函数引用,除此之外还有另一个例子:

    public interface interfaceTest { //定义一个函数接口

    void test();

    }

    public class test {

    public static void main(String[] args) {

    repeat(10, test::test));

    }

    public static void test() {

    System.out.println("hello");

    }

    public static void repeat(int n, interfaceTest action)

    {

    for (int i = 0; i < n; i++) action.test();

    }

    }

    这里函数引用主要有三种情况:

    object::instanceMethod

    Class::staticMethod

    Class::instanceMethod

    就拿第一种来说,就描述的是object中的instanceMethod方法,其中instanceMethod的参数类型需要与定义的函数接口一致,若函数引用中的函数有参数,则函数接口也应该有相应的参数。比如说:

    public interface interfaceTest { //定义一个函数接口

    void test(int value);

    }

    public class test {

    public static void main(String[] args) {

    repeat(10,test::testTwo);

    }

    public static void repeat(int n, interfaceTest action)

    {

    for (int i = 0; i < n; i++) action.testTwo(i);

    }

    public static void testTwo(int n) {

    System.out.println("test:"+n);

    }

    }

    可能有人会说lambda函数跟这个有什么关系,我们看看下面这个:

    0752b3d2b8f8f2c5656d133dcd9c264a.png

    就可以知道,其实函数引用也是属于lambda的一部分。

    展开全文
  • java8使得定义匿名函数成为可能,这在以前的版本中是不可能的。让我们举个例子java docs了解如何声明匿名函数、类下面的示例HelloWorldAnonymousClasses使用Anonymous局部变量初始化语句中的类法语问候语和西班牙语...

    是的,如果您使用的是最新的Java版本8。java8使得定义匿名函数成为可能,这在以前的版本中是不可能的。

    让我们举个例子

    java docs

    了解如何声明匿名函数、类

    下面的示例HelloWorldAnonymousClasses使用Anonymous

    局部变量初始化语句中的类

    法语问候语和西班牙语问候语,但使用本地类

    变量englishgreeting的初始化:

    public class HelloWorldAnonymousClasses {

    interface HelloWorld {

    public void greet();

    public void greetSomeone(String someone);

    }

    public void sayHello() {

    class EnglishGreeting implements HelloWorld {

    String name = "world";

    public void greet() {

    greetSomeone("world");

    }

    public void greetSomeone(String someone) {

    name = someone;

    System.out.println("Hello " + name);

    }

    }

    HelloWorld englishGreeting = new EnglishGreeting();

    HelloWorld frenchGreeting = new HelloWorld() {

    String name = "tout le monde";

    public void greet() {

    greetSomeone("tout le monde");

    }

    public void greetSomeone(String someone) {

    name = someone;

    System.out.println("Salut " + name);

    }

    };

    HelloWorld spanishGreeting = new HelloWorld() {

    String name = "mundo";

    public void greet() {

    greetSomeone("mundo");

    }

    public void greetSomeone(String someone) {

    name = someone;

    System.out.println("Hola, " + name);

    }

    };

    englishGreeting.greet();

    frenchGreeting.greetSomeone("Fred");

    spanishGreeting.greet();

    }

    public static void main(String... args) {

    HelloWorldAnonymousClasses myApp =

    new HelloWorldAnonymousClasses();

    myApp.sayHello();

    }

    }

    匿名类的语法

    考虑FrenchGreeting对象的实例化:

    HelloWorld frenchGreeting = new HelloWorld() {

    String name = "tout le monde";

    public void greet() {

    greetSomeone("tout le monde");

    }

    public void greetSomeone(String someone) {

    name = someone;

    System.out.println("Salut " + name);

    }

    };

    匿名类表达式由以下内容组成:

    这个

    new

    操作人员

    要实现的接口或要扩展的类的名称。在这

    例如,匿名类正在实现接口

    黄色的。

    包含构造函数参数的括号,就像

    普通类实例创建表达式。注意:当您实现

    一个接口,没有构造函数,因此使用

    括号,如本例中所示。

    一个主体,它是一个类声明主体。更具体地说,在

    body,方法声明是允许的,但语句不是。

    展开全文
  • Lambda介绍Lambda,别名函数式编程,维基百科给出以下...Lambda表达式基于数学中的λ演算得名,直接对应于其中的lambda抽象(lambda abstraction),是一个匿名函数,即没有函数名的函数。Lambda表达式可以表示闭包(...

    Lambda介绍

    Lambda,别名函数式编程,维基百科给出以下介绍:

    函数式编程是一种编程范式。它把计算当成是数学函数的求值,从而避免改变状态和使用可变数据。它是一种声明式的编程范式,通过表达式和声明而不是语句来编程。

    Lambda表达式基于数学中的λ演算得名,直接对应于其中的lambda抽象(lambda abstraction),是一个匿名函数,即没有函数名的函数。Lambda表达式可以表示闭包(注意和数学传统意义上的不同)。

    λ 演算是数理逻辑中的一个形式系统,在函数抽象和应用的基础上,使用变量绑定和替换来表达计算。讨论 λ 演算离不开形式化的表达。在本文中,我们尽量集中在与编程相关的基本概念上,而不拘泥于数学上的形式化表示。λ 演算实际上是对前面提到的函数概念的简化,方便以系统的方式来研究函数。

    Java中的Lambda

    自Java8面世以后,也就代表着java从此以后同样支持lambda语法,使得之前繁琐的操作都可以使用简便的语法进行代替,最具代表性的改革就是新增的Stream类,让我们对一个集合的排序、过滤、映射和采集更加方便!

    我们拟定一个场景,对于给定的一个int数组,过滤掉负数,并对剩余的元素进行排序,在java8之前我们的实现需要这么写:

    int[] array = {7, -2, 3, 5, -9, 3, -5, -1, 6, 8, 20};

    List list = new ArrayList();

    //过滤负数

    for(int i: array) {

    if(i >= 0) list.add(i);

    }

    //排序

    Collections.sort(list);

    for(int i: list) {

    System.out.println(i);

    }

    复制代码

    使用Stream之后:

    int[] array = {7, -2, 3, 5, -9, 3, -5, -1, 6, 8, 20};

    Arrays.stream(array)

    .filter(a -> a >= 0) //过滤

    .sorted() //排序

    .forEach(System.out::println);

    复制代码

    可以看到,实现的过程更加简洁和优雅,lambda大大节省了代码空间,提升了代码可读性,但使用的难度也随之提高,对于传统的编程方式,lambda语法无疑是一次重大的冲击。

    Java中Lambda语法的使用

    函数式接口

    什么是函数式接口呢?在Java8之前,我们想实现一个接口,最简单的方式直接使用匿名类:

    Comparator comparator = new Comparator() {

    @Override

    public int compare(Integer o1, Integer o2){

    return o1 > o2 ? 1 : -1;

    }

    };

    复制代码

    这里要注意,Comparator是一个接口类型,它的内部只有一个需要被实现的方法,那么我们将之称之为函数式接口,一般的函数式接口都会加上@FunctionalInterface注解,如果该接口待实现的方法超出两个,你的IDE就会提醒你这不是一个规范的函数式接口,对于符合的,我们就可以使用lambda语法进行初始化:

    Comparator comparator = (o1, o2) -> o1 > o2 ? 1 : -1;

    复制代码

    将之与java8之前的实现对比,我们发现有很多共同之处,我们来分析一下lambda的实现:

    (o1, o2) -> o1 > o2 ? 1 : -1;

    复制代码

    将上部分以->做分割线,分成两部分,它们分别是(o1, o2)和o1 > o2 ? 1 : -1。很明显,前者代表着函数的两个入参,后者代表着两个入参的逻辑实现,由此可得,lambda由两部分组成:入参定义和逻辑实现。

    对于一个函数式接口,我们可以用简单的lambda语法去实现接口内唯一的待实现方法,反推一下,对于lambda这种匿名的函数定义风格,如果一个接口存在两个待实现的方法,lambda则无法具体表示实现的是哪一个方法,由此反推可得,一个函数式接口最多只能有一个待实现方法。

    JDK对Lambda的支持

    通过函数式接口的定义和lambda实现我们知道了lambda语法的一个简单格式,但是在开发过程中,我们不可能对于每一个lambda的应用都定义个函数式接口,实际上,JDK中已经存在了很多lambda函数:

    Function:接受一个参数输入,输入类型为 T,输出类型为 R。 抽象方法为R apply(T)。

    BiFunction:接受两个参数输入, T 和 U 分别是两个参数的类型,R 是输出类型。抽象方法为R apply(T, U)。

    Consumer:接受一个输入,没有输出。抽象方法为 void accept(T t)。

    Predicate:接受一个输入,输出为 boolean 类型。抽象方法为 boolean test(T t)。

    Supplier:没有输入,一个输出。抽象方法为 T get()。

    BinaryOperator:接受两个类型相同的输入,输出的类型与输入相同,相当于 BiFunction。

    UnaryOperator:接受一个输入,输出的类型与输入相同,相当于 Function。

    BiPredicate:接受两个输入,输出为 boolean 类型。抽象方法为 boolean test(T t, U u)。

    它们分别应用于不同的场景,以下将会有几个演示,首先使用lambda实现一个计算器:

    BinaryOperator cal = (a, b) -> a + b;

    System.out.println(bo.apply(1, 2)); // 3

    复制代码

    再来一个,使用lambda实现对数字正负的判断

    int a = 1;

    int b = -1;

    Predicate predicate = i -> i >= 0;

    System.out.println(predicate.test(a)); //true

    System.out.println(predicate.test(b)); //false

    复制代码

    总结

    在Stream中,lambda的应用非常广泛,我们如果想讲lambda更熟练的掌握,需要自己亲自的去使用lambda,在实战中去真正体会lambda的强大之处。

    参考文章

    展开全文
  • 函数式编程(函数式接口):一个接口只包含一个方法实现public interface Lambda{void method();}// 调用Lambda lambda = new Lambda(){};Lambda lambda1 = () - >{};Lambda lambda2 = () ->xxx;Function接口,...
  • 函数式编程(函数式接口):一个接口只包含一个方法实现public interface Lambda{void method();}// 调用Lambda lambda = new Lambda(){};Lambda lambda1 = () - >{};Lambda lambda2 = () ->xxx;Function接口,...
  • 本文笔记于书籍《Java8 函数式编程》Java中提供java.util.concurrent包还有第三方库来处理并发。但对于大型数据集合,Java还需要高效的并行操作。Java8增加Lambda表达式来处理批量数据。面向对象编程是对数据进行...
  • for(Method method : methods) // 对象里为什么只有一个 display 函数呢 ,没有 show 函数? System.out.println(method.getName()); } public static void main(String [] args){ Anonymousfunction anonymous...
  • 本文实例分析了js中匿名函数的创建与调用方法。分享给大家供大家参考。具体实现方法如下:匿名函数就是没有名字的函数了,也叫闭包函数(closures),允许 临时创建一个没有指定名称的函数。最经常用作回调函数...
  • Java匿名函数Lambda

    千次阅读 2019-01-24 10:47:07
    匿名内部类由于没有名字,创建格式如下: 父类名|接口名 对象名 = new 父类构造器(参数列表)|实现接口() { //匿名内部类的类体部分 } 匿名内部类必须要继承一个父类或者实现一个接口,当然也仅能只继承...
  • 匿名内部类也就是没有名字的内部类正因为没有名字,所以匿名内部类只能使用一次,它通常用来简化代码编写但使用匿名内部类还有个前提条件:必须继承一个父类或实现一个接口实例1:不使用匿名内部类来实现抽象方1 ...
  • 1. 概述1.1 函数式编程简介Java作为面向对象的编程语言,如果按照编程种类划分属于命令式编程(Imperative Programming)。常见的编程范式还有逻辑式编程(Logic Programming),函数式编程(Functional Programming)。...
  • Java 匿名函数、构造方法、构造代码块、方法重载与方法重写
  • 因为我写python代码的时候不太有这个思想,写匿名函数很少。这里python\scala\java 三种语言做下对照。 匿名函数,即没有函数名的函数。 目录 1、python关键字 lambda : 2、scala关键字 => 3、java 关键字...
  • 比如Java标准库中的java.lang.Runnable和 java.util.Comparator都是典型的函数式接口。java 8提供@FunctionalInterface作为注解,这个注解是非必须的,只要接口符合函数式接口的标准(即只包含一个方法的接口),虚拟...
  • 以下为译文:大概每个人在学生时代开始就使用Java了,我们一直在学习Java,但Java中总有一些概念含混不清,不论是...匿名类的用法多线程同步的实现序列化一,匿名类Java匿名类很像局部类或内联类,只是没有名字。我...
  • java学习中,匿名函数、构造方法、构造代码块、构造方法中调用构造方法(java 学习中的小记录)作者:王可利(Star·星星)匿名函数匿名对象:没有名字的对象匿名对象使用的注意点:1.一般不会用匿名对象给属性赋值,...
  • 1.lambda表达式排序我们首先看几个比较常见的排序例子,基本数据类型的排序List list = Arrays.asList(1,3,2,5,4);list.sort(Comparator.naturalOrder());System.out.println(list);list.sort(Comparator.reverse...
  • 大概每个人在学生时代开始就使用Java了,我们一直在学习Java,但Java中总有一些概念含混不清,不论是对...1匿名类Java匿名类很像局部类或内联类,只是没有名字。我们可以利用匿名类,同时定义并实例化一个类。只有局...
  • 好程序员Java教程分享Java8.0新特性之Lambda表达式Java 8 已经发布很久了,很多报道表明Java...它允许我们将函数当成参数传递给某个方法,或者把代码本身当作数据处理:函数式开发者非常熟悉这些概念。很多JVM平台上...
  • WindowFunction2.java如下: import org.apache.flink.api.java.tuple.Tuple; import org.apache.flink.api.java.tuple.Tuple2; import org.apache.flink.streaming.api.functions.windowing.WindowFunction; import...
  • .pngJava语言概述Java语言概述.pngJava语言语言描述javaee企业版javase标准版javame小型版JDKJDK(Java开发工具包)Java语言语言Java语言Java关键字Java标识符Java注释Java常量Java变量Java运算符Java语句Java函数Java...
  • 接口的默认方法Java 8使我们能够通过使用default关键词。此功能也称为虚拟可拓方法.下面是我们的第一个例子:interface Formula { double calculate(int a); default double sqrt(int a) { return Math.sqrt(a);...
  • Java 语言是否应增加闭包以及如何添加?在跨越边界 系列最近的一篇文章中,我的朋友兼同事 Bruce Tate 以 Ruby 为例描述了闭包的强大功能。最近在安特卫普召开的 JavaPolis 会议上,听众人数最多的演讲是 Neal ...
  • 很多人反映在学习Java时常常被内部类和匿名类搞晕,接下来就给大家梳理一下内部类与匿名类的相关知识。 内部类: 可以将一个类的定义放在里另一个类的内部,这就是内部类。广义上我们将内部类分为四种:成员内部类...
  • 话不多说,开始今天的学习:现在直播一直都很火,今天我们就用Java代码简单地模拟一个直播案例,以此来一步步说明什么叫函数式编程。不要看这个名字好像挺难懂的样子,其实很简单,两分钟时间即可看完。一、直播间...
  • 下面要给大家讲到的就是java Lambda表达式使用方面的内容,主要是作为参数使用的详解,下面就一起通过文章来进行了解吧。Lambda表达式一种常见的用途就是作为参数传递给方法,这需要声明参数的类型声明为函数式接口...
  • JDK8已经发行有几年了,在该版本中推出了不少新特性,其中比较有代表的新特性有:Lambda表达式,Stream流,方法...为了让更多的Java从业者在学习新特性的时候少走弯路并快速学习新特性的使用,本课程将详细讲解Lam...
  • 作者 |Himanshu Verma译者 | 弯月,责编 | 屠敏出品 | CSDN(ID:CSDNnews)以下为译文:大概每个人在学生时代开始就使用Java了,我们一直在学习Java,但Java中总有一些概念含混不清,不论是对初级还是高级程序员都是...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 4,694
精华内容 1,877
关键字:

java匿名函数

java 订阅