Java 8 函数式编程入门之Lambda

Lambda表达式&Stream流-函数式编程-java8函数式编程(Lambda表达式,Optional,Stream流)从入门到精通-最通俗易懂 Lambda来自JDK8,可以对匿名内部类进行简化。体现了函数式编程的思想。不需要关注对象,而是要关注要对什么数据做什么操作Lambda表达式是基于"可省略可推导"原则的,关注数据如何进行操作的函数式编程思想的,在函数式接口的匿名内部类的省略。Java8的stream使用的是函数式编程模式,如同它的名字一样,它可以被用来对集合或数组进行链状流式的操作。可以更方便的让我们对集合或数组操作。 阅读详情

前言
Java 8最大的变化非lambda莫属,Java终于可以探索函数式编程的道路。本文专注于Java 8中的lambda及相关的知识点进行介绍,而对于stream流式处理则计划在下一篇文章中进行介绍。

Java 8 函数式编程入门之Lambda

引子

业界大牛Steve Yegge曾经讲述过Java魔鬼国王在全国范围内驱逐动词的故事:

在Java王国中,国王Java靠铁腕统治着他的国家。在这里,名词是最重要的居民,它们扮演了社会主体。相比之下,动词的处境则糟糕的多,它们负责了王国里的所有工作,但却得不到任何尊重;它们没有办法单独出现在社会上,一旦出现,变会立即被名词逮捕。然而"逮捕"本身也是动词,必须去创造一个"逮捕者"协助执行逮捕的动作,而创造和协助又同样是动词…而在世界另一边,有一片贫瘠的土地。这里动词和名词一样是"一等公民"。事实上,名词几乎无所事事,单独出现也没有什么意义,而动词也没有奇怪的法律要求必须被名词包裹…

那么Java王国中的居民真的快乐么?

—————————— 改述自*《名词王国里的死刑》*

要么改变,要么衰亡。通过Java 7 DynamicInvoke的预热,Java 8最大的变化就是引入Lambda表达式,一定程度上支持了函数式编程的范式。相比Lisp自由的语法、Haskell艰深的Monad概念,Java 8 Lambda只提供了非常基础的函数式语法,虽然简单,但也足够友好实用。

Java 8提供了"行为参数化"的模式,支持Lambda匿名函数、闭包、高阶函数等,支持类型推断,同时内置了一批实用的函数接口,并制定了自定义函数接口的设计规范。

Lambda表达式

从匿名类到Lambda

在Java 8出现之前,参数传递上只有基础类型、对象引用、或者接口注入的形式。但我们如果只希望在类的内部使用某个接口时,我们没有必要为每个类都设计一个实现接口的类,此时可以通过匿名类来实现这一功能。示例代码如下:

Thread thread = new Thread(new Runnable() {
  @Override
  public void run() {
    System.out.println("Hello, Anonymous Class!");
  }
});

thread.start();

事实上,匿名类经过javac编译后,通过字节码分析可以看出,匿名类实际上就是采用内部类的实现方式:以Main.java作为源文件名,Javac首先生成Main$1.class,这个类实现了Runnable接口,并用final 修饰,最终Main.class使用了这个类作为内部类

...
  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=4, locals=2, args_size=1
         0: new           #2                  // class java/lang/Thread
         3: dup
         4: new           #3                  // class Main$1
         7: dup
         8: invokespecial #4                  // Method Main$1."<init>":()V
        11: invokespecial #5                  // Method java/lang/Thread."<init>":(Ljava/lang/Runnable;)V
...

上述例子中Runnable接口只有一个方法。Java使用**单一抽象方法(Single Abstract Method, SAM)**来表示行为,常见的例如Runnable接口、Callable接口、Comparable接口等,这些接口或类都只有一个方法,表示一个独立的行为。每次都去实现或者实例化这些行为,并不是值得推荐的方式。在过去,Java经常使用上述匿名类的方式。

但是从以上的例子可以看出,要编写某个接口的行为时,我们必须要书写大量的样板代码。而且参差的缩进、冗长的结构,使得代码可读性大大降低。而Java 8 Lambda则提供了一种轻巧的行为传递方式:

