Lambdas:来到您附近的Java 8!

什么是Lambda?

Lambda表达式是一种匿名函数,可以在方法中内联编写,并且可以在使用表达式的任何地方使用。 有时您可能会发现它们被称为闭包,尽管我在下面解释了对该参考的一些注意事项。 像普通的Java方法一样,它具有参数和可以执行的主体。 lambda表达式是Java 8中令人兴奋的新功能之一,它已定义为JSR 335的一部分。

添加lambda表达式将使Java更轻松地支持函数式编程技术和高阶函数。 这并不是说突然变成一夜之间成为一种异乎寻常而深奥的语言(例如Haskell),但是它将朝着与C#,Ruby或python之类的语言相同的方向发展。 也就是说,为有意义的功能样式提供部分支持,但仍然允许您使用命令式技术,例如可变变量。

基本语法

这是一个lambda表达式,它使数字增加1:

x -> x + 1

如您所见,表达式以参数开头,以参数主体结尾,并用箭头将两者分开。 您也可以显式键入参数,在类型注释上放置类型注释或具有多个参数。 如果您想执行这些操作,则需要将参数放在方括号中,例如:

// Explicit Types
    (Integer x) -> x + 1
    // Multiple Arguments
    (Integer x1, Integer x2) -> x1 + 1
    // Annotations:
    (Integer x1, @SuppressWarnings("unused") Integer x2) -> x1 + 1

到目前为止,所有的lambda主体都是表达式,但是您也可以像常规方法一样,将主体编写为一系列语句。

(x) -> { 
    x += 5; 
    System.out.println(x); 
    return x; 
};

由于lambda是正则表达式,因此您可以将其视为正则表达式。 例如,您可以将它们分配给变量,将它们作为参数传递给其他方法。

// a method: 
public static void useFunc(IntFun f) { 
    System.out.println(f.apply(2)); 
} 

// in code 
IntFun inc = x -> x + 1; 
useFunc(inc); 
useFunc(x -> x + 1);

类型?

由于这是Java,因此即使不是所有这些“ x”参数都标记为“整数”,所有这些函数仍然是静态类型的。 幸运的是,Java 7中方法句柄的引入提供了一种引用方法本身的方法。 这意味着您的函数并不需要全部实现某个通用接口,它们可以是被认为是“函数接口”的任何东西。

引用规范草案,“功能接口是仅具有一种抽象方法的接口,因此表示单个功能协定。” 这些也可以用首字母缩写词“ SAM”来表示,它代表“单一抽象方法”。 例如:

interface Runnable { void run(); } 

interface Function { public R apply(A a); } 

interface IntFun extends Function {} 

// equals is defined by java.lang.Object, so this only has one abstract method 
interface Comparator { 
    boolean equals(Object obj); 
    int compare(T o1, T o2); 
}

因此,通过确保使用保持这些约束的接口,当前正在编写/正在编写的任何API都可以被lambda使用。 Guava库是一个已经鼓励有限的函数编程风格的示例API。

更有趣的例子

经验丰富的函数式程序员会意识到map函数,该函数会为您返回一个新列表,其中每个值都由函数更改。 在番石榴世界中,此功能称为“变换”。 这是您今天可以编写的一些Java代码示例,使用它来递增列表:

Collection result = transform(newArrayList(1, 2, 3), new Function() { 
    @Override 
    public Integer apply(Integer x) { 
        return x + 1; 
    } 
});

这是一个高阶函数的示例,即以函数为参数或返回函数的函数。 转换功能使迭代集合的过程抽象化,并建立一个新的集合,从而可以编写更多抽象的高级代码。 不幸的是,由于强制使用了许多行噪声,因此在一定程度上克服了可读性的优势,但是如果您使用lambda重写它:

Collection result = transform(newArrayList(1, 2, 3),x -> x + 1);

另一个常用的高阶函数是滤波函数。 如果为它提供一个集合和一个谓词,它将返回一个新集合,其中包含谓词对其适用的旧集合中的元素。 这是一个用匿名内部类样式和lambda表达式方式编写的代码示例。

Collection threeAndFive = filter(newArrayList(1, 3, 5), new Predicate() { 
    @Override 
    public boolean apply(Integer x) { 
        return x > 2; 
    } 
}); 

Collection threeAndFiveByLambda = filter(newArrayList(1, 3, 5),x -> x > 2);

方法参考

当然,您可能已有一个已经定义了许多方法的现有代码库,您希望使用它们代替lambda。 目前,这在Java中使用匿名内部类也是可能的,但同样麻烦。 除了提供lambda表达式外,JSR 335还提出了一些语法糖,以使此过程更容易。 您可以使用'::'符号作为已编写的现有方法的方法参考。 这是前面的示例,但是使用了方法参考:

// Existing method 
public static boolean greaterThanTwo(Integer x) { 
    return x > 2; 
} 

// prints [3, 5] 
System.out.println(filter(newArrayList(1,3,5),LambdasExample::greaterThanTwo));

他们真的是闭包吗?

