转载

浅谈Java8

浅谈Java8

前言

项目中偶有使用Java8,了解一些基本的用法,但是没有来得及系统的学习,所以一些概念比较模糊,没有理解透彻,最近把一些教程和书籍细细地看了一下,觉得豁然开朗了许多,之前有些不理解的概念也理清了,在这里总结了一下。

浅谈Java8

函数式编程(面向声明、而非过程)

在Java8中,会看到很多类似下面风格的代码:使用Labmda表达式。这种写法就是一种声明式的写法:告诉计算机要做什么,而不是怎么做。

//我们通过函数声明式的过滤出我们想要的结果。而不是在写个for循环做条件判断,然后筛选结果(过程式)
Arrays.asList(1, 3, 4, 5, 10).stream().filter(v -> v > 5).collect(Collectors.toList());
复制代码

函数接口

只有一个抽象方法,可有多个默认实现的接口。定义一个函数接口,如下:

@FunctionalInterface //添加这个注解后,编译器会检查当前的接口是否符合函数接口规范
public interface Formula {
    double calucalte(int value);

    default int sum(int v1, int v2) { //默认实现方法,当实现接口时可以不实现
        return v1 + v2;
    }

    default double maxValue(Double... values) {//计算所给参数的最大值
        return Arrays.stream(values).max(Double::compareTo).orElse(0.0);
    }
}

复制代码

接口的默认方法

  • 为什么要有这个特性

之前的接口好处是面向抽象而不是面向具体编程,缺陷是,当需要修改接口时候,需要修改全部实现该接口的类。对于已经发布的版本,是没法在给接口添加新方法的同时不影响已有的实现。我觉得这里就解释的很好: 链接

Lambda表达式

  • 为什么使用Lambda表达式?

使得对接口的实现更加简单明了,代码更加清晰,对上面的代码进行测试:

//Java8以前的做法:实例化接口
Formula formu = new Formula() {
  @Override
   public double calucalte(int value) {
        return sum(value, 10);//可以直接调用接口中的默认实现方法
   }
};
System.out.println(formu.calucalte(10));
//使用Lambda表达式的做法:本质上还是接口实现。
Formula formula = a -> a + 1;//语法:参数列表->Lambda主体(相当于函数接口的实现),编译器会对参数类型进行判断
System.out.println(formula.maxValue());
复制代码

函数的传递

在Java的核心类库中,经常可以看到在方法中传递函数,下图是 Collections 类中的一个方法:

浅谈Java8
//Java8之前:
List<Integer> values = Arrays.asList(9, 1, 2, 4, 5);
Collections.sort(values, new Comparator<Integer>() {//往方法中传递函数的代码,该方法需要用到函数的执行结果
    @Override
    public int compare(Integer o1, Integer o2) {
        return o1.compareTo(o2);
    }
});
//Java8:一行代码解决
Collections.sort(values, Integer::compareTo);//方法引用:复用已存在的方法
复制代码

JDK提供函数接口

JDK中提供了很多实用的函数接口,大概列出了一些,具体可看下API文档,在使用过程看下源码可以理解的更透彻。 Stream API 中很多方法使用了这些函数接口。

函数接口 抽象方法 说明
Predicate 断定型 boolean test(T t); 确定给定类型参数是否满足某种约束
Consumer 消费型 void accept(T t); 对给定类型参数进行操作
Supplier 供给型 T get(); 返回结果
R apply(T t) 函数性 R apply(T t); 对T类型进行操作、返回R类型结果
  • 看下这些接口在源码当中的使用:
//Strem类中的filter方法:通过某种规则进行过滤。
Stream<T> filter(Predicate<? super T> predicate);
//使用时用Lambda表达式实现接口
List list = Stream.of(1, 3, 4, 5, 10).filter(v -> v > 5).collect(Collectors.toList());
复制代码

流(Stream)

构建流

如何从值序列、数组、文件来构建流?可用 Stream.of()Arrays.stream() 方法

//由值构建
String s = "sunnyDay";
List list = Stream.of(s).collect(Collectors.toList());//使用Stream.of()构建流
//由数组构建
int[] numbers = {2, 0, 2, 0};
int sum = Arrays.stream(numbers).sum();
复制代码

收集器

stream 中的元素作汇总:生成List、Map

原文  https://juejin.im/post/5e7e1aaf51882573c04cbdcb
正文到此结束
Loading...