ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

JAVA8的了解和使用

2021-03-14 13:36:01  阅读:190  来源: 互联网

标签:Stream 实现 Optional 接口 了解 使用 方法 JAVA8 表达式


 

java8最重要的是实现函数式编程。即方法本身就是一种数据类型,可作为参数传入。

 

函数式接口

只有一个抽象方法的接口,就叫函数式接口。实现类只需要实现这一个方法即可。只需要实现一个方法,可以写成lambdal表达式。(以往,是可以使用匿名内部类,但匿名内部类的不同之处,要实现接口的所有抽象方法,因此匿名内部类不完全可以用lambdal表达式来代替)

public class TestLambda {
    
    public static void main(String[] args) {
        
        Runnable task = () -> {for (int i = 0; i < 10; i++) {
            System.out.println("it is :" + Thread.currentThread().getName());
        }};
        Thread thread = new Thread(task);
        thread.start();
        
        
        for (int i = 0; i < 10; i++) {
            System.out.println("it is :" + Thread.currentThread().getName());
        }
        
    }

}

以上这种写法,函数式编程。

JDK 1.8 新增加的函数接口:java.util.function,包含了很多类,用来支持 Java的 函数式编程;

Function<T,R>   输入T,返回R

Consumer<T>    输入一个值,没有返回值

Supplier<T>   没有输入值,返回一个值

Predicate<T>   输入一个值,返回一个布尔

 

Lambda表达式

闭包???  java中的体现,内部类,闭包能够将一个方法作为一个变量去存储,这个方法有能力去访问所在类的自由变量。

 就是一个方法。入参->出参。关键在于,lambda可以直接作为方法参数。也就是一个方法【一定有返回值的方法】作为另一个方法的参数。

 

以下是lambda表达式的重要特征:   ()-> { }

  • 可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。
  • 可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号【例如stream对map进行遍历时】。  如果是空参也可以使用()
  • 可选的大括号:如果主体包含了一个语句,就不需要使用大括号。 -> {}
  • 可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定明表达式返回了一个数值。如果有返回值,就要return进行声明

 

Lambda 表达式免去了使用匿名方法的麻烦,并且给予Java简单但是强大的函数化的编程能力。

lambda 表达式只能引用标记了 final 的外层局部变量,这就是说不能在 lambda 内部修改定义在域外的局部变量,否则会编译错误。

public class Java8Tester {

    public static void main(String args[]) {

        final int num = 1;

        Converter<Integer, String> s = (param) -> System.out.println(String.valueOf(param + num));

        s.convert(2);  // 输出结果为 3

    }

 

    public interface Converter<T1, T2> {

        void convert(int i);

    }

}

说明:

Lambda 表达式的局部变量可以不用声明为 final,但是必须不可被后面的代码修改(即隐性的具有 final 的语义), 匿名内部类也是如此;

在 Lambda 表达式当中不允许声明一个与局部变量同名的参数或者局部变量;

跟匿名内部类很像,但范围要小,只能实现函数式接口;

能写成lambda表达式的,都是对于函数式接口,写的都是其实现类,例如stream的操作,方法里写的lamdal都是函数式接口的实现类;

局部的,不能用static修饰,可以调用局部变量(隐式final)和成员变量(无论实例或者静态)

 

方法引用和构造器引用

::两个英文冒号

当lambda表达式,代码块只有一行代码,不仅可以省略花括号,还可以写成方法引用。

 

 

默认方法

Java 8 新增了接口的默认方法。

简单说,默认方法就是接口可以有实现方法,而且不需要实现类去实现其方法。

我们只需在方法名前面加个default关键字即可实现默认方法。  不能加static【就是给实现类用的,不是接口本身用的】,不能private【否则不能继承了】

为什么要有这个特性? 如果修改接口就要修改所有的实现类;所以直接将要接口要修改的部分,即增加的功能,直接在接口进行实现,实现类不需要修改进行实现。此时这个接口类似抽象类了,不仅有抽象方法也有非抽象方法。

首先,之前的接口是个双刃剑,好处是面向抽象而不是面向具体编程,缺陷是,当需要修改接口时候,需要修改全部实现该接口的类【接口定义好规范之后不能随便再修改,否则所有的实现类都要进行修改】,目前的java 8之前的集合框架没有foreach方法,通常能想到的解决办法是在JDK里给相关的接口添加新的方法及实现。然而,对于已经发布的版本,是没法在给接口添加新方法的同时不影响已有的实现。所以引进的默认方法。他们的目的是为了解决接口的修改与现有的实现不兼容的问题。

 

 

流式编程stream

参考:

 https://blog.csdn.net/qq_20989105/article/details/81234175 

 

Java 8 中的 Stream 是对集合(Collection)对象功能的增强,它专注于对集合对象进行各种非常便利、高效的聚合操作(aggregate operation),或者大批量数据操作 (bulk data operation)。

Stream API 借助于同样新出现的Lambda表达式,极大的提高编程效率和程序可读性。