Thread thread = new Thread( () -> System.out.println("Hello, Lambda!") );
thread.start();

通过javap -v,可以看到,Java 8 Lambda使用了Java 7中添加的新指令invokedynamic,以及配套的MethodHandles、MethodHandle、MethodType、CallSite实现动态调用:

...
  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=3, locals=2, args_size=1
         0: new           #2                  // class java/lang/Thread
         3: dup
         4: invokedynamic #3,  0              // InvokeDynamic #0:run:()Ljava/lang/Runnable;
...

传递表达式与方法引用

这种将Lambda表达式直接当作参数传入方法的方式称为传递表达式(pass-through lambda)。使用lambda代替匿名类往往是个不错的注意,但如果我们没有办法一眼看出lambda表达式的作用,又或者代码中充斥含义不明的lambda,那么Lambda化简代码书写的意义还存在吗?事实上,Java 8还提供了另外一种行为传递的方式,方法引用(Method Reference)。方法引用允许我们像往常一样书写类和成员方法,同时允许直接将方法作为参数直接传入另一个方法中。

方法引用允许在传递给方法时直接传入方法名,考虑以下表格的示例,lambda表达式都可以改写成方法引用的形式:

lambda表达式说明改写成方法引用
artist -> search(artist) lambda内使用调用者的内部方法this::search
artist -> Artist.toAbbr(artist)lambda内使用参数类的静态方法Article::toAbbr
artist -> artist.getName()lambda内使用了参数的实例方法Article::getName
(name, country) -> new Artist(name, country)lambda内使用了构造方法Artist::new
(artist, country) -> artist.isBornIn(country)参数既出现在方法名的左边,又出现在方法名的右边Artist::isBornIn

可以看出,方法引用同样是一种简洁的表达方式。上述表格的示例其实并不难理解:当我们使用::索引到方法名时,该方法总会将lambda的形参依次传入自己的参数中;值得注意的是,实例的方法第一个参数总是该实例本身,其次才是方法声明的参数,而类的静态方法则不会将实例传入参数中,事实上,Java在内部实现上就有着类似Python实例方法使用显式self作为第一个参数传入的方式,只是在语法替我们隐藏了而已。

我们可以看到,Lambda匿名表达式虽然简单、方便,但完美的Lambda应该只有一行。比起方法引用,Lambda依然有以下不足:

  1. Lambda缺少文档化的支持,而方法引用可以正常在类中填充文档;
  2. Lambda缺少行为的含义描述,而方法引用的命名就可以指代行为的意义;
  3. 重复的Lambda并不能得到代码复用,而方法引用可以复用代码。

Java中闭包的实现

闭包允许函数将自身运行环境的状态同某个不可见的变量绑定起来,在JavaScript中,闭包是非常常见的设计模式。Java中,我们也可以通过返回一个lambda定义的接口,将需要的环境包裹到函数中,跟随返回的lambda传递到函数外部。

public class Printer {

  public static Runnable print() {
    String location = "World";  // Reference Type
    int value = 2;              // Primtive Type
    Runnable runnable = () -> System.out.println("Hello " + location + value);
    return runnable;
  }
  
  public static void main(String[] args) {
    Runnable runnable = Printer.print();
    runnable.run();
  }
}

但是Java对闭包的要求非常严格:闭包包裹的变量必须是不可变的。如果使用匿名类实现,那么上例中的location必须用final修饰;lambda中虽然不做此要求,但如果尝试在print函数内部改变location的值,则会出现编译错误。这也是有些人质疑Java是否真的实现闭包的原因之一。如果是引用类型,那么如果引用不变,而引用的值发生变化,那么这种改变是被允许的。

现在会有这样的问题:闭包是如何携带了状态的呢?仔细思考一下,JVM是栈模式运行的,方法嵌套则栈不断增高。可能就会这样的情况:print的lambda会在高级别的栈运行,并由print返回到低级别的栈main中,而在mian中又存在更多嵌套的函数,使用了lambda的方法,那么这个lambda将会运行在更高级别的栈上。那么lambda携带的状态location还能否跨栈调用呢?

事实上是不能的。Java在编译时,就将闭包依赖的环境变量写入到方法的字节码中,Java在字节码中会首先将需要的变量依次存储起来。通过javap,我们可以很清除地看到这一点:

public static java.lang.Runnable print();
    descriptor: ()Ljava/lang/Runnable;
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=3, args_size=0
         0: ldc           #2                  // String World
         2: astore_0
         3: iconst_2
         4: istore_1
         5: aload_0
         6: iload_1
         7: invokedynamic #3,  0              // InvokeDynamic #0:run:(Ljava/lang/String;I)Ljava/lang/Runnable;
        12: astore_2
        13: aload_2
        14: areturn

函数接口

函数接口注释@FunctionalInterface

虽然通过定义单一抽象方法,就可以在代码中使用lambda表达式,但并不是每个只包含一个函数的接口或类都表示某个行为,例如Comparable、Closable。因此,对于函数接口,Java 8中要求使用注释@FunctionalInterface对每个表示函数的函数接口进行修饰,该注释会在编译期强制检查接口是否符合函数接口的标准,从而很容易定位问题。

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface FunctionalInterface {}

通过查看注释@FunctionalInterface的源代码,可知该注释需要作用在接口或者类上,并且在JavaDoc和JVM运行时都会保留这个注解。

接口的默认方法与静态方法

Java 8为lambda增添了很多实用的功能,例如为Collection提供了Stream流式的数据处理方法。但这会给兼容性带来不小的难题:如果自定义实现了List、Map的类,那么一旦升级到Java 8,就会因为没有实现stream的方法而导致编译错误。Java 8采用了默认方法的方式来解决Collection接口的兼容性问题,在方法最左端添加default关键字,便可以在接口中实现该方法。

// java.lang.Iterable
public interface Iterable<T> {

    Iterator<T> iterator();

    default void forEach(Consumer<? super T> action) {
        Objects.requireNonNull(action);
        for (T t : this) {
            action.accept(t);
        }
    }
    
    default Spliterator<T> spliterator() {
        return Spliterators.spliteratorUnknownSize(iterator(), 0);
    }
}

// java.lang.Collection
public interface Collection<E> extends Iterable<E> {
  // ...
  default Stream<E> stream() {
    return StreamSupport.stream(spliterator(), false);
  }
}

由于接口没有成员变量,因此默认方法只能通过调用子类的方法修改子类本身。在Collection.stream方法的默认实现中,则调用了父接口spliterator的默认实现。同时,这种默认方法本身也可以被子类或子接口覆盖。这种默认方法相当于为接口实现了默认的行为,当某个接口具有同样的行为特征时,可以使用接口的默认方法而不必使用继承来实现了。

但是,*《Effective Java》*这本书对默认方法的态度是非常保守的:使用默认方法可能会导致接口的实现在没有错误或警告的情况下编译,而在运行时出现异常。书中认为,默认接口就是为了解决兼容性问题(事实上也的确如此),应该避免在现有接口中添加新的默认方法。

Java 8中添加了新的语言特性:可以在接口中实现静态方法。以往的最佳实践是采用静态工厂方法,为某个类设计一个复数形式的工具类,这个类中只包含很多静态方法,例如Object对应的工具类为Objects、Collection对应的工具类为Collections。如果一个方法有充分的语义和某个概念相关,那么就应该将该方法和相关的类或者接口放在一起,而不是放在工具类中,例如Stream中的of方法,可以将参数转化成stream流的形式,进而使用流处理的方法。

public interface Stream<T> extends BaseStream<T, Stream<T>> {
  // ...
  public static<T> Stream<T> of(T t) {
    return StreamSupport.stream(new Streams.StreamBuilderImpl<>(t), false);
  }
}

值得注意的是,虽然@FunctionalInterface修饰的函数接口只能包含一个方法,但是对于默认方法和静态方法则没有任何数量限制,并且在客户端也可以通过类或者实例使用这些方法。在java.util.function中,有相当多的函数接口同时使用了默认方法和静态方法,例如Function、Predicate等。我们自定义一个函数接口:

