13

lambda 表达式 Java vs JS

 3 years ago
source link: https://mp.weixin.qq.com/s/V7IB_NRWcxYSosdoPbFeGw
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

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

1 遍历

  • java代码

List<Integer> 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<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
List<Integer> 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<People> peopleList = Lists.newArrayList();
peopleList.add(new People(10001L, "张三", 0));
peopleList.add(new People(10002L, "李四", 1));
peopleList.add(new People(10003L, "王五", 0));

List<PeopleDto> 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<Integer> 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<People> peopleList = Lists.newArrayList();
peopleList.add(new People(10001L, "张三", 0));
peopleList.add(new People(10002L, "李四", 1));
peopleList.add(new People(10003L, "王五", 0));

// 对人员按性别进行分组
Map<Integer, List<People>> 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<Integer>> list = Arrays.asList(Arrays.asList(1, 2, 3), Arrays.asList(4, 5, 6), Arrays.asList(7, 8, 9));
List<Integer> 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规范中引入了函数式编程,让代码更简洁,易懂,是非常好的一门语言。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK