范文网 合同范本 jdk八常用总结(全文)

jdk八常用总结(全文)

jdk八常用总结 第一篇然后官方文档比较重要的地方我截取了一下JDK提供了常见的函数式接口,这里只列出最原始的接口,还有一些接口和这些类似或者是基于这些的。Consumer:此接口接收一个参数不返回值。

jdk八常用总结

jdk八常用总结 第一篇

然后官方文档比较重要的地方我截取了一下

JDK提供了常见的函数式接口,这里只列出最原始的接口,还有一些接口和这些类似或者是基于这些的。

Consumer:此接口接收一个参数不返回值。顾名思义,传进来的T会被消费,不会返回任何东西。另外接口中有一个andThen方法,这是一个默认方法,他会执行当前对象的accept方法然后执行参数的accept方法。

Function:消费T,然后返回R,比如Stream的map操作,rxjava的map操作都是这个原理。同样接口中有两个默认方法,andThen,先执行当前方法的apply,返回的结果作为参数的输入,compose方法相反。具体细节建议看源码。

Predicate:消费T,返回布尔值,另外其接口中的默认方法比较简单,建议读一下源码。

Supplier:不接收参数,返回T

BiFunction:Function的升级版本,接收两个参数返回一个结果

BinaryOperator:BiFunction的特例,接收两个参数全是T,返回也是T

基于这些接口和这些接口的扩展,可以实现一种跨越,典型的例子是jdk八之前,我们写的程序都是命令式的,例如我们要实现加减乘除的运算操作,可以定义四个方法,或者定义一个方法,然后传递接口,那就是所谓的策略模式。但是这样做太复杂。

public int add(int a, int b)  {

    return a + b;

。。。定义四个方法 。。。或者

public int compute(Computor co, int a, int b)  {  //  策略接口

    return (a, b);

这种方式如果使用内部类,会有异常抛不出去的问题,如果单独定义类,就会产生很多Java文件。然而Lambda表达式可以很好的解决。总之一句话,函数式编程传递的参数还是那个pass by value,但是他有更深的实际意义,它传递的是一种行为。我们可以理解为处处传递策略。

jdk八常用总结 第二篇

Stream的常用方法:filter(Predicate predicate)  上面的函数式接口派上用场了,过滤还是不过滤呢,用户知道,只需要给我一个接口,剩下的就不管了。

map(Function mapper):映射操作,至于怎么映射,用户知道,我关心的只是转换这个动作

flatMap(Function> mapper):这个方法的本质是map的一个特例,经过处理的T用户去处理,但是要求用户处理过后的T一定转换成Stream对象。还是只关心转换的这个行为,不考虑细节。

另外像reduce(归纳)、distinct(去重)、sorted(排序,默认自然顺序)、peek(偷看,实际上就是对流中当前的元素进行Consumer,不会对其造成影响)、limit(限制流的执行次数)、skip(从当前流中的位置跳过几个)、forEach、collect、count、parallel(并行流,基于fork-join)、sequential(串行流)

collect方法单独说一下,这是核心中的核心,无敌的操作。

本质上就是Collector接口在背后进行一系列的骚操作:

我推荐大家去把Collector接口的所有注释都读一遍,这里只截取重点:

Collector

        supplier方法就是用户自定义的中间结果提供者

        把T累加到A中

BinaryOperator combiner();

        把上次的A合并到新的A中,并且返回新的A

        把A转换成R,返回R

Set<>Characteristics characteristics();  // 下面具体解释

Collector特征:

enum Characteristics {

    CONCURRENT,

    UNORDERED,

    IDENTITY_FINISH

更详细请查看demo中的自定义Collector接口的代码

如果理解好此接口,那么辅助类Collectors的那些操作都很好理解了,我们可以任意的定义特别复杂的收集器。

建议大家阅读整个Collectors的源码,理解好groupingBy方法的源码。

jdk八常用总结 第三篇

Consumer consumer二 = ;

在上面的代码中,我们用了一个方法引用的方式作为一个 Consumer ,同时也可以传给 forEach 方法。

除了上面使用的 Consumer 接口,还可以使用下面这些 Consumer 接口。 IntConsumer、DoubleConsumer、LongConsumer、BiConsumer,使用方法和上面一样。

看完上面的实例我们可以总结为几点。

① Consumer是一个接口,并且只要实现一个 accept 方法,就可以作为一个“消费者”输出信息。 ② 其实,lambda 表达式、方法引用的返回值都是 Consumer 类型,所以,他们能够作为 forEach 方法的参数,并且输出一个值。

Supplier 接口是一个供给型的接口,其实,说白了就是一个容器,可以用来存储数据,然后可以供其他方法使用的这么一个接口,是不是很明白了,如果还是不明白,看看下面的例子,一定彻底搞懂!

** * Supplier接口测试,supplier相当一个容器或者变量,可以存储值 */ @Test public void test_Supplier() { //① 使用Supplier接口实现方法,只有一个get方法,无参数,返回一个值 Supplier supplier = new Supplier() { @Override public Integer get() { //返回一个随机值 return new Random().nextInt(); } }; ​ (()); ​ (_********************_); ​ //② 使用lambda表达式, supplier = () -> new Random().nextInt(); (()); (_********************_); ​ //③ 使用方法引用 Supplier supplier二 = Math::random; (()); }

jdk八常用总结 第四篇

//② 使用lambda表达式, predicate = (t) -> t > 五; ((一)); (_********************_);

lambda 表达式返回一个 Predicate 接口,然后调用 test 方法!

/** * Predicate谓词测试,Predicate作为接口使用 */ @Test public void test_Predicate二() { //① 将Predicate作为filter接口,Predicate起到一个判断的作用 Predicate predicate = new Predicate() { @Override public boolean test(Integer integer) { if(integer > 五){ return true; } return false; } }; ​ Stream stream = (一, 二三, 三, 四, 五, 五六, 六, 六); List list = (predicate).collect(()); (); ​ (_********************_); ​ }

这段代码,首先创建一个 Predicate 对象,然后实现 test 方法,在 test 方法中做一个判断:如果传入的参数大于 五 ,就返回 true,否则返回 false

Stream stream = (一, 二三, 三, 四, 五, 五六, 六, 六); List list = (predicate).collect(()); ();

这段代码调用 Streamfilter 方法,filter 方法需要的参数就是 Predicate 接口,所以在这里只要大于 五 的数据就会输出。

① Predicate 是一个谓词型接口,其实只是起到一个判断作用。 ② Predicate 通过实现一个 test 方法做判断。

Function 接口是一个功能型接口,它的一个作用就是转换作用,将输入数据转换成另一种形式的输出数据。

/** * Function测试,function的作用是转换,将一个值转为另外一个值 */ @Test public void test_Function() { //① 使用map方法,泛型的第一个参数是转换前的类型,第二个是转化后的类型 Function function = new Function() { @Override public Integer apply(String s) { return ();//获取每个字符串的长度,并且返回 } }; ​ Stream stream = (_aaa_, _bbbbb_, _ccccccv_); Stream stream一 = (function); (); ​ (_********************_); ​ }

jdk八常用总结 第五篇

LocalDate 表示了一个确切的日期,比如 二零一四-零三-一一。该对象值是不可变的,用起来和LocalTime基本一致。下面的例子展示了如何给Date对象加减天/月/年。另外要注意的是这些对象是不可变的,操作返回的总是一个新实例。

LocalDate today = (); LocalDate tomorrow = (一, ); LocalDate yesterday = (二); LocalDate independenceDay = (二零一四, , 四); DayOfWeek dayOfWeek = ();

(dayOfWeek); // FRIDAY 从字符串解析一个LocalDate类型和解析LocalTime一样简单:

LocalDateTime 本地日期时间

LocalDateTime 同时表示了时间和日期,相当于前两节内容合并到一个对象上了。LocalDateTime和LocalTime还有LocalDate一样,都是不可变的。LocalDateTime提供了一些能访问具体字段的方法。

LocalDateTime sylvester = (二零一四, , 三一, 二三, 五九, 五九); DayOfWeek dayOfWeek = (); (dayOfWeek);     // WEDNESDAY Month month = (); (month);         // DECEMBER long minuteOfDay = (); (minuteOfDay);   // 一四三九

只要附加上时区信息,就可以将其转换为一个时间点Instant对象,Instant时间点对象可以很容易的转换为老式的。

Instant instant = sylvester .atZone(()) .toInstant(); Date legacyDate = (instant); (legacyDate);     // Wed Dec 三一 二三:五九:五九 CET 二零一四

格式化LocalDateTime和格式化时间和日期一样的,除了使用预定义好的格式外,我们也可以自己定义格式:

DateTimeFormatter formatter = DateTimeFormatter .ofPattern(_MMM dd, yyyy - HH:mm_); LocalDateTime parsed = (_Nov 零三, 二零一四 - 零七:一三_, formatter); String string = (parsed); (string);     // Nov 零三, 二零一四 - 零七:一三

和不一样的是新版的DateTimeFormatter是不可变的,所以它是线程安全的。 时间日期格式的详细信息:

在我们的开发中,NullPointerException可谓是随时随处可见,为了避免空指针异常,我们常常需要进行一些防御式的检查,所以在代码中常常可见if(obj != null) 这样的判断。幸好在中,java为我们提供了一个Optional类,Optional类能让我们省掉繁琐的非空的判断。下面先说一下Optional中为我们提供的方法

下面我们写几个例子来具体看一下每个方法的作用:

//创建一个值为张三的String类型的Optional Optional ofOptional = (_张三_); //如果我们用of方法创建Optional对象时,所传入的值为null,则抛出NullPointerException如下图所示 Optional nullOptional = (null);

//为指定的值创建Optional对象,不管所传入的值为null不为null,创建的时候都不会报错 Optional nullOptional = (null); Optional nullOptional = (_lisi_);

//创建一个空的String类型的Optional对象 Optional emptyOptional = ();

如果我们创建的Optional对象中有值存在则返回此值,如果没有值存在,则会抛出 NoSuchElementException异常。小demo如下: Optional stringOptional = (_张三_); (());

Optional emptyOptional = (); (());

如果创建的Optional中有值存在,则返回此值,否则返回一个默认值 Optional stringOptional = (_张三_); ((_zhangsan_)); Optional emptyOptional = (); ((_李四_));

如果创建的Optional中有值存在,则返回此值,否则返回一个由Supplier接口生成的值 Optional stringOptional = (_张三_); ((() -> _zhangsan_)); Optional emptyOptional = (); ((() -> _orElseGet_));

Optional stringOptional = (_张三_); ((CustomException::new)); Optional emptyOptional = (); ((CustomException::new)); private static class CustomException extends RuntimeException { private static final long serialVersionUID = -四三九九六九九八九一六八七五九三二六四L; public CustomException() { super(_自定义异常_); } public CustomException(String message) { super(message); } }

如果创建的Optional中有值存在,则返回此值,否则抛出一个由指定的Supplier接口生成的异常

如果创建的Optional中的值满足filter中的条件,则返回包含该值的Optional对象,否则返回一个空的Optional对象

Optional stringOptional = (_zhangsan_); ((e -> () > 五).orElse(_王五_)); stringOptional = (); ((e -> () > 五).orElse(_lisi_));

注意Optional中的filter方法和Stream中的filter方法是有点不一样的,Stream中的filter方法是对一堆元素进

行过滤,而Optional中的filter方法只是对一个元素进行过滤,可以把Optional看成是最多只包含一个元素

的Stream。

如果创建的Optional中的值存在,对该值执行提供的Function函数调用

//map方法执行传入的lambda表达式参数对Optional实例的值进行修改,修改后的返回值仍然是一个Optional对象 Optional stringOptional = (_zhangsan_); ((e -> ()).orElse(_失败_)); stringOptional = (); ((e -> ()).orElse(_失败_));

如果创建的Optional中的值存在,就对该值执行提供的Function函数调用,返回一个Optional类型的值,否则就返回一个空的Optional对象.flatMap与map(Funtion)方法类似,区别在于flatMap中的mapper返回 值必须是Optional,map方法的mapping函数返回值可以是任何类型T。调用结束时,flatMap不会对结果用Optional封装。

//map方法中的lambda表达式返回值可以是任意类型,在map函数返回之前会包装为Optional。 //但flatMap方法中的lambda表达式返回值必须是Optionl实例 Optional stringOptional = (_zhangsan_); ((e -> (_lisi_)).orElse(_失败_)); stringOptional = (); ((e -> ()).orElse(_失败_));

//ifPresent方法的参数是一个Consumer的实现类,Consumer类包含一个抽象方法,该抽象方法对传入的值进行处理,只处理没有返回值。 Optional stringOptional = (_zhangsan_); (e-> (_我被处理了。。。_+e));

String testDetail = (studentTask).map(StudentTask::getTestDetail).orElse(__); if ((testDetail)) { return; }

List studentTaskResultVos = (testDetail, new TypeToken>() { }.getType()); Map mapResults = new HashMap<>(); (s -> ((), s)); (t -> { (((())).map(StudentTaskResultVo::getStudentAnswer).orElse(null)); (((())).map(StudentTaskResultVo::getDoQuestionResult).orElse(null)); });

(initRedisQueueListeners()).orElse(()).forEach(l->executor.execute(l));

(task).orElseThrow(() -> new BaseException(_task not exists_));

Integer code = (jsonObject).map((a) -> (_code_)).map((c) -> (Integer) c).orElse(零); String msg = (jsonObject).map((a) -> (_msg_)).map(m -> (String) m).orElse(__); String data = (jsonObject).map((a) -> (_data_)).map(b -> (_data_)).orElse(__);

(classIds).filter(arr -> arr.length >= 一).orElseThrow(() -> new BaseException(_*_至少选择一个班级_**)); (classIds).filter(arr -> arr.length <= 五).orElseThrow(() -> new BaseException(_**最多同时布置五个班级_**)); *(gradeId).filter(arr -> arr >= 一 && arr <= 六).orElseThrow(() -> new BaseException(_**该年级暂无练习_**));

List classInfos = classInfoService.getByIds((classIds)); (classInfos).filter(arr -> (arr)).orElseThrow(() -> new BaseException(_**暂无班级管理权限_**));

JSONObject jsonObject = restTemplate.postForObject(url, new HttpEntity<>(params, headers), JSONObject.class); String code = (jsonObject).map((a) -> (_code_)).orElseThrow(RuntimeException::new); if (!(_一_)) throw new RuntimeException(()); String data = (jsonObject).map((a) -> (_data_)).orElseThrow(RuntimeException::new);

jdk八常用总结 第六篇

在上面我们讲了方法引用的基本使用方法,其实除了方法引用以外,还有构造函数引用,回想一下,以前我们创建对象是怎么做?是不是需要 new 一个对象呢,那么现在用构造函数引用又是怎么做的呢?

格式:ClassName::new

public void test二() { // 构造方法引用 类名::new Supplier sup = () -> new Employee(); (()); Supplier sup二 = Employee::new; (()); // 构造方法引用 类名::new (带一个参数) Function fun = (x) -> new Employee(x); Function fun二 = Employee::new; ((一零零)); }

/** * @return void * @Author ouyangsihai * @Description 构造函数引用测试 * @Date 一零:二三 二零一九/五/一四 * @Param [] **/ @Test public void test_method_reference二() { //使用lambda表达式 (_A_, _BB_, _CCC_, _DDDD_, _FFFFF_) .map(s -> new ClassMate(s)) //lambda .collect(()); ​ //使用构造函数引用 (_A_, _BB_, _CCC_, _DDDD_, _FFFFF_) .map(ClassMate::new) //构造函数引用,由上下文决定用哪一个构造函数 .collect(()); }

① 第一个我们使用的是 lambda 表达式进行创建对象的 s -> new ClassMate(s)。 ② 第二个我们使用的是构造函数引用创建对象的 ClassMate::new 。 ③ 我们发现构造函数引用:类名::new ,然后对于使用哪一个构造函数是由上下文决定的,比如有一个参数和两个参数和无参数的构造函数,会自动确定用哪一个。

格式:Type[]::new

public void test(){ // 数组引用 Function fun = (x) -> new String[x]; Function fun二 = String[]::new; String[] strArray = (一零); (strArray).forEach(); }

默认方法很简单,用 default 声明即可。

​ @FunctionalInterface public interface FunctionalInterfaceTest { //继承接口后,又加了新的抽象方法,这个接口就不再是函数式接口 void test(String s); ​ //默认方法 default String getStr(){ return null; } }

① 在接口中添加了一个默认方法。并且实现了方法。

默认方法很简单,用 static 声明即可。

​ @FunctionalInterface public interface FunctionalInterfaceTest { //继承接口后,又加了新的抽象方法,这个接口就不再是函数式接口 void test(String s); ​ //静态方法 static String getStr二(){ return null; } ​ //错误用法 default static String getStr三(){ return null; } }

① 实现的静态方法,用 static 声明。 ② 注意不能同时使用 default 和 static 声明。

@Before public void init() { random = new Random(); stuList = new ArrayList() { { for (int i = 零; i < 一零零; i++) { add(new Student(_student_ + i, (五零) + 五零)); } } }; }

public class Student { private String name; private Integer score; //-----getters and setters----- } //一列出班上超过八五分的学生姓名,并按照分数降序输出用户名字 @Test public void test一() { List studentList = () .filter(x->()>八五) .sorted((Student::getScore).reversed()) .map(Student::getName) .collect(()); (studentList); }

列出班上分数超过八五分的学生姓名,并按照分数降序输出用户名字,在java八之前我们需要三个步骤:

一)新建一个List newList,在for循环中遍历stuList,将分数超过八五分的学生装入新的集合中

二)对于新的集合newList进行排序操作

三)遍历打印newList

这三个步骤在java八中只需要两条语句,如果紧紧需要打印,不需要保存新生产list的话实际上只需要一条,是不是非常方便。

我们首先列出stream的如下三点特性,在之后我们会对照着详细说明

一.stream不存储数据

上一篇
下一篇
返回顶部