@FunctionalInterface
public interface SAMInterface {

  void generalFunction ();

  default void defaultFunction(){};

  static void staticFunction(){};
}

通过javac与javap,可以看到该函数接口的方法生成了一个抽象方法,而默认方法则变成了普通方法,静态方法变成了类的静态方法。除了缺少一个构造函数,该接口与直接使用抽象类生成的结构是非常类似的。

  public abstract void generalFunction();
    descriptor: ()V
    flags: ACC_PUBLIC, ACC_ABSTRACT

  public void defaultFunction();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=0, locals=1, args_size=1
         0: return
      LineNumberTable:
        line 6: 0

  public static void staticFunction();
    descriptor: ()V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=0, locals=0, args_size=0
         0: return
      LineNumberTable:
        line 8: 0

内置函数接口

JDK为函数接口提供了丰富的实现,绝大部分情况下,我们都不需要自定义函数接口。在包java.util.function中,一共提供了43个泛型或基本类型的函数接口,可供我们直接使用。而对于我们使用者而言,只需要记住6个基本的函数接口,余下的接口都会非常容易的猜测出来:

Java 8 基本内置函数接口

  1. 单一泛型的函数接口,包括UnaryOperator、BinaryOperator、Predicate、Supplier、Consumer。Java要求泛型不能是基本类型,但是装箱拆箱会导致一定的性能损失,因此java.util.function额外为每种基本类型(int、long、double)实现了上述5个内置接口,例如DoublePredicate、IntSupplier、LongUnaryOperator等,以及一个返回boolean型的BooleanSupplier接口,一共16个。
  2. 双泛型的函数接口,指的是Function。与上同理,java.util.function同样额外提供了关于基本类型(int、long、double)之间、或者与泛型之间相互转换的内置接口,例如DoubleToIntFunction、IntToLongFunction、IntFunction、DoubleFunction、ToLongFunction、ToIntFunction等一共12个。
  3. 接受一个参数的函数接口,包括Predicate、Function、Consumer(这里不包括只能接受一个的UnaryOperator)。java.util.function提供了双泛型参数的版本,例如BiPredicate、BiFunction、BiConsumer一共3个。同时为BiFunction提供了返回基本类型的函数接口,ToIntBiFunction、ToDoubleBiFunction、ToLongBiFunction一共3个。对于Consumer则额外提供了接受单个泛型和一个基本类型参数的函数接口,包括ObjDoubleConsumer、ObjIntConsumer、ObjLongConsumer一共3个。
  4. 6 + 16 + 12 + (3 + 3 + 3) = 43,这样就记下了java.util.function提供的所有内置接口。

参考资料

[1] Richard W. Java 8 函数式编程[M]. 王群锋
[2] Joshua B. Effective Java 3rd Edition
[3] Venkat S. Java 8 idioms

1、Java 8 新特性之 Lambda 表达式与函数式编程入门 本文介绍了 Java 8 的新特性,重点讲解了 Lambda 表达式与函数式编程的基础知识。内容包括 Lambda 表达式的语法、函数式接口的定义与使用、方法引用、变量作用域、默认方法以及接口中的静态方法。通过丰富的代码示例,展示了如何利用这些新特性提升代码的简洁性与灵活性,帮助开发者更高效地进行 Java 开发。 阅读详情

相关推荐

35、Java NIO与函数式编程入门

本文介绍了Java NIO的基础知识及其在高效文件和网络I/O操作中的应用,包括FileChannel的使用、并发访问控制和文件锁定机制。同时,还探讨了Java 8引入的函数式编程特性,如Lambda表达式、函数式接口、方法引用和流(Streams),并通过具体示例展示了如何利用这些特性编写简洁、灵活和高效的代码。最后,文章对Java NIO和函数式编程的核心知识点进行了总结,并提供了适用场景的指导建议。

3a9bq4r8t2y的博客 73

Java函数式编程

