【杏仁】JAVA常用Lambda表达式

前言


【杏仁】写在前面的话

有缘人:
  您好!
  首先,请原谅我把模块化思维用到写文章上,前言部分独立抽离出来写了篇文章,这样【杏仁】系列的文章就可以重复引用了。
  偷懒,始终是程序员最棒的优点。
  偷懒,是一门很高深的艺术,很容易误入歧途,请君三思而行!


背负着你的失望
渐行渐远
不奢求理解
毕竟你生而不是我
                           ——杏仁奶昔随笔


静下心 看风的流动

目录


一、关于Lambda
二、常用方法

注:菜单设置有锚点,点击可直达相关内容

正文


一、关于Lambda[1]

许多热门的编程语言如今都有一个叫做Lambda或者闭包的语言特性,包括比较经典的函数式编程语言Lisp,Scheme,也有稍微年轻的语言比如JavaScript,Python,Ruby,Groovy,Scale,C#,甚至C++也有Lambda表达式。一些语言是运行在java虚拟机上,作为虚拟机最具代表的语言java当然也不想落后。
Java 8给我们带来的几个重量级新特性之一,就是Lambda,借用 Lambda 表达式可以让我们的程序设计更加简洁,不仅让代码变的简单、而且可读、最重要的是代码量也随之减少很多。
不了解Java8是什么,请参考【杏仁】Windows/Linux下安装与配置JDK关于JDK部分内容。

Lambda 表达式都使用 Lambda 运算符 =>,该运算符读为“goes to”。
语法格式
参数列表 => 语句或语句块

以下是lambda表达式的重要特征:
可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。
可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。
可选的大括号:如果主体包含了一个语句,就不需要使用大括号。
可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定明表达式返回了一个数值。

注意:使用Lambda时传入的参数是不可变更的,或者final类型的。
通常不建议通过Lambda修改外层数据。虽然我们可以用匿名内部类来实现Lambda表达式,也可以用Lambda表达式来替换内部类,但并不代表这两者是等价的。这两者在某一个重要概念是不同的:this指代的上下文是不一样的。当您使用内部类时,它将创建一个新的范围。通过实例化具有相同名称的新局部变量,可以从封闭范围覆盖局部变量。您还可以在内部类中使用这个关键字作为它实例的引用。但是,lambda表达式可以使用封闭范围。您不能在lambda的主体内覆盖范围内的变量。
多使用方法引用,尽量避免在Lambda的方法体中使用{}代码块(一行代码解决最好)。

没有绝对的 有的向前 有的原地盛开

二、常用方法[2]

1.用收集器,从List里面取出某个字段,组合成新的List

#对应实体类的List
List beanList = this.BeanService.findEntityList(map);
List idList = beanList .stream().map(e -> e.getId()).collect(Collectors.toList());

#通用的MapList
List> mapList = this.BeanService.getMapList(map);
List userNameList = beanList .stream().map(e -> e.get("userName").toString()).collect(Collectors.toList());

#类似4,5,9,45,21,42的字符串
String idStr = "4,5,9,45,21,42";
List ids = Arrays.asList(idStr .split(",")).stream().map(e -> Long.parseLong(e.trim())).collect(Collectors.toList());

#数组转List
int[] nums = {4,5,9,45,21,42};
List list = Arrays.stream(nums).boxed().collect(Collectors.toList());

2.重写方法、实现接口

#单语句可省return
Runnable runnable=()->System.out.println("Running from Lambda");
#相当于
Runnable runnable=new Runnable(){
    @Override
    public void run(){
        System.out.println("Running without Lambda");
    }
};

new Thread( () -> System.out.println("In Java8, Lambda expression rocks !!") ).start();
#相当于
new Thread(new Runnable() {
    @Override
    public void run() {
        System.out.println("Before Java8, too much code for too little to do");
    }
}).start();

3.循环

List features = Arrays.asList("Lambdas", "Default Method", "Stream API", "Date and Time API");
features.forEach(n -> System.out.println(n));
#或者用::
features.forEach(System.out::println);

4.循环和基础计算

#数组内所有数增加10%,并输出
List numList = Arrays.asList(100, 200, 300, 400, 500);
numList .stream().map((e) -> e + .10*e).forEach(System.out::println);
#结果:110, 220, 330, 440, 550

#增加10%后再求和
double sum= numList .stream().map((e) -> e+ .10*e).reduce((sum, e) -> sum + e).get();
#结果:1650.0

#通过summaryStatistics() 获取个数、最小值、最大值、总和以及平均值
IntSummaryStatistics stats = primes.stream().mapToInt((e) -> e).summaryStatistics();
stats.getMax()
stats.getMin()
stats.getSum()
stats.getAverage()

5.数组内大小写转换并拼接

List strList = Arrays.asList("USA", "Japan", "France", "Germany", "Italy", "U.K.","Canada");
String strChange = strList .stream().map(e -> e.toUpperCase()).collect(Collectors.joining(", "));
#结果变成USA, JAPAN, FRANCE, GERMANY, ITALY, U.K., CANADA

6.数组去重

List numbers = Arrays.asList(9, 10, 3, 4, 7, 3, 4);
List distinct = numbers.stream().map( i -> i).distinct().collect(Collectors.toList());
#结果distinct  = [9, 10, 3, 4, 7]

7.数组过滤与排序

List numbers = Arrays.asList(4, 5, 6,1, 2, 3,7, 8,8,9,10);
#过滤出偶数列表 [4,6,8,8,10]
List evens = integers.stream().filter(i -> i % 2 == 0).collect(Collectors.toList()); 
#排序并且提取出前5个元素 [1,2,3,4,5]
List sortIntegers = integers.stream().sorted().limit(5).collect(Collectors.toList());

8.数据并行处理
Lambda的并行流虽好,但也要注意使用场景。如果平常的业务处理比如过滤,提取数据,没有涉及特别大的数据和耗时操作,则真的不需要开启并行流。我在工作中看到有些人一个只有几十个元素的列表的过滤操作也开启了并行流,其实这样做会更慢。因为多行线程的开启和同步这些花费的时间往往比你真实的处理时间要多很多。但一些耗时的操作比如I/O访问,DB查询,远程调用,这些如果可以并行的话,则开启并行流是可提升很大性能的。因为并行流的底层原理是fork/join,如果你的数据分块不是很好切分,也不建议开启并行流。举个例子ArrayList的Stream可以开启并行流,而LinkedList则不建议,因为LinkedList每次做数据切分要遍历整个链表,这本身就已经很浪费性能,而ArrayList则不会。

#在表达式中加入parallel(),即可调用多个cpu处理
.parallel()
【杏仁】JAVA常用Lambda表达式_第1张图片
www.siner.vip

作者 @杏仁奶昔
2019 年 04月 13 日


  1. 关于Lambda部分 ↩

  2. 常用方法部分 ↩

你可能感兴趣的:(【杏仁】JAVA常用Lambda表达式)