同时它提供串行和并行两种模式进行汇聚操作,并发模式能够充分利用多核处理器的优势,使用fork/join并行方式来拆分任务和加速处理过程。

通常编写并行代码很难而且容易出错, 但使用Stream API无需编写一行多线程的代码,就可以很方便地写出高性能的并发程序。

所以说,Java 8 中首次出现的java.util.stream 是一个函数式语言+多核时代综合影响的产物。 

什么是流【其实是迭代器】
Stream 不是集合元素,它不是数据结构并不保存数据【集合是用来保存数据,是一个容器,是有数据结构的,数组,链表,队列等等】,它是有关算法和计算的,它更像一个高级版本的 Iterator。原始版本的Iterator,用户只能显式地一个一个遍历元素并对其执行某些操作;高级版本的 Stream,用户只要给出需要对其包含的元素执行什么操作,比如 “过滤掉长度大于 10 的字符串”、“获取每个字符串的首字母”等,Stream 会隐式地在内部进行遍历,做出相应的数据转换。【隐性的迭代器,流的形式】

Stream 就如同一个迭代器(Iterator),单向,不可往复,数据只能遍历一次,遍历过一次后即用尽了,就好比流水从面前流过,一去不复返。

而和迭代器又不同的是,Stream 可以并行化操作,迭代器只能命令式地、串行化操作。顾名思义,当使用串行方式去遍历时,每个 item 读完后再读下一个 item。而使用并行去遍历时,数据会被分成多个段,其中每一个都在不同的线程中处理,然后将结果一起输出。Stream 的并行操作依赖于 Java7 中引入的 Fork/Join 框架(JSR166y)来拆分任务和加速处理过程。

 

构造:

因为是迭代器,所以针对的是集合和数组而言,集合和数组都可以构造stream流;

 

类型:

对于基本数据类型,有三种对应的包装类型Stream,IntStream、LongStream、DoubleStream。当然我们也可以用 Stream<Integer>、Stream<Long> >、Stream<Double>,但是boxing和 unboxing会很耗时,所以特别为这三种基本数值型提供了对应的 Stream;

 

转换:

流可以转换成数据结构,集合

 

常见操作:

Intermediate:

map (mapToInt, flatMap 等)、 filter、 distinct、 sorted、 peek、 limit、 skip、 parallel、 sequential、 unordered

Terminal:

forEach、 forEachOrdered、 toArray、 reduce、 collect、 min、 max、 count、 anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 iterator

Short-circuiting:

anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 limit

 

Optional  类

从 Java 8 引入的一个很有趣的特性是 Optional  类。Optional 类主要解决的问题是臭名昭著的空指针异常(NullPointerException)  NEP

本质上,这是一个包含有可选值的包装类,这意味着 Optional 类既可以含有对象也可以为空。

Optional 是 Java 实现函数式编程的强劲一步,并且帮助在范式中实现。但是 Optional 的意义显然不止于此。

 

在 Java 8 之前,任何访问对象方法或属性的调用都可能导致 NullPointerException:

String isocode = user.getAddress().getCountry().getIsocode().toUpperCase();

在这个小示例中,如果我们需要确保不触发异常,就得在访问每一个值之前对其进行明确地检查:

if (user != null) {

    Address address = user.getAddress();

    if (address != null) {

        Country country = address.getCountry();

        if (country != null) {

            String isocode = country.getIsocode();

            if (isocode != null) {

                isocode = isocode.toUpperCase();

            }

        }

    }

}

变得冗长,难以维护。

 

String result = Optional.ofNullable(user)

  .flatMap(User::getAddress)

  .flatMap(Address::getCountry)

  .map(Country::getIsocode)

  .orElse("default");

 

构建

使用  of() 和 ofNullable() 方法创建包含值的 Optional;明确对象不为 null  的时候使用 of()。

如果对象即可能是 null 也可能是非 null,你就应该使用 ofNullable() 方法:

 

获取

get,可能会空,所以获取前判断使用ifPresent此外如果存在可以lamdal对元素进行操作

Optional<ExamProduct> mayExists = this.findByVidAndProductCode(examProduct.getVid(),
    examProduct.getProductCode());
mayExists.ifPresent(product -> examProduct.setId(product.getId()));

 

默认值

如果为空时,就是返默认值。

 orElse(),它的工作方式非常直接,如果有值则返回该值,否则返回传递给它的参数值;

 orElseGet() —— 其行为略有不同。这个方法会在有值的时候返回值,如果没有值,它会执行作为参数传入的 Supplier(供应者) 函数式接口,并将返回其执行结果;

除了 orElse() 和 orElseGet() 方法,Optional 还定义了 orElseThrow() API —— 它会在对象为空的时候抛出异常,而不是返回备选的值;

 

时间类

之前的问题:Date非线程安全,可变;时区问题麻烦

 

Base64

引入作为标准类库

Base64.Decoder和Encoder

 

标签:Stream,实现,Optional,接口,了解,使用,方法,JAVA8,表达式
来源: https://www.cnblogs.com/wenhui2015/p/14532202.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有