函数式接口:有且仅有一个抽象方法的接口Java 中的函数式编程体现就是 Lambda 表达式,所以函数式接口就是可以适用于 Lambda 使用的接口只有确保接口中有且仅有一个抽象方法,Java 中的 Lambda 才能顺利地进行推导如何检测一个接口是不是函数式接口呢?放在接口定义的上方:如果接口是函数式接口,编译通过;如果不是,编译失败。

qq_49487356的博客 9414

S4HANA - Cost Elements成本要素

SAP这里面的配置逻辑很像,就是先建一个对象,然后不停给这个对象附加一些属性,给一个账户附加编号范围,附加账户组。所有模块的维度都在这个表里,看下图的GL,CO,COPA,AA,ML的都在ACDOCA里。要把这5个类型和六大要素对应,先得把六大要素和账户类型对应下(以下是个人理解,不知道对错):当然那个C是新来的,我觉得放在资产下面也行,就不画图了。S4的嵌入式分析是在业务逻辑都整套嵌入的情况下,预开发了数据模型,所以它能提供的就不仅是原始数据了,它能提供的是包含所有相关联的上下文的信息数据。

weixin_45689053的博客 2392

Java 函数式编程

在 Java 8 之前,Java 是没有很明确的函数式编程这么一说的,那之前的 Java 代码都是类、方法等组成的,若想要实现一个很简单的功能往往要写上很多代码,这就非常地不方便。于是,在 Java 8 中更新了一系列与函数式编程相关的内容,比如 Lambda 表达式(新增)、函数式接口(强化),以及配合函数式接口使用的 Stream 流(新增)等。而 Java 中函数式编程的典型代表就是 Lambda 表达式了。函数式接口本质上还是接口,只不过它比较特殊,它有且仅有一个抽象方法。

小康2022的博客 2255

Cadence 中Cutout、Design_Outline 和 Outline的区别

摘要: 在PCB设计中,Cutout、Design_Outline和Outline都与电路板外形相关但用途不同。Cutout用于定义切割区域(如孔、槽),直接影响制造;Design_Outline仅标记设计边界,作为参考不影响切割;Outline则是实际切割轮廓层,用于制造。三者区别在于:Cutout针对具体切割区域,Design_Outline是设计参考,Outline是最终切割依据。设计时需根据需求选择合适层:外形参考用Design_Outline/Outline,切割区域用Cutout。

卤煮小鱼的博客 1783

Colmap参数调优实战:如何通过5个关键设置提升3D重建精度

本文深入探讨Colmap参数调优实战,通过5个关键设置显著提升3D重建精度。重点解析特征匹配参数、BA优化配置、初始化策略、资源分配及动态调整方法,结合量化数据和实际案例,帮助开发者精准优化重建流程,适用于古建筑扫描、无人机航拍等多种场景。

weixin_30872157的博客 430

Java8新特性【函数式编程API、新时间日期处理API、Optional容器类】总结

文章目录1、Lambda表达式1.1什么是Lambda表达式1.2从匿名类到 Lambda 的转换1.3Lambda表达式语法2、函数式接口2.1什么是函数式接口2.2自定义函数式接口2.3内置核心函数式接口2.4接口中常用的默认方法3、方法引用与构造器引用3.1 推荐用法3.2 基本格式3.3 语法详解(了解)3.3.1引用类的静态方法3.3.2 引用对象的实例方法3.3.4 引用类的实例方法3.3.5 构造器引用4、Stream API4.1什么是Stream4.2Stream操作的三个步骤4.2.1创

欢迎来到编程小栈 1534

Copula函数实战:如何用MATLAB计算气象干旱与农业干旱的联合概率?

本文提供了一份基于MATLAB的Copula函数实战指南,详细阐述了如何利用该多变量联合分布函数计算气象干旱与农业干旱的联合概率及条件概率。通过从数据预处理、边缘分布拟合到Copula模型选择与检验的完整流程,帮助环境科学与农业气象研究者量化干旱事件的关联风险,为风险评估提供定量依据。

weixin_29213655的博客 429

Java 函数式编程合集

