前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >JAVA8 Lambda表达式到底优不优雅?

JAVA8 Lambda表达式到底优不优雅?

作者头像
疯狂的KK
发布2019-08-16 15:24:35
6700
发布2019-08-16 15:24:35
举报
文章被收录于专栏:Java项目实战Java项目实战

今天看到一个关注很久的公众号,作者是一个10年+的程序员,现在自主创业,他原文中是这么说的:多去看看外面的世界,不要把自己封闭在技术的圈子内,这对自己不管是创业还是挣钱,都有莫大的帮助;

个人虽然很同意他的说法,但是带来的问题就是你如何跻身于高端的,创业大佬的,技术大牛的圈子,人家张嘴就是技术潮流,闭嘴就是互联网一线信息,个人还是觉得踏实提升自己,对于投资自己的脑袋这件事深表认同。

目前JAVA版本每半年更新已到JAVA12了,虽然工作中用的是JDK1.8,但不用他的特性是不是有点浪费?针对各个版本的新特性,应该1.8是相当稳定,适用性最多,使用率最高的版本,毕竟新版本还有待市场考察。

那么JAVA8到底有多优雅呢?首先看下都有神马新特性

我们从代码角度体会下JAVA8的好处;

需求:设计接口实现对对象属性的过滤。

方案:除去SQL编写方式外,一般我们都会针对接口编程

公共属性:Employee

代码语言:javascript
复制
public class Employee {
    private Integer id;
    private Integer age;
    private Integer salary;
    private String name;
    public Employee(Integer id, Integer age, Integer salary, String name) {
        this.id = id;
        this.age = age;
        this.salary = salary;
        this.name = name;
    }
    @Override
    public String toString() {
        return "Employee{" +
                "id=" + id +
                ", age=" + age +
                ", salary=" + salary +
                ", name='" + name + '\'' +
                '}';
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Employee() {
    }
    public Employee(Integer id, Integer age, Integer salary) {
        this.id = id;
        this.age = age;
        this.salary = salary;
    }
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    public Integer getSalary() {
        return salary;
    }
    public void setSalary(Integer salary) {
        this.salary = salary;
    }

}

方案一:针对接口编程,定义接口,逻辑放在实现类

代码语言:javascript
复制
public interface MyProduce<T> {

    boolean bySalary(Employee employee);
}
代码语言:javascript
复制
public class MyProduceImpl implements MyProduce<Employee> {
    @Override
    public boolean bySalary(Employee employee) {
        return employee.getSalary()>5000;
    }
}
代码语言:javascript
复制
public class TestJava8 {

        List<Employee> employees= Arrays.asList(
            new Employee(1,20,2000,"张三"),
            new Employee(2,30,28000,"李四"),
            new Employee(3,40,1000,"王五"),
            new Employee(4,50,5000,"赵六")
        );
}

实现过滤工资小于5000的员工

代码语言:javascript
复制
 public List<Employee> filterEmployee(List<Employee> list,MyProduce<Employee> mp) {
        List<Employee> emps = new ArrayList<>();
        for (Employee employee : list) {
            if (employee.getSalary() < 5000) {
                emps.add(employee);
            }
        }
        return emps;
    }
代码语言:javascript
复制
@Test
    public void test1(){
        List<Employee> employees = filterEmployee(this.employees, new MyProduce<Employee>() {
            @Override
            public boolean bySalary(Employee employee) {
                return employee.getSalary() <5000;
            }
        });
        for (Employee employee : employees) {
            System.out.println(employee);
        }
    }

方案二:匿名内部类

代码语言:javascript
复制
   @Test
    public void test2(){
        List<Employee> employee = filterEmployee(employees, new MyProduce<Employee>() {
            @Override
            public boolean bySalary(Employee employee) {
                return employee.getSalary() < 5000;
            }
        });
        for (Employee emp : employee) {
            System.out.println(emp);
        }
    }

方案三:Lambda表达式

代码语言:javascript
复制
@Test
    public void test3(){
        List<Employee> employees = filterEmployee(this.employees,(e)->e.getSalary()>5000);
        employees.forEach(System.out::println);
    }

方案四:Stream流,工资大于5000的前2位员工,打印出员工的名称,不需要任何接口

代码语言:javascript
复制
 @Test
    public void test4(){
        employees.stream()
                 .filter((e)->e.getSalary()>=5000)
                 .limit(2)
                 .forEach(System.out::println);
        employees.stream()
                 .map(Employee::getName)
                .forEach(System.out::println);
        }

省掉了各种过滤的接口,各种实现方法的调用,且流式调用,要多方便有多方便,要多简洁有多简洁。代码量更少,功能更强大

Lambda表达式

为什么使用 Lambda 表达式

Lambda 是一个匿名函数,我们可以把 Lambda 表达式理解为是一段可以传递的代码(将代码像数据一样进行传递)。可以写出更简洁、更灵活的代码。作为一种更紧凑的代码风格,使Java的语言表达能力得到了提升。

Lambda表达式的语法

Lambda 表达式在Java 8 语言中引入了一个新的语法元素和操作符。这个操作符为 “->” , 该操作符被称为 Lambda 操作符或箭头操作符。它将 Lambda 分为两个部分:

左侧:指定了 Lambda 表达式需要的参数列表

右侧:指定了 Lambda 体,即 Lambda 表达式要执行的功能。

函数式接口:接口中只有一个抽象方法的接口,SAM类型的接口(Single Abstract Method)。定义了这种类型的接口,使得以其为参数的方法,可以在调用时,使用一个lambda表达式作为参数

语法格式:

1.0:无参数无返回值

() ->System.out.println("Hello");

2.0:有一个参数无返回值

Consumer<String> con=(x)->System.out.println("x");

3.0: 只一个参数无返回值,小括号可以省略不写

习惯上写小括号

4.0:多个参数,有返回值,Lambda体中有多条语句

Comparator<Integer> com=(x,y)->{

System.out.println("多条语句");

return Integer.compare(1,2);

};

5.0:多个参数,有返回值,Lambda体中有一条语句,return 和大括号都可以不写

6.0:Lambda参数列表的类型可以省略不写,JVM可通过向上下文推断数据类型

总结:左右遇一括号省,

左侧推断类型省,

@FunctionalInterface检查是否是函数式接口

1. 默认方法与静态方法并不影响函数式接口的契约,可以任意使用

2. 可以有 Object 中覆盖的方法,也就是 equals,toString,hashcode等方法。

JDK 8之前已有的函数式接口:

java.lang.Runnable

java.util.concurrent.Callable

java.util.Comparator

java.io.FileFilter

java.lang.reflect.InvocationHandler

代码语言:javascript
复制
import java.util.Objects;
/**
 * Represents an operation that accepts a single input argument and returns no
 * result. Unlike most other functional interfaces, {@code Consumer} is expected
 * to operate via side-effects.
 *
 * <p>This is a <a href="package-summary.html">functional interface</a>
 * whose functional method is {@link #accept(Object)}.
 *
 * @param <T> the type of the input to the operation
 *
 * @since 1.8
 */*表示接受单个输入参数,并返回无返回值。与大多数其他功能接口不同,需要@code consumer*通过副作用操作@FunctionalInterface
public interface Consumer<T> {}

注意事项:

代码语言:javascript
复制
 @Test
    public void test5(){
       int num=8;//????
        Runnable r=new Runnable(){
            @Override
            public void run() {
                System.out.println("Hello:"+"\t"+num);
            }
        };
        r.run();
        Runnable r1= ()-> System.out.println("HELLO:"+"\t"+num);
        r1.run();
    }

在1.8以前局部内部类中应用了一个同级别的局部变量,他应该是final的

但是为什么java8不需要也能编译通过呢?其实底层他还是final的,我们验证一下

变量num是来自内部类,需要final或者实际上是final的,说明1.8进行了底层加final;

然后说下网上的关于java8 Lambda表达式的性能问题。搜索结果验证说用了Lambda反而性能下降了,执行foreach时间长了,特别是大数据遍历。还拿了并行代码对比,我觉得要看实际的用途,看看Lambda解决问题的侧重点,lambda写的好可以极大的减少代码冗余,同时可读性也好过冗长的内部类,匿名类。

本身就是侧重于减少代码冗余的,你非得谈性能?

6月最后一天啊,针对于年初计划,执行情况做一下小总结,年初定了年度计划目标,年中,年末做一个检查,5年后回味自己的今天,希望有质的提升

2019年6月30日:

1.今天是听得到APP历史记录1242条的一天。

2.今天是百词斩APP背单词累计的第394天,背单词数4866个

3.今天是一年写40篇文章计划的第26篇

好的今天记录就到这里。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-06-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 赵KK日常技术记录 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Lambda表达式
    • 为什么使用 Lambda 表达式
      • Lambda表达式的语法
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档