初探Java8lambda表达式

要说现在什么火, 估计函数式编程算一个吧,看看人家javascript写起来多爽,java呢?一切皆对象。好像离着函数式编程挺远的,不过在java8中我们终于迎来了类似函数式编程-Java风格的lambda表达式,在用lambda重构你的代码后,啥感觉? 倍爽!

这篇博客我们就来小探一下java8的lambda表达式,领略一下lambda表达式的风骚!

lambda表达式语法

lambda的语句可以用以下伪代码表示,很简单,不过还有很多更简单的表达方式,

(Type ...argument) -> {code}

还有一下变种方式,

(Type ...argument) -> x * y // 执行x * y , 注意有返回值的情况下,这里会自动推导返回

初探lambda表达式

只看语法没什么卵用,最好的学习方法还是在实践中去掌握它。先来几个简单的尝尝鲜吧:用lambda表达式去遍历一个List。在没有lambda之前,我们是怎么遍历一个List的呢?相信大家很熟悉,

List<String> list = Arrays.asList("aaa", "bbb", "ccc");
for(String item : list) {
    System.out.println(item);
}

不多说, 再来看看lambda怎么做,

List<String> list = Arrays.asList("aaa", "bbb", "ccc");
list.forEach((item) -> System.out.println(item));

一行代码搞定!关键代码就是(item) -> System.out.println(item),这样的语法在上面我们已经介绍了,因为只有一句表达式,所以{}可以省略。

等等,上面的方式还不是最简单的,

List<String> list = Arrays.asList("aaa", "bbb", "ccc");
list.forEach(System.out::println);

哎哟,这什么玩意! 嘿嘿,System.out::println等同于(x) -> System.out.println(x)。这种语法我们在下面会详细讲解。

和上面遍历相似,我们再来看看线程现在该怎么写,

new Thread(() -> {
   // do something
   System.out.println("hello thread");
}).start();

恩,简单不? 而且有了上面的基础,也很好理解了。

排序!排序!

在lambda中排序也简单了许多,看下面代码,

String[] array = {"bbb", "ddd", "aaa"};
Arrays.sort(array, (String a, String b) -> a.compareTo(b));

stream

在java8中,Collection多了一个stream方法,stream方法天生就是配合lambda来的,stream提供了好多好用的方法,例如filter用来过滤,下面的代码,我们只打印以a开头的字符串。

List<String> list = Arrays.asList("abc", "abb", "ddd");
list.stream().filter((String item) -> item.startsWith("a"))
        .forEach(System.out::println);

limit,类似sql中的limit,用来限制遍历个数,例如下面代码,我们将遍历List中的前5条数据,

List<String> list = Arrays.asList("abc", "abb", "ddd", "111", "ddd", "yyy", "999");
list.stream().limit(5).forEach(System.out::println);

关于Stream更多好玩的方法,可以去api中查看说明,这里就不一一讲解了。

自定义函数式接口

在上面的代码中,我们都是去使用了系统提供了函数式接口,那我们自己能不能自定义呢?答案是可以的,要自定义函数式接口必须符合以下两个条件。

  1. 该接口中有且仅有一个方法。
  2. 在接口上使用注解@FunctionalInterface (非必须,但良好的编程规范是加上)

遵循上面的规范,我们来自定义一个函数式接口吧,

@FunctionalInterface
interface Func {
    String builder(String firstName, String lastName);
}

哎(二声),一个函数接口搞定了,如何用呢?其实你已经会用了。

Func func = (String first, String last) -> {
 return first + "." + last;
};
System.out.println(func.builder("f", "l"));

恩,太熟悉了,不过估计有朋友想到了更简洁的代码,

Func func = (String first, String last) -> first + "." + last;
System.out.println(func.builder("f", "l"));

俩冒号是个啥

上面我们再用System.out::println的时候说了,System.out::println等同于(x) -> System.out.println(x)。现在就让我们来了解一下这个::

::其实是一种依赖lambda自动推导的语法糖(纳尼? 其实lambda表达式本身在java中就是一种语法糖),概念性的东西我也不会说,下面就让我们用3个例子来学习

一下这个::吧。

class Util {
    public static String getSomething(String a, String b) {
        return a + ";" + b;
    }
}

@FunctionalInterface
interface Func {
    public String get(String a, String b);
}

Func f = Util::getSomething;
System.out.println(f.get("aaa", "bbb"));

主要的代码就是Func f = Util::getSomething了,其实他就等同于Func f = (String a, String b) -> Util.getSomething(a, b)。其实就是用Util.getSomething()去实现了Func的get方法,不过这里看起来是不是有种Util实现了Func接口的感觉,嘿嘿。

上面的getSomething是一个静态方法,如果是实例方法呢?

class Util {
    public String doGet(String a, String b) {
        return a + ";" + b;
    }
}
Util util = new Util();
Func f2 = util::doGet;
System.out.println(f2.get("ccc", "ddd"));

::和构造方法呢?

class Student {
    private String name;

    public Student(String name) {
        this.name = name;
        System.out.println(this.name);
    }
}

@FunctionalInterface
interface StudentInterface {
    Student build(String name);
}

StudentInterface si = Student::new;
Student stu = si.build("loader");

像不像静态工厂模式?恩?

时间: 2024-10-11 21:42:21

初探Java8lambda表达式的相关文章

Java8-Lambda表达式(1)

使用匿名类来表示不同的行为并不令人满意:代码十分的啰嗦,这会影响程序员在实践中使用行为参数化的积极性.在这里,我们会认识Java8中解决这个问题的工具Lambda表达式.它可以让你很简洁第表示一个行为或者传递代码.现在你可以把Lambda表达式看做匿名功能,它基本上没有声明名称的方法,但和匿名类一样,它可以作为参数传递给一个方法. 1.Lambda管中窥豹 我们可以把Lambda表达式理解为简洁地表示课传递的匿名函数的一种方式:它没有名称,但它有参数列表.函数主体.返回类型,可能还有可以抛出的异

Java8-Lambda表达式(2)

1.把Lambda付诸实践:环绕执行模式 让我们通过一个例子,看看在实践中如何利用Lambda和行为参数化来让代码更加灵活,更加简洁.资源处理(例如处理文件或者数据库)时一个常见的模式就是打开一个资源,做一些处理,然后在关闭资源.这个设置和清理阶段总是很类似,并且会围绕着执行处理的那些重要代码.这就是所谓的环绕执行(execute around)模式.如下图所示 例如:在以下代码中,红色部分就是从一个从文件中读取一行所需的模板代码(注意:Java7中,带资源的try语句,它已经简化了代码,因为你

Java8-Lambda表达式(3)

函数式接口定义且只定义了一个抽象方法.函数式接口很有用,因为抽象方法的签名可以描述Lambda表达式的签名.函数式接口的抽象方法的签名称为函数描述符.所以为了应用不同的Lambda表达式,你需要一套能够描述常见函数描述符的函数式接口.Java API 中已经有了几个函数式接口,例如Comparable.Runnable.Callable. 1.系统中的函数式接口 Java8中的java.util.function包中引入了几个新的函数式接口,例如:Predicate.Consumer.Funct

DataBinding初探 数据绑定的用法 ,import 集合类型,绑定的表达式,访问集合类型2

数据绑定的用法 import语法 <data> <import type="android.view.view"/> </data> 如果类名相同,可以启用别名 <import type="android.view.view" /> <import type ="com.example.real.estate.View" alias="Vista" /> import

Key/Value之王Memcached初探:三、Memcached解决Session的分布式存储场景的应用

一.高可用的Session服务器场景简介 1.1 应用服务器的无状态特性 应用层服务器(这里一般指Web服务器)处理网站应用的业务逻辑,应用的一个最显著的特点是:应用的无状态性. PS:提到无状态特性,不得不说下Http协议.我们常常听到说,Http是一个无状态协议,同一个会话的连续两个请求互相不了解,他们由最新实例化的环境进行解析,除了应用本身可能已经存储在全局对象中的所有信息外,该环境不保存与会话有关的任何信息.之所以我们在使用ASP.NET WebForm开发中会感觉不到Http的无状态特

[深入剖析React Native]React 初探

认识React React是一个用于构建用户界面的JavaScript库. React主要用于构建UI,很多人认为React是MVC中的V,即视图. React起源于Facebook的内部项目,用来架设Instagram的网站,并于2013年5月开源. React拥有较高的性能,代码逻辑非常简单,越来越多的人已开始关注和实用它. React特点 声明式设计 - React**采用声明范式**,可以轻松描述应用. 高效 - React通过对DOM的模拟,最大限度地减少与DOM的交互. 灵活 - R

stream_iterator、ostream_iterator 使用初探

STL定义了供输入及输出的iostream iterator类,称为 istream_iterator和ostream_iterator,分别支持单一型别的元素的读取和写入. 使用方法: 1.包含头文件: #include <iterator>  using namespace std;       2.像使用其他iterator一样使用istream_iterator和 ostream_iterator.如:  使用一对"连接至标准输入"的iterator用于标示元素范围

第18课 三目运算符和逗号表达式

1. 三目运算符 (1)三目运算符(a?b:c)可以作为逻辑运算的载体 (2)规则:当a的值为真时,返回变量b的值(而不是变量本身):否则返回c的值. [实例分析]三目运算符初探 #include <stdio.h> int main() { int a = 1; int b = 2; int c = 0; c = a < b ? a : b; //(a<b)?a:b; //以下代码试图根据条件有选择地给a或b变量赋值.但这样的 //代码是错的,因为三目运算符的返回值是a或b变量的

函数式编程初探

[函数式编程初探] 1. 函数是"第一等公民" 所谓"第一等公民"(first class),指的是函数与其他数据类型一样,处于平等地位,可以赋值给其他变量,也可以作为参数,传入另一个函数,或者作为别的函数的返回值. 2. 只用"表达式",不用"语句" "表达式"(expression)是一个单纯的运算过程,总是有返回值:"语句"(statement)是执行某种操作,没有返回值.函数式编