Java的这个函数式编程,总感觉还是很拗,说是传递的函数,实际上是传递函数所属的对象,然后调用接口,并不是纯的传递函数,只不过是借助lambda简化了一下写法,或者是终于官方提供了一个“传函数”的规范吧。

nickDaDa的博客 3759

VOWIFI--相关的协议文档

一、3GPP相关协议文档 3GPP 23.402 Architecture enhancements for non-3GPP accesse- //重要 整体框架结构和流程,3GPP和NON-3GPP切换 3GPP 36.304  User Equipment (UE) procedures in idle mode //重要,终端在空闲状态下3GPP与NON-3GPP之间的重选方法   3GP

时九博客 3578

数据预处理之数据平滑处理#matlab

介绍基于 MATLAB 的数据平滑方法,主要介绍 smooth 函数、smoothts 函数和 medfilt1 函数的用法。

m0_56619132的博客 2414

Java 8 Lambda 表达式:函数式编程入门

Java 8 Lambda 表达式:函数式编程入门 大家好,我是微赚淘客返利系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿! 一、Lambda表达式的引入 Java 8引入了Lambda表达式,这是一种匿名函数的语法糖,它允许我们以更简洁的方式实现函数式编程。 二、Lambda表达式的基本语法 Lambda表达式...

weixin_30661579的博客 119

从 ABAP 视角看 JSON :7.40 版本带来的那些改变

摘要:ABAP 对 JSON 的原生支持 随着企业系统与外部 API 的交互增多,ABAP 从 NetWeaver 7.40 开始原生支持 JSON 格式。通过复用现有 XML 基础设施,ABAP 团队引入 JSON-XML 概念,使用 sXML Library 和 IF_SXML=>CO_XT_JSON 常量处理 JSON 数据。开发人员可通过 CALL TRANSFORMATION 语句实现 ABAP 数据与 JSON 的双向转换,大幅简化了与外部系统的数据交互。这种标准化的 JSON 处理方式提

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 180

Java 8 函数式编程入门:从 Lambda 到 Stream 并行执行

本文围绕 Java 8 引入的函数式编程特性展开,系统介绍了 Lambda 表达式、Stream API 及其并行执行机制。重点从执行模型角度解析 Stream 的流水线结构、惰性执行策略以及串行流与并行流的差异,并结合 Spliterator 与 Fork/Join 框架说明其底层实现原理,为在实际工程中合理使用 Stream 提供参考。

稳扎稳打,持续进步 1207

医学图像的对抗攻击:模型安全性与鲁棒性分析

医学图像的对抗攻击:模型安全性与鲁棒性分析 ,人工智能,计算机视觉,大模型,AI,本文围绕医学图像的对抗攻击展开,分析了其对AI模型的威胁。介绍了对抗样本定义、攻击原理,以及FGSM、BIM、PGD等常见攻击方法,还给出了相关代码示例。阐述了攻击对模型诊断准确性和可信度的影响,提出对抗训练、输入预处理、模型集成等提升模型安全性与鲁棒性的方法,探讨了评估指标、数据集和流程,分析了实际应用中的挑战与应对策略,最后展望了未来发展趋势。

不踩坑,不知道坑有多深;不总结,踩过的坑白踩。 18万+

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

java c lambda表达式_Java8函数式编程入门

Lambda表达式Lambda表达式是函数式编程的核心。Lambda表达式即匿名函数,它是一段没有函数名的函数体,可以作为参数直接传递给相关的调用者。在第一小节举的例子,一个线程输出"Hello World"字符串:Runnable r = new Runnable() {public void run() {System.out.println("Hello World!");}};new Th...

weixin_29808375的博客 131

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

Java 8 Lambda表达式入门:从匿名内部类到函数式编程

函数式编程是现代软件开发中的重要范式,Java 8引入的Lambda表达式让行为参数化变得更加简洁。在传统Java代码中,匿名内部类常用于传递行为,但冗长的语法结构增加了阅读和维护成本。Lambda表达式作为轻量级匿名函数,配合函数式接口,使开发者能够以更直观的方式表达业务逻辑。通过变量捕获机制和Stream API的结合,集合处理可形成流畅的声明式流水线,显著提升代码可读性。在电商订单处理、批量过滤排序等实战场景中,Lambda与内置函数式接口如Predicate、Consumer灵活组合,替代大量样板代