在引言中,我提到过lambda表达式可以称为closures 。 这意味着一个函数能够引用其正常范围之外的变量,或者被封闭在周围范围的自由变量之上。

int value = 5; 

IntFun addValue = x -> x + value;

在此代码示例中,“ addValue”函数能够在周围的范围内引用名为“ value”的变量,尽管对此有一些警告。 如果您之前编写过匿名内部类,那么您会记得它们只能引用标记为final的周围变量,即未分配给它们。 这里的限制是相似的,只是它已被概括为最终有效的限制 。 简而言之,您可以引用未分配给多个变量的变量。 原理是,如果将变量标记为final或可以将其标记为final而不引入编译器错误,则该变量实际上是final。

尝试和链接

lambdas规范的早期草案审核的一部分已经在线发布,并且如果您想了解正在发生的事情的来龙去脉,那么这可能对您来说很有趣。 如果您有兴趣尝试编写一些lambda代码,则已经有二进制快照 。 这些内容经常更新,如果您想了解lambda内部结构的实质,可以尝试构建源代码 。 关于使用二进制代码编写代码的唯一警告是,由于它仍处于草稿版本中,并且仍使用“#”运算符代替“ ::”作为方法参考语法,因此它仍然存在一些bug。

摘要

这是对Java 8 Lambda表达式的一些概念的介绍,因此简化了所涉及的一些问题,但是对于读者来说,了解即将发生的事情应该足够了。 很高兴看到Oracle在事物的语言方面引入了一些有用的更改,这种更改已经停滞了一段时间。

参考: Lambdas:来到您附近的Java 8! 从我们的JCG合作伙伴 Richard Warburton在Insightful Logic博客上获得。

翻译自: https://www.javacodegeeks.com/2013/07/lambdas-coming-to-a-java-8-near-you.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
lambdas Preface. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . vii 1. Introduction. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 Why Did They Need to Change Java Again? 1 What Is Functional Programming? 2 Example Domain 3 2. Lambda Expressions. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 Your First Lambda Expression 5 How to Spot a Lambda in a Haystack 6 Using Values 8 Functional Interfaces 9 Type Inference 11 Key Points 13 Exercises 14 3. Streams. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 From External Iteration to Internal Iteration 17 What’s Actually Going On 20 Common Stream Operations 21 collect(toList()) 22 map 22 filter 24 flatMap 25 max and min 26 A Common Pattern Appears 27 reduce 28 Putting Operations Together 30 Refactoring Legacy Code 31 iii Multiple Stream Calls 34 Higher-Order Functions 36 Good Use of Lambda Expressions 36 Key Points 37 Exercises 37 Advanced Exercises 39 4. Libraries. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 Using Lambda Expressions in Code 41 Primitives 42 Overload Resolution 45 @FunctionalInterface 47 Binary Interface Compatibility 47 Default Methods 48 Default Methods and Subclassing 49 Multiple Inheritance 52 The Three Rules 53 Tradeoffs 54 Static Methods on Interfaces 54 Optional 55 Key Points 56 Exercises 57 Open Exercises 58 5. Advanced Collections and Collectors. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 Method References 59 Element Ordering 60 Enter the Collector 62 Into Other Collections 62 To Values 63 Partitioning the Data 64 Grouping the Data 65 Strings 66 Composing Collectors 67 Refactoring and Custom Collectors 69 Reduction as a Collector 76 Collection Niceties 77 Key Points 78 Exercises 78 6. Data Parallelism. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81 Parallelism Versus Concurrency 81 iv | Table of Contents Why Is Parallelism Important? 83 Parallel Stream Operations 83 Simulations 85 Caveats 88 Performance 89 Parallel Array Operations 92 Key Points 94 Exercises 94 7. Testing, Debugging, and Refactoring. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97 Lambda Refactoring Candidates 97 In, Out, In, Out, Shake It All About 98 The Lonely Override 98 Behavioral Write Everything Twice 99 Unit Testing Lambda Expressions 102 Using Lambda Expressions in Test Doubles 105 Lazy Evaluation Versus Debugging 106 Logging and Printing 106 The Solution: peek 107 Midstream Breakpoints 107 Key Points 108 8. Design and Architectural Principles. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109 Lambda-Enabled Design Patterns 110 Command Pattern 110 Strategy Pattern 114 Observer Pattern 117 Template Method Pattern 119 Lambda-Enabled Domain-Specific Languages 123 A DSL in Java 124 How We Got There 125 Evaluation 127 Lambda-Enabled SOLID Principles 127 The Single Responsibility Principle 128 The Open/Closed Principle 130 The Dependency Inversion Principle 134 Further Reading 137 Key Points 137 9. Lambda-Enabled Concurrency. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139 Why Use Nonblocking I/O? 139 Callbacks 140 Table of Contents | v Message Passing Architectures 144 The Pyramid of Doom 145 Futures 147 Completable Futures 149 Reactive Programming 152 When and Where 155 Key Points 155 Exercises 156 10. Moving Forward 159

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值