lambda 表达式 Java vs JS

函数式编程可以让代码更简洁易懂,更人性化,在主流编程语言中大行其道,像scala, python这些语言都是完全函数式编程语言。而java与javascript这两门前后端分别用得最广泛的语言,也与时俱进各自支持了函数式编程,下面就对它们从各方面进行对比:

1 遍历

  • java代码
List list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
list.forEach(System.out::print);

list.forEach(item->System.out.println(item));
  • 运行结果
  • javascript代码
let list = [1,2,3,4,5,6,7,8,9];
list.forEach(item=>console.log(item));
  • 运行结果
  • 小结
    在遍历数组/集合的时候,java与javascript语法很类似,不分上下。

2 过滤

  • java代码
// 过滤出奇数项
List list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
List oddlist = list.stream().filter(item -> item % 2 == 1)
                .collect(Collectors.toList());
oddlist.forEach(System.out::println);
  • 结果
  • javascript代码
// 过滤出奇数项
let list = [1,2,3,4,5,6,7,8,9];
let oddList = list.filter(item=>item % 2==1);
oddList.forEach(item=>console.log(item));
  • 结果
  • 小结
    在过滤场景中,java需要先把集合转成流(stream),然后再做过滤,而且需要对过滤后的流进行收集(collect),代码显示冗长,多余;相比之下,javascript就非常简洁,代码量少,略胜一筹。

3 映射

映射是把一个对象A通过一定的规则转换成B,经常用在DTO与Enitiy互相转换,或者需要把当前对象构造成接口所需要的格式的场景下。

  • java代码

people类

public class People {

    // id
    private Long id;

    // 姓名
    private String name;

    // 性别
    private Integer gender;


    public People(Long id, String name, Integer gender) {
        this.id = id;
        this.name = name;
        this.gender = gender;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getGender() {
        return gender;
    }

    public void setGender(Integer gender) {
        this.gender = gender;
    }
}

dto类

package cn.weiyisoft.platform.wms.service;

public class PeopleDto {

    // id
    private Long id;

    // 姓名
    private String name;

    // 性别(0:女,1:男)
    private Integer gender;

    // 性别 label
    private String genderLabel;

    public PeopleDto() {
    }

    public PeopleDto(Long id, String name, Integer gender, String genderLabel) {
        this.id = id;
        this.name = name;
        this.gender = gender;
        this.genderLabel = genderLabel;
    }


    @Override
    public String toString() {
        return "PeopleDto{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", gender=" + gender +
                ", genderLabel='" + genderLabel + '\'' +
                '}';
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getGender() {
        return gender;
    }

    public void setGender(Integer gender) {
        this.gender = gender;
    }

    public String getGenderLabel() {
        return genderLabel;
    }

    public void setGenderLabel(String genderLabel) {
        this.genderLabel = genderLabel;
    }
}

转换代码

// entity 转成 dto
List peopleList = Lists.newArrayList();
peopleList.add(new People(10001L, "张三", 0));
peopleList.add(new People(10002L, "李四", 1));
peopleList.add(new People(10003L, "王五", 0));

List peopleDtoList = peopleList.stream().map(item -> {
    PeopleDto peopleDto = new PeopleDto();
    peopleDto.setId(item.getId());
    peopleDto.setName(item.getName());
    peopleDto.setGender(item.getGender());
    peopleDto.setGenderLabel(Objects.equals(item.getGender(), 1) ? "男" : "女");
    return peopleDto;
  }).collect(Collectors.toList());

peopleDtoList.forEach(System.out::println);
  • 结果
PeopleDto{id=10001, name='张三', gender=null, genderLabel='女'}
PeopleDto{id=10002, name='李四', gender=null, genderLabel='男'}
PeopleDto{id=10003, name='王五', gender=null, genderLabel='女'}
  • javascript代码
let peopleList = [{id:1001, name:"张三", gender: 0},{id:1002, name:"李四", gender: 1},{id:1003, name:"王五", gender: 0}];
let perpleDtoList = peopleList.map(item=>({...item, genderLabel: item.gender ===1 ? '男':'女'}));
perpleDtoList.forEach(item->console.log(item));
  • 结果
{id: 1001, name: "张三", gender: 0, genderLabel: "女"}
{id: 1002, name: "李四", gender: 1, genderLabel: "男"}
{id: 1003, name: "王五", gender: 0, genderLabel: "女"}
  • 小结
    java所限于刻板的语言结构,需要写太多太多代码了,setter,getter,构造方法这些代码冗余太多,就算用lombok进行简化,也还是需要几十行的代码,反观,javascript利用它ES6中的析构,以及语言天生的动态扩展属性的能力,写出来的代码是这样的简洁明了,完胜java。

4 聚合(reduce)

  • java代码
List list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
// 选择对每个元素*2,再求和
Integer sum = list.stream().map(item -> item * 2).reduce(0, Integer::sum);

System.out.println(sum);
  • 结果
  • javascript
let list = [1,2,3,4,5,6,7,8,9];
let sum = list.map(item=>item*2).reduce((s, c)=> s+c, 0);
console.log(sum);
  • 结果
  • 结论
    java与javascript不相上下。

5 分组

  • java代码
List peopleList = Lists.newArrayList();
peopleList.add(new People(10001L, "张三", 0));
peopleList.add(new People(10002L, "李四", 1));
peopleList.add(new People(10003L, "王五", 0));

// 对人员按性别进行分组
Map<Integer, List> genderGroup = peopleList.stream().collect(Collectors.groupingBy(People::getGender));

genderGroup.forEach((k, v)->{
  System.out.println("gender:"+ k);
  System.out.println("value:" + new Gson().toJson(v));
});
  • 结果
gender:0
value:[{"id":10001,"name":"张三","gender":0},{"id":10003,"name":"王五","gender":0}]
gender:1
value:[{"id":10002,"name":"李四","gender":1}]
  • javascript代码

非常遗憾,暂时没找到方法。

6 扁平化

扁平化用于降维非常有用,比如把二维数组降维成一维。

  • java代码
// 把二维数组转成一维数组
List<List> list = Arrays.asList(Arrays.asList(1, 2, 3), Arrays.asList(4, 5, 6), Arrays.asList(7, 8, 9));
List collect = list.stream().flatMap(Collection::stream).collect(Collectors.toList());

collect.forEach(System.out::println);
  • 结果
  • javascript
// 把二维数组转成一维数组
let list = [[1,2,3],[4,5,6],[7,8,9]];
let flatList = list.flat();
flatList.forEach(item=>console.log(item))
  • 结果
  • 小结
    在扁平化功能上,js也更简洁,而且可以通过 Infinity 作为参数,扁平化无限维度的数组,如下:
let a = [1,[2,3,[4,[5]]]];  
a.flat(Infinity); // [1,2,3,4,5]  a是4维数组

7 结论

函数式编程作为目前主流的编程方法,确实是非常好用,可以简化代码,避免for, if else这些嵌套,更接近自然语言,也让人更易读懂代码,需要在工作中不断的使用以达到运用自如的目的。
java语言作为一个后端的老牌语言,可以与时俱进,在jdk8中就引入了lambda,已经非常不错,但受限于原有的一些设计,还是需要写太多太多的代码,显示呆板,冗余;相比下,javascript也是前端的老牌语言,在es6规范中引入了函数式编程,让代码更简洁,易懂,是非常好的一门语言。