weixin_33860528的博客 461

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

Java 8 Lambda表达式:从匿名内部类到函数式编程入门

在Java开发中,匿名内部类长期承担着传递行为的任务,但冗长的样板代码、this指向混乱和变量捕获限制,让代码可读性与维护性大打折扣。Java 8引入的Lambda表达式,将行为参数化从理想变为现实,它不仅是语法简化,更是函数式编程思维的入口。理解Lambda本质需要掌握其语法结构、类型推断机制,以及函数式接口这一核心前提。同时,方法引用作为Lambda的简化形态,能进一步提升代码表达力。通过结合Stream API,Lambda能够优雅地完成集合过滤、排序与映射等场景。本文面向工程实践,梳理了从匿名内部类

weixin_34198881的博客 405

java8函数式编程(Lambda表达式,Optional,Stream流)从入门到精通

当流中有大量元素时,我们可以使用并行流去提高操作的效率。JDK5中引入的自动装箱和自动拆箱让我们在使用对应的包装类时就好像使用基本数据类型一样方便。但是在大量的数据不断的重复装箱拆箱的时候,你就不能无视这个时间损耗了。假如接口只有一个 函数需要被重写,则可以使用 Lambda表达式来 代替 类的创建和重写。如果我们自己去用代码实现的话其实会非常的复杂,并且要求你对并发编程有足够的理解和认识。我们之前用到的很多Stream的方法由于都使用了泛型。但是你一定要知道装箱和拆箱肯定是要消耗时间的。

yin_ming_hui的博客 832

Java8新特性实战 开发Lambda表达式排序工具 函数式编程入门

Java8引入Lambda表达式,允许将函数作为方法参数传递。其语法为或,简化匿名内部类的写法。

kaote234c的博客 138

java isprime函数,Java8 编程规范入门之【函数式接口、lambda表达式、方法以及构造器引用】...

函数式接口使用背景我们知道,java是一门面向对象编程语言,java中一切都是面向对象的(除了原始数据类型)。在java中函数(方法)是类/对象的一部分,不能单独存在。而其他一些函数式编程语言如C++、Javascript等语言,可以编写单独的函数并可以直接调用它们。面向对象并非不好,只是有时候需要编写冗长的代码。举个简单的例子,我们需要创建一个Runnable实例,通常我们会使用匿名内部类如下:...

weixin_35440082的博客 354

Java8新特性

Java8新特性Lambda表达式什么是lambda?lambda基础语法函数式接口函数式接口案例JDK8函数式接口分类消费型接口示例供给接口示例函数型接口示例断言型接口示例 Lambda表达式 什么是lambda? lambda表达式是一段可以传递的代码,它的核心思想是将面向对象中的传递数据变成传递行为。 我们回顾一下在使用java8之前要做的事,之前我们编写一个线程时是这样的: Runnab...

const_ 802

Java中的Lambda表达式:从入门到精通

Lambda表达式是Java 8引入的一项重要特性,它为Java编程带来了函数式编程的特性,使得代码更加简洁、灵活和易于理解。本文从基本语法到高级技巧全面介绍了Lambda表达式的应用,希望读者能够通过学习掌握Lambda表达式,提高代码编写的效率和质量。

微赚淘客系统开发者博客 366

Lambda表达式Java教程

在本文中,我们提供了全面的Lambda Expressions Java教程。 1. Lambda Expressions Java教程–简介 Lambda表达式被认为是Java 8中引入的最好的功能之一。Lambda表达式被认为是Java进入函数式编程世界的第一步 。 可以将其视为无需类即可创建的函数。 它也可以像参数一样传递,并且可以在需要时和根据需要执行。 Java Lambda表...

最佳 Java 编程 138
上一篇: 详解 JVM Garbage First(G1) 垃圾收集器
下一篇: 用高阶函数轻松实现Java对象的深度遍历
coderlius
博客等级 码龄9年 141粉丝 10原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值