biFunction) {
+ return biFunction.apply(name, age);
+ }
+}
diff --git a/core-java-modules/core-java-8/src/main/java/com/wdbyte/Jdk8Base64.java b/core-java-modules/core-java-8/src/main/java/com/wdbyte/Jdk8Base64.java
new file mode 100644
index 0000000..c50f47c
--- /dev/null
+++ b/core-java-modules/core-java-8/src/main/java/com/wdbyte/Jdk8Base64.java
@@ -0,0 +1,36 @@
+package com.wdbyte;
+
+import java.nio.charset.StandardCharsets;
+import java.util.Base64;
+
+/**
+ *
+ * JDK8 对 base64 编码的支持
+ *
+* @Author https://www.wdbyte.com
+ * @Date 2019/6/12 9:47
+ */
+public class Jdk8Base64 {
+
+ public void base64Test() {
+ String text = "1234567";
+ // 编码
+ String encoded = Base64.getEncoder().encodeToString(text.getBytes(StandardCharsets.UTF_8));
+ System.out.println(encoded);
+
+ // 解码
+ String decoded = new String(Base64.getDecoder().decode(encoded), StandardCharsets.UTF_8);
+ System.out.println(decoded);
+
+ // url 编码
+ String url = "https://www.baidu.com/s?wd=jdk8";
+ String urlEncoded = Base64.getUrlEncoder().encodeToString(url.getBytes(StandardCharsets.UTF_8));
+ System.out.println(urlEncoded);
+ String urldecoded = new String(Base64.getUrlDecoder().decode(urlEncoded), StandardCharsets.UTF_8);
+ System.out.println(urldecoded);
+
+ // Result
+ // MTIzNDU2Nw==
+ // 1234567
+ }
+}
diff --git a/core-java-modules/core-java-8/src/main/java/com/wdbyte/Jdk8Function.java b/core-java-modules/core-java-8/src/main/java/com/wdbyte/Jdk8Function.java
new file mode 100644
index 0000000..9d14a98
--- /dev/null
+++ b/core-java-modules/core-java-8/src/main/java/com/wdbyte/Jdk8Function.java
@@ -0,0 +1,124 @@
+package com.wdbyte;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.function.Predicate;
+
+
+/**
+ *
+ * 方法引用,通过方法的名字指向一个方法
+ *
+ * - Supplier: 数据提供器,可以提供 T 类型对象;无参的构造器,提供了 get 方法
+ * - Function: 数据转换器,接收一个 T 类型的对象,返回一个 R类型的对象; 单参数单返回值的行为接口;提供了 apply, compose, andThen, identity 方法
+ * - Consumer: 数据消费器, 接收一个 T类型的对象,无返回值,通常用于设置T对象的值; 单参数无返回值的行为接口;提供了 accept, andThen 方法
+ * - Predicate: 条件测试器,接收一个 T 类型的对象,返回布尔值,通常用于传递条件函数; 单参数布尔值的条件性接口。提供了 test (条件测试) , and-or- negate(与或非) 方法。
+ *
+* @Author https://www.wdbyte.com
+ * @Date 2019/2/18 22:08
+ */
+public class Jdk8Function {
+
+ public void testFunction() {
+ // 构造器引用
+ final Car bmwCar = Car.create(Car::new);
+ bmwCar.setName("BMW");
+ final Car audiCar = Car.create(Car::new);
+ audiCar.setName("AUDI");
+ List cars = Arrays.asList(bmwCar, audiCar);
+ // 静态方法引用
+ cars.forEach(Car::collide);
+ // 特定类的任意对象的方法引用
+ cars.forEach(Car::repair);
+ // 特定对象的方法引用
+ cars.forEach(bmwCar::follow);
+ }
+
+ /**
+ * 函数接口
+ */
+ public void functionInterfaceTest() {
+ List skills = Arrays.asList("java", "golang", "c++", "c", "python");
+ Predicate length4 = (str) -> str.length() > 4;
+ filterByForeach(skills, length4);
+ System.out.println("----------------------");
+ filterByFilter(skills, length4);
+ }
+
+ /**
+ * 接收函数参数
+ *
+ * @param list
+ * @param condition
+ */
+ public void filterByForeach(List list, Predicate condition) {
+ list.forEach(a -> {
+ if (condition.test(a)) {
+ System.out.print(a + " ");
+ }
+ });
+ }
+
+ /**
+ * 接收函数参数
+ *
+ * @param list
+ * @param condition
+ */
+ public void filterByFilter(List list, Predicate condition) {
+ list.stream().filter(a -> condition.test(a)).forEach(a -> System.out.print(a + (" ")));
+ }
+
+ /**
+ * predicate 的复杂使用
+ */
+ public void predicateTest() {
+ Predicate startsWith = (str) -> str.startsWith("g");
+ Predicate length = (str) -> str.length() > 4;
+
+ List skills = Arrays.asList("java", "golang", "c++", "c", "python");
+ skills.stream().filter(startsWith.and(length)).forEach((skill) -> {
+ System.out.print(skill + " ");
+ });
+ }
+
+}
+
+class Car {
+ private String name;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public static Car create(final Supplier supplier) {
+ return supplier.get();
+ }
+
+ public static void collide(final Car car) {
+ System.out.println("Collied:" + car.getName());
+ }
+
+ public void follow(final Car another) {
+ System.out.println("Following the:" + another.getName());
+ }
+
+ public void repair() {
+ System.out.println("Repaired:" + this.getName());
+ }
+
+}
+
+@FunctionalInterface
+interface Supplier {
+ /**
+ * 获取元素
+ *
+ * @return
+ */
+ T get();
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-8/src/main/java/com/wdbyte/Jdk8Interface.java b/core-java-modules/core-java-8/src/main/java/com/wdbyte/Jdk8Interface.java
new file mode 100644
index 0000000..790262a
--- /dev/null
+++ b/core-java-modules/core-java-8/src/main/java/com/wdbyte/Jdk8Interface.java
@@ -0,0 +1,82 @@
+package com.wdbyte;
+
+/**
+ *
+ * 接口的静态方法和默认方法
+ *
+ *
+* @Author https://www.wdbyte.com
+ * @Date 2019/2/18 22:52
+ */
+public class Jdk8Interface {
+ public static void main(String[] args) {
+ // 接口静态方法
+ Person.say();
+ // 接口默认方法
+ Person southerner = new Southerner();
+ southerner.eat();
+ // 接口重写方法
+ Northerners northerners = new Northerners();
+ northerners.eat();
+
+ /**
+ * result
+ * 你好啊
+ * 吃米饭
+ * 吃馒头
+ */
+ }
+}
+
+/**
+ * 南方人
+ */
+class Southerner implements Person {
+
+}
+
+/**
+ * 北方人
+ */
+class Northerners implements Person {
+ @Override
+ public void eat() {
+ System.out.println("吃馒头");
+ }
+}
+
+/**
+ * 多个接口有相同的默认方法必须重写方法
+ */
+class PersonImpl implements Person, Person2 {
+
+ @Override
+ public void eat() {
+ System.out.println("吃米饭吃粥");
+ }
+}
+
+interface Person {
+ /**
+ * 接口静态方法
+ */
+ static void say() {
+ System.out.println("你好啊");
+ }
+
+ /**
+ * 接口默认方法
+ */
+ default void eat() {
+ System.out.println("吃米饭");
+ }
+}
+
+/**
+ *
+ */
+interface Person2 {
+ default void eat() {
+ System.out.println("吃粥");
+ }
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-8/src/main/java/com/wdbyte/Jdk8Lambda.java b/core-java-modules/core-java-8/src/main/java/com/wdbyte/Jdk8Lambda.java
new file mode 100644
index 0000000..cbd5029
--- /dev/null
+++ b/core-java-modules/core-java-8/src/main/java/com/wdbyte/Jdk8Lambda.java
@@ -0,0 +1,235 @@
+package com.wdbyte;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ *
+ * Lambda 的语法主要是下面几种。
+ * 1. (params) -> expression
+ * 2. (params) -> statement
+ * 3. (params) -> {statements;}
+ * Lambda 的语法特性。
+ *
+ * 1. 使用 `->` 分割 Lambda 参数和处理语句。
+ * 2. 类型可选,可以不指定参数类型,编译器可以自动判断。
+ * 3. 圆括号可选,如果只有一个参数,可以不需要圆括号,多个参数必须要圆括号。
+ * 4. 花括号可选,一个语句可以不用花括号,多个参数则花括号必须。
+ * 5. 返回值可选,如果只有一个表达式,可以自动返回不需要 return 语句,花括号中需要 return 语法。
+ *
+* @Author https://www.wdbyte.com
+ * @Date 2019/2/17 14:48
+ */
+public class Jdk8Lambda {
+
+ /**
+ * Lambda 的使用,使用 Runnable 例子
+ *
+ * @throws InterruptedException
+ */
+ @Test
+ public void createLambda() throws InterruptedException {
+ // 使用 Lambda 之前
+ Runnable runnable = new Runnable() {
+ @Override
+ public void run() {
+ System.out.println("JDK8 之前的线程创建");
+ }
+ };
+ new Thread(runnable).start();
+
+ // 使用 Lambda 之后
+ Runnable runnable1Jdk8 = () -> System.out.println("JDK8 之后的线程创建");
+ new Thread(runnable1Jdk8).start();
+
+ // 更加紧凑的方式
+ new Thread(() -> System.out.println("JDK8 之后的线程创建")).start();
+ }
+
+ /**
+ * 定义函数接口
+ */
+ @FunctionalInterface
+ public interface FunctionInterfaceDemo {
+ void say(String name, int age);
+ }
+
+ /**
+ * 函数接口,Lambda 测试
+ */
+ @Test
+ public void functionLambdaTest() {
+ FunctionInterfaceDemo demo = (name, age) -> System.out.println("我叫" + name + ",我今年" + age + "岁");
+ demo.say("金庸", 99);
+ }
+
+
+ static class User {
+ private String name;
+ private Integer age;
+
+ public User() {
+ }
+
+ public User(String name, Integer age) {
+ this.name = name;
+ this.age = age;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public Integer getAge() {
+ return age;
+ }
+
+ public void setAge(Integer age) {
+ this.age = age;
+ }
+ }
+
+ public static List userList = new ArrayList();
+
+ static {
+ userList.add(new User("A", 26));
+ userList.add(new User("B", 18));
+ userList.add(new User("C", 23));
+ userList.add(new User("D", 19));
+ }
+
+ /**
+ * 测试方法引用
+ */
+ @Test
+ public void methodRef() {
+ User[] userArr = new User[userList.size()];
+ userList.toArray(userArr);
+ // User::getAge 调用 getAge 方法
+ Arrays.sort(userArr, Comparator.comparing(User::getAge));
+ for (User user : userArr) {
+ System.out.println(user);
+ }
+ }
+
+ /**
+ * 排序输出
+ */
+ @Test
+ public void testSortBeforeJdk8() {
+ // 使用 Lambda 之前
+ userList.sort(new Comparator() {
+ @Override
+ public int compare(User u1, User u2) {
+ return u1.getAge() - u2.getAge();
+ }
+ });
+ for (User user : userList) {
+ System.out.println(user);
+ }
+ System.out.println("------------------------");
+
+ // 使用 Lambda 之后
+ // 方式1
+ userList.sort((User u1, User u2) -> u1.getAge() - u2.getAge());
+ userList.forEach(System.out::println);
+ System.out.println("------------------------");
+ // 方式2
+ userList.sort((u1, u2) -> u1.getAge().compareTo(u2.getAge()));
+ userList.forEach(System.out::println);
+ System.out.println("------------------------");
+ // 方式3
+ userList.sort(Comparator.comparing(User::getAge));
+ userList.forEach(System.out::println);
+ System.out.println("------------------------");
+ // 方式4
+ userList.stream().sorted(Comparator.comparing(User::getAge)).forEach(System.out::println);
+ }
+
+ /**
+ * 新的遍历方式
+ */
+ @Test
+ public void foreachTest() {
+ List skills = Arrays.asList("java", "golang", "c++", "c", "python");
+ // 使用 Lambda 之前
+ for (String skill : skills) {
+ System.out.print(skill + ",");
+ }
+ System.out.println();
+
+ // 使用 Lambda 之后
+ // 方式1,forEach+lambda
+ skills.forEach((skill) -> System.out.print(skill + ","));
+ System.out.println();
+ // 方式2,forEach+方法引用
+ skills.forEach(System.out::print);
+ }
+
+ /**
+ * Lambda 对于流的操作
+ */
+ @Test
+ public void streamTest() {
+ List skills = Arrays.asList("java", "golang", "c++", "c", "python", "java");
+ // Jdk8 之前
+ for (String skill : skills) {
+ System.out.print(skill + ",");
+ }
+ System.out.println();
+
+ // Jdk8 之后-去重遍历
+ skills.stream().distinct().forEach(skill -> System.out.print(skill + ","));
+ System.out.println();
+ // Jdk8 之后-去重遍历
+ skills.stream().distinct().forEach(System.out::print);
+ System.out.println();
+ // Jdk8 之后-去重,过滤掉 ptyhon 再遍历
+ skills.stream().distinct().filter(skill -> skill != "python").forEach(skill -> System.out.print(skill + ","));
+ System.out.println();
+
+ // Jdk8 之后转字符串
+ String skillString = String.join(",", skills);
+ System.out.println(skillString);
+ }
+
+ /**
+ * 数据转换
+ */
+ @Test
+ public void mapTest() {
+ List numList = Arrays.asList(1, 2, 3, 4, 5);
+ // 数据转换
+ numList.stream().map(num -> num * num).forEach(num -> System.out.print(num + ","));
+
+ System.out.println();
+
+ // 数据收集
+ Set numSet = numList.stream().map(num -> num * num).collect(Collectors.toSet());
+ numSet.forEach(num -> System.out.print(num + ","));
+ }
+
+ /**
+ * 数学计算测试
+ */
+ @Test
+ public void mapMathTest() {
+ List list = Arrays.asList(1, 2, 3, 4, 5);
+ IntSummaryStatistics stats = list.stream().mapToInt(x -> x).summaryStatistics();
+ System.out.println("最小值:" + stats.getMin());
+ System.out.println("最大值:" + stats.getMax());
+ System.out.println("个数:" + stats.getCount());
+ System.out.println("和:" + stats.getSum());
+ System.out.println("平均数:" + stats.getAverage());
+
+ // 求和的另一种方式
+ Integer integer = list.stream().reduce((sum, cost) -> sum + cost).get();
+ System.out.println(integer);
+ }
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-8/src/main/java/com/wdbyte/Jdk8LocalDateTime.java b/core-java-modules/core-java-8/src/main/java/com/wdbyte/Jdk8LocalDateTime.java
new file mode 100644
index 0000000..9af6004
--- /dev/null
+++ b/core-java-modules/core-java-8/src/main/java/com/wdbyte/Jdk8LocalDateTime.java
@@ -0,0 +1,191 @@
+package com.wdbyte;
+
+import java.time.*;
+import java.time.format.DateTimeFormatter;
+import java.time.temporal.ChronoUnit;
+import java.time.temporal.TemporalAdjusters;
+import java.util.Date;
+
+import org.junit.jupiter.api.Test;
+
+/**
+ *
+ * JDK 8 date / time api
+ *
+ * 优点:
+ *
+ * - 都是final 不可变类, 适用于多线程
+ * - 用法清晰,如都适用的now(),of(),parse(),format()方法
+ * - 实现了大部分常用操作方法
+ *
+ *
+* @Author https://www.wdbyte.com
+ * @Date 2019/2/19 17:48
+ */
+public class Jdk8LocalDateTime {
+
+ /**
+ * 时间获取
+ *
+ *
+ */
+ @Test
+ public void nowTimeTest() {
+ // 当前精确时间
+ LocalDateTime now = LocalDateTime.now();
+ System.out.println("当前精确时间:" + now);
+ System.out.println("当前精确时间:" + now.getYear() + "-" + now.getMonthValue() + "-" + now.getDayOfMonth() + " "
+ + now.getHour() + "-" + now.getMinute() + "-" + now.getSecond());
+
+ // 获取当前日期
+ LocalDate localDate = LocalDate.now();
+ System.out.println("当前日期:" + localDate);
+ System.out
+ .println("当前日期:" + localDate.getYear() + "-" + localDate.getMonthValue() + "-" + localDate.getDayOfMonth());
+
+ // 获取当天时间
+ LocalTime localTime = LocalTime.now();
+ System.out.println("当天时间:" + localTime);
+ System.out.println("当天时间:" + localTime.getHour() + ":" + localTime.getMinute() + ":" + localTime.getSecond());
+
+ // 有时区的当前精确时间
+ ZonedDateTime nowZone = LocalDateTime.now().atZone(ZoneId.systemDefault());
+ System.out.println("当前精确时间(有时区):" + nowZone);
+ System.out
+ .println("当前精确时间(有时区):" + nowZone.getYear() + "-" + nowZone.getMonthValue() + "-" + nowZone.getDayOfMonth()
+ + " " + nowZone.getHour() + "-" + nowZone.getMinute() + "-" + nowZone.getSecond());
+ }
+
+ /**
+ * 时间创建
+ */
+ @Test
+ public void createTime() {
+ LocalDateTime ofTime = LocalDateTime.of(2019, 10, 1, 8, 8, 8);
+ System.out.println("当前精确时间:" + ofTime);
+
+ LocalDate localDate = LocalDate.of(2019, 10, 01);
+ System.out.println("当前日期:" + localDate);
+
+ LocalTime localTime = LocalTime.of(12, 01, 01);
+ System.out.println("当天时间:" + localTime);
+
+ }
+
+ /**
+ * 日期转换
+ */
+ @Test
+ public void convertTimeTest() {
+ LocalDateTime parseTime = LocalDateTime.parse("2019-10-01T22:22:22.222");
+ System.out.println("字符串时间转换:" + parseTime);
+
+ LocalDate formatted = LocalDate.parse("20190101", DateTimeFormatter.BASIC_ISO_DATE);
+ System.out.println("字符串时间转换-指定格式:" + formatted);
+
+ // Date 转换成 LocalDateTime
+ Date date = new Date();
+ ZoneId zoneId = ZoneId.systemDefault();
+ System.out.println("Date 转换成 LocalDateTime:" + LocalDateTime.ofInstant(date.toInstant(), zoneId));
+
+ // LocalDateTime 转换成 Date
+ LocalDateTime localDateTime = LocalDateTime.now();
+ Date toDate = Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
+ System.out.println("LocalDateTime 转换成 Date:" + toDate);
+
+ // 当前时间转时间戳
+ long epochMilli = LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli();
+ System.out.println("当前时间转时间戳:" + epochMilli);
+ // 时间戳转换成时间
+ LocalDateTime epochMilliTime =
+ LocalDateTime.ofInstant(Instant.ofEpochMilli(epochMilli), ZoneId.systemDefault());
+ System.out.println("时间戳转换成时间:" + epochMilliTime);
+ }
+
+ /**
+ * 日期格式化
+ */
+ @Test
+ public void formatTest() {
+ LocalDateTime now = LocalDateTime.now();
+ System.out.println("当前时间:" + now);
+ System.out.println("格式化后:" + now.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
+ System.out.println("格式化后:" + now.format(DateTimeFormatter.ISO_LOCAL_DATE));
+ System.out.println("格式化后:" + now.format(DateTimeFormatter.ISO_LOCAL_TIME));
+ System.out.println("格式化后:" + now.format(DateTimeFormatter.ofPattern("YYYY-MM-dd hh:mm:ss")));
+ }
+
+ /**
+ * 时间比较
+ */
+ @Test
+ public void diffTest() {
+ LocalDateTime now = LocalDateTime.now();
+ LocalDateTime yestory = now.minusDays(1);
+ System.out.println(now + "在" + yestory + "之后吗?" + now.isAfter(yestory));
+ System.out.println(now + "在" + yestory + "之前吗?" + now.isBefore(yestory));
+
+ // 时间差
+ long day = yestory.until(now, ChronoUnit.DAYS);
+ long month = yestory.until(now, ChronoUnit.MONTHS);
+ long hours = yestory.until(now, ChronoUnit.HOURS);
+ long minutes = yestory.until(now, ChronoUnit.MINUTES);
+ System.out.println("相差月份" + month);
+ System.out.println("相差天数" + day);
+ System.out.println("相差小时" + hours);
+ System.out.println("相差分钟" + minutes);
+
+ // 距离JDK 14 发布还有多少天?
+ LocalDate jdk14 = LocalDate.of(2020, 3, 17);
+ LocalDate nowDate = LocalDate.now();
+ System.out.println("距离JDK 14 发布还有:" + nowDate.until(jdk14, ChronoUnit.DAYS) + "天");
+ }
+
+ /**
+ * 日期加减
+ */
+ @Test
+ public void calcTest() {
+ LocalDateTime now = LocalDateTime.now();
+ System.out.println("当前时间:" + now);
+ LocalDateTime plusTime = now.plusMonths(1).plusDays(1).plusHours(1).plusMinutes(1).plusSeconds(1);
+ System.out.println("增加1月1天1小时1分钟1秒时间后:" + plusTime);
+ LocalDateTime minusTime = now.minusMonths(2);
+ System.out.println("减少2个月时间后:" + minusTime);
+ }
+
+ /**
+ * 时间方法
+ */
+ @Test
+ public void timeFunctionTest() {
+ LocalDateTime now = LocalDateTime.now();
+ System.out.println("当前时间:" + now);
+
+ // LocalDateTime 本月第一天
+ // 方法1
+ LocalDateTime firstDay = now.withDayOfMonth(1);
+ System.out.println("本月第一天:" + firstDay);
+ // 方法2
+ firstDay = now.with(TemporalAdjusters.firstDayOfMonth());
+ System.out.println("本月第一天:" + firstDay);
+
+ // LocalDateTime 本月最后一天
+ LocalDateTime lastDay = now.with(TemporalAdjusters.lastDayOfMonth());
+ System.out.println("本月最后一天:" + lastDay);
+
+
+ // LocalDateTime 当天最后一秒
+ // 方法1
+ LocalDateTime lastSecondOfDay1 = now.withHour(23).withMinute(59).withSecond(59);
+ System.out.println("当天最后一秒:" + lastSecondOfDay1);
+ // 方法2
+ LocalDateTime lastSecondOfDay2 = LocalDateTime.now().with(LocalTime.MAX);
+ System.out.println("当天最后一秒:" + lastSecondOfDay2);
+
+
+ // 是否闰年
+ System.out.println("今年是否闰年:" + Year.isLeap(now.getYear()));
+ }
+
+}
diff --git a/core-java-modules/core-java-8/src/main/java/com/wdbyte/Jdk8NashornJs.java b/core-java-modules/core-java-8/src/main/java/com/wdbyte/Jdk8NashornJs.java
new file mode 100644
index 0000000..ac34fd1
--- /dev/null
+++ b/core-java-modules/core-java-8/src/main/java/com/wdbyte/Jdk8NashornJs.java
@@ -0,0 +1,36 @@
+package com.wdbyte;
+
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineManager;
+import javax.script.ScriptException;
+
+import org.junit.jupiter.api.Test;
+
+/**
+ *
+ *
+ * Java 8提供了新的Nashorn JavaScript引擎,使得我们可以在JVM上开发和运行JS应用。
+ *
+ * Nashorn JavaScript引擎是javax.script.ScriptEngine的另一个实现版本,
+ *
+ * 这类Script引擎遵循相同的规则,允许Java和JavaScript交互使用,例子代码如下:
+ *
+* @Author https://www.wdbyte.com
+ * @Date 2019/6/12 9:41
+ */
+public class Jdk8NashornJs {
+
+ @Test
+ public void nashornJsTest() throws ScriptException {
+ ScriptEngineManager scriptEngineManager = new ScriptEngineManager();
+ ScriptEngine jsEngine = scriptEngineManager.getEngineByName("JavaScript");
+ System.out.println(jsEngine.getClass().getName());
+ String string = (String)jsEngine.eval("var str=\"hello\";str+\" java\"");
+ System.out.println(string);
+
+ // result
+ // jdk.nashorn.api.scripting.NashornScriptEngine
+ // hello java
+ }
+
+}
diff --git a/core-java-modules/core-java-8/src/main/java/com/wdbyte/Jdk8Optional.java b/core-java-modules/core-java-8/src/main/java/com/wdbyte/Jdk8Optional.java
new file mode 100644
index 0000000..fc080a8
--- /dev/null
+++ b/core-java-modules/core-java-8/src/main/java/com/wdbyte/Jdk8Optional.java
@@ -0,0 +1,223 @@
+package com.wdbyte;
+
+import java.util.Optional;
+
+import org.junit.jupiter.api.Test;
+
+/**
+ *
+ * JDK8 为解决空指针增加的 Optional 方法
+ *
+* @Author https://www.wdbyte.com
+ * @Date 2019/2/19 11:40
+ */
+public class Jdk8Optional {
+
+ /**
+ * 创建一个 Optional
+ */
+ @Test
+ public void createOptionalTest() {
+ // Optional 构造方式1 - of 传入的值不能为 null
+ Optional helloOption = Optional.of("hello");
+
+ // Optional 构造方式2 - empty 一个空 optional
+ Optional emptyOptional = Optional.empty();
+
+ // Optional 构造方式3 - ofNullable 支持传入 null 值的 optional
+ Optional nullOptional = Optional.ofNullable(null);
+ }
+
+ /**
+ * 检查是否有值
+ */
+ @Test
+ public void checkOptionalTest() {
+ Optional helloOptional = Optional.of("Hello");
+ System.out.println(helloOptional.isPresent());
+
+ Optional emptyOptional = Optional.empty();
+ System.out.println(emptyOptional.isPresent());
+
+ // 如果有值,则获取想要的信息
+ helloOptional.ifPresent(s -> System.out.println(s.length()));
+ emptyOptional.ifPresent(s -> System.out.println(s.length()));
+ }
+
+ /**
+ * 如果有值,输出长度
+ */
+ @Test
+ public void whenIsPresentTest() {
+ Optional helloOptional = Optional.of("Hello");
+ Optional emptyOptional = Optional.empty();
+ // 如果有值,则获取想要的信息
+ helloOptional.ifPresent(s -> System.out.println(s.length()));
+ emptyOptional.ifPresent(s -> System.out.println(s.length()));
+ }
+
+ /**
+ * 如果没有值,获取默认值
+ */
+ @Test
+ public void whenIsNullGetTest() {
+ // 如果没有值,获取默认值
+ Optional emptyOptional = Optional.empty();
+ String orElse = emptyOptional.orElse("orElse default");
+ String orElseGet = emptyOptional.orElseGet(() -> "orElseGet default");
+ System.out.println(orElse);
+ System.out.println(orElseGet);
+ }
+
+ /**
+ * 如果没有值,会抛异常
+ */
+ @Test
+ public void getTest() {
+ Optional stringOptional = Optional.of("hello");
+ System.out.println(stringOptional.get());
+ // 如果没有值,会抛异常
+ Optional emptyOptional = Optional.empty();
+ System.out.println(emptyOptional.get());
+ }
+
+ /**
+ * orElse 和 orElseGet 的区别
+ */
+ @Test
+ public void orElseAndOrElseGetTest() {
+ // 如果没有值,默认值
+ Optional emptyOptional = Optional.empty();
+ System.out.println("空Optional.orElse");
+ String orElse = emptyOptional.orElse(getDefault());
+ System.out.println("空Optional.orElseGet");
+ String orElseGet = emptyOptional.orElseGet(() -> getDefault());
+ System.out.println("空Optional.orElse结果:" + orElse);
+ System.out.println("空Optional.orElseGet结果:" + orElseGet);
+ System.out.println("--------------------------------");
+ // 如果没有值,默认值
+ Optional stringOptional = Optional.of("hello");
+ System.out.println("有值Optional.orElse");
+ orElse = stringOptional.orElse(getDefault());
+ System.out.println("有值Optional.orElseGet");
+ orElseGet = stringOptional.orElseGet(() -> getDefault());
+ System.out.println("有值Optional.orElse结果:" + orElse);
+ System.out.println("有值Optional.orElseGet结果:" + orElseGet);
+ }
+
+ public String getDefault() {
+ System.out.println(" 获取默认值中..run getDeafult method");
+ return "hello";
+ }
+
+ /**
+ * 如果没有值,抛出异常
+ */
+ @Test
+ public void whenIsNullThrowExceTest() throws Exception {
+ // 如果没有值,抛出异常
+ Optional emptyOptional = Optional.empty();
+ String value = emptyOptional.orElseThrow(() -> new Exception("发现空值"));
+ System.out.println(value);
+ }
+
+ @Test
+ public void functionTest() {
+ // filter 过滤
+ Optional optional123 = Optional.of(123);
+ optional123.filter(num -> num == 123).ifPresent(num -> System.out.println(num));
+
+ Optional optional456 = Optional.of(456);
+ optional456.filter(num -> num == 123).ifPresent(num -> System.out.println(num));
+
+ // map 转换
+ Optional optional789 = Optional.of(789);
+ optional789.map(String::valueOf).map(String::length).ifPresent(length -> System.out.println(length));
+ }
+
+ /**
+ * 电脑里【有可能】有声卡
+ * 声卡【有可能】有USB接口
+ */
+ @Test
+ public void optionalTest() {
+ // 没有声卡,没有 Usb 的电脑
+ Computer computerNoUsb = new Computer();
+ computerNoUsb.setSoundCard(Optional.empty());
+ // 获取 usb 版本
+ Optional computerOptional = Optional.ofNullable(computerNoUsb);
+ String version = computerOptional.flatMap(Computer::getSoundCard).flatMap(SoundCard::getUsb)
+ .map(Usb::getVersion).orElse("UNKNOWN");
+ System.out.println(version);
+ System.out.println("-----------------");
+
+ // 如果有值,则输出
+ SoundCard soundCard = new SoundCard();
+ Usb usb = new Usb();
+ usb.setVersion("2.0");
+ soundCard.setUsb(Optional.ofNullable(usb));
+ Optional optionalSoundCard = Optional.ofNullable(soundCard);
+ optionalSoundCard.ifPresent(System.out::println);
+ // 如果有值,则输出
+ if (optionalSoundCard.isPresent()) {
+ System.out.println(optionalSoundCard.get());
+ }
+
+ // 输出没有值,则没有输出
+ Optional optionalSoundCardEmpty = Optional.ofNullable(null);
+ optionalSoundCardEmpty.ifPresent(System.out::println);
+ System.out.println("-----------------");
+
+ // 筛选 Usb2.0
+ optionalSoundCard.map(SoundCard::getUsb)
+ .filter(usb1 -> "3.0".equals(usb1.map(Usb::getVersion)
+ .orElse("UBKNOW")))
+ .ifPresent(System.out::println);
+ }
+
+}
+
+/**
+ * 计算机
+ */
+class Computer {
+ private Optional soundCard;
+
+ public Optional getSoundCard() {
+ return soundCard;
+ }
+
+ public void setSoundCard(Optional soundCard) {
+ this.soundCard = soundCard;
+ }
+}
+
+/**
+ * 声卡
+ */
+class SoundCard {
+ private Optional usb;
+
+ public Optional getUsb() {
+ return usb;
+ }
+
+ public void setUsb(Optional usb) {
+ this.usb = usb;
+ }
+}
+
+/**
+ * USB
+ */
+class Usb {
+ private String version;
+
+ public String getVersion() {
+ return version;
+ }
+
+ public void setVersion(String version) {
+ this.version = version;
+ }
+}
diff --git a/core-java-modules/core-java-8/src/main/java/com/wdbyte/Jdk8Stream.java b/core-java-modules/core-java-8/src/main/java/com/wdbyte/Jdk8Stream.java
new file mode 100644
index 0000000..d78cdb2
--- /dev/null
+++ b/core-java-modules/core-java-8/src/main/java/com/wdbyte/Jdk8Stream.java
@@ -0,0 +1,373 @@
+package com.wdbyte;
+
+import org.junit.jupiter.api.Test;
+import java.io.BufferedReader;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.util.*;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+import java.util.stream.Stream;
+
+/**
+ *
+ * JDK 8 steam 流操作
+ *
+* @Author https://www.wdbyte.com
+ * @Date 2019/8/12 18:03
+ */
+public class Jdk8Stream {
+
+ /**
+ * 创建流的几种方式
+ * 集合
+ * Collection.stream();
+ * Collection.parallelStream()
+ * 数组
+ * Arrays.stream(T array) or Stream.of()
+ * 文件流
+ * java.io.BufferedReader.lines()
+ * 静态方法
+ * IntStream.range,IntStream.of
+ */
+ @Test
+ public void createStream() throws FileNotFoundException {
+ List nameList = Arrays.asList("Darcy", "Chris", "Linda", "Sid", "Kim", "Jack", "Poul", "Peter");
+ String[] nameArr = {"Darcy", "Chris", "Linda", "Sid", "Kim", "Jack", "Poul", "Peter"};
+ // 集合获取 Stream 流
+ Stream nameListStream = nameList.stream();
+ // 集合获取并行 Stream 流
+ Stream nameListStream2 = nameList.parallelStream();
+ // 数组获取 Stream 流
+ Stream nameArrStream = Stream.of(nameArr);
+ // 数组获取 Stream 流
+ Stream nameArrStream1 = Arrays.stream(nameArr);
+
+ // 文件流获取 Stream 流
+ BufferedReader bufferedReader = new BufferedReader(new FileReader("README.md"));
+ Stream linesStream = bufferedReader.lines();
+
+ // 从静态方法获取流操作
+ IntStream rangeStream = IntStream.range(1, 10);
+ rangeStream.limit(10).forEach(num -> System.out.print(num+","));
+ System.out.println();
+ IntStream intStream = IntStream.of(1, 2, 3, 3, 4);
+ intStream.forEach(num -> System.out.print(num+","));
+ }
+
+ @Test
+ public void streamDemo(){
+ List nameList = Arrays.asList("Darcy", "Chris", "Linda", "Sid", "Kim", "Jack", "Poul", "Peter");
+ // 1. 筛选出名字长度为4的
+ // 2. 名字前面拼接 This is
+ // 3. 遍历输出
+ nameList.stream()
+ .filter(name -> name.length() == 4)
+ .map(name -> "This is "+name)
+ .forEach(name -> System.out.println(name));
+ }
+
+ /**
+ * 转换成为大写然后收集结果,遍历输出
+ */
+ @Test
+ public void toUpperCaseDemo() {
+ List nameList = Arrays.asList("Darcy", "Chris", "Linda", "Sid", "Kim", "Jack", "Poul", "Peter");
+ List upperCaseNameList = nameList.stream()
+ .map(String::toUpperCase)
+ .collect(Collectors.toList());
+ upperCaseNameList.forEach(name -> System.out.print(name + ","));
+ }
+
+ /**
+ * 把数字值乘以2
+ */
+ @Test
+ public void mapTest() {
+ List numberList = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
+ // 映射成 2倍数字
+ List collect = numberList.stream()
+ .map(number -> number * 2)
+ .collect(Collectors.toList());
+ collect.forEach(number -> System.out.print(number + ","));
+ System.out.println();
+
+ numberList.stream()
+ .map(number -> "数字 " + number + ",")
+ .forEach(number -> System.out.print(number));
+ }
+
+
+
+ /**
+ * flatmap把对象扁平化
+ */
+ @Test
+ public void flatMapTest() {
+ Stream> inputStream = Stream.of(
+ Arrays.asList(1),
+ Arrays.asList(2, 3),
+ Arrays.asList(4, 5, 6)
+ );
+ List collect = inputStream
+ .flatMap((childList) -> childList.stream())
+ .collect(Collectors.toList());
+ collect.forEach(number -> System.out.print(number + ","));
+ }
+
+ /**
+ * 遍历输出
+ */
+ @Test
+ public void forEachTest(){
+ List numberList = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
+ numberList.stream().forEach(number -> System.out.print(number+","));
+ }
+
+ /**
+ * filter 数据筛选
+ * 筛选出偶数数字
+ */
+ @Test
+ public void filterTest() {
+ List numberList = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
+ List collect = numberList.stream()
+ .filter(number -> number % 2 == 0)
+ .collect(Collectors.toList());
+ collect.forEach(number -> System.out.print(number + ","));
+ }
+
+ /**
+ * 查找第一个数据
+ * 返回的是一个 Optional 对象
+ */
+ @Test
+ public void findFirstTest(){
+ List numberList = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
+ Optional firstNumber = numberList.stream()
+ .findFirst();
+ System.out.println(firstNumber.orElse(-1));
+ }
+
+ /**
+ * Stream 转换为其他数据结构
+ */
+ @Test
+ public void collectTest() {
+ List numberList = Arrays.asList(1, 1, 2, 2, 3, 3, 4, 4, 5);
+ // to array
+ Integer[] toArray = numberList.stream()
+ .toArray(Integer[]::new);
+ // to List
+ List integerList = numberList.stream()
+ .collect(Collectors.toList());
+ // to set
+ Set integerSet = numberList.stream()
+ .collect(Collectors.toSet());
+ System.out.println(integerSet);
+ // to string
+ String toString = numberList.stream()
+ .map(number -> String.valueOf(number))
+ .collect(Collectors.joining()).toString();
+ System.out.println(toString);
+ // to string split by ,
+ String toStringbJoin = numberList.stream()
+ .map(number -> String.valueOf(number))
+ .collect(Collectors.joining(",")).toString();
+ System.out.println(toStringbJoin);
+ }
+
+ /**
+ * 使用流操作和不使用流操作的编码风格对比
+ */
+ @Test
+ public void diffTest() {
+ // 不使用流操作
+ List names = Arrays.asList("Jack", "Jill", "Nate", "Kara", "Kim", "Jullie", "Paul", "Peter");
+ // 筛选出长度为4的名字
+ List subList = new ArrayList<>();
+ for (String name : names) {
+ if (name.length() == 4) {
+ subList.add(name);
+ }
+ }
+ // 把值用逗号分隔
+ StringBuilder sbNames = new StringBuilder();
+ for (int i = 0; i < subList.size() - 1; i++) {
+ sbNames.append(subList.get(i));
+ sbNames.append(", ");
+ }
+ // 去掉最后一个逗号
+ if (subList.size() > 1) {
+ sbNames.append(subList.get(subList.size() - 1));
+ }
+ System.out.println(sbNames);
+ System.out.println("----------------");
+
+ // 使用 Stream 流操作
+ String nameString = names.stream()
+ .filter(num -> num.length() == 4)
+ .collect(Collectors.joining(", "));
+ System.out.println(nameString);
+
+ // String string = names.stream().filter(num -> num.length() == 4).map(name -> name.toUpperCase()).collect(Collectors.joining(","));
+ String string = names.stream()
+ .filter(num -> num.length() == 4)
+ .map(name -> name.toUpperCase())
+ .collect(Collectors.joining(","));
+ }
+
+ /**
+ * reduce 字符串拼接例子
+ */
+ @Test
+ public void reduceTest() {
+ List skills = Arrays.asList("java", "golang", "c++", "c", "python");
+ String s = skills.stream().reduce((all, skill) -> all + skill).get();
+ System.out.println(s);
+ }
+
+ /**
+ * 数据去重例子
+ */
+ @Test
+ public void distinctTest() {
+ List skills = Arrays.asList("java", "golang", "c++", "c", "python", "java");
+ List collects = skills.stream().distinct().collect(Collectors.toList());
+ collects.forEach(skill -> System.out.println(skill));
+ System.out.println("---------------------------------------------");
+ skills = Arrays.asList("java", "golang", "c++", "c", "python", "java");
+ skills.stream().distinct().forEach(s -> System.out.println(s));
+ }
+
+ /**
+ * 数学计算测试
+ */
+ @Test
+ public void mathTest() {
+ List list = Arrays.asList(1, 2, 3, 4, 5, 6);
+ IntSummaryStatistics stats = list.stream().mapToInt(x -> x).summaryStatistics();
+ System.out.println("最小值:" + stats.getMin());
+ System.out.println("最大值:" + stats.getMax());
+ System.out.println("个数:" + stats.getCount());
+ System.out.println("和:" + stats.getSum());
+ System.out.println("平均数:" + stats.getAverage());
+ }
+
+ /**
+ * 按年龄分组
+ */
+ @Test
+ public void groupByTest() {
+ List ageList = Arrays.asList(11, 22, 13, 14, 25, 26);
+ Map> ageGrouyByMap = ageList.stream()
+ .collect(Collectors.groupingBy(age -> String.valueOf(age / 10)));
+
+ ageGrouyByMap.forEach((k, v) -> {
+ System.out.println("年龄" + k + "0多岁的有:" + v);
+ });
+ }
+
+ /**
+ * 按某个条件分组
+ * 给一组年龄,分出成年人和未成年人
+ */
+ @Test
+ public void partitioningByTest() {
+ List ageList = Arrays.asList(11, 22, 13, 14, 25, 26);
+ Map> ageMap = ageList.stream()
+ .collect(Collectors.partitioningBy(age -> age > 18));
+ System.out.println("未成年人:" + ageMap.get(false));
+ System.out.println("成年人:" + ageMap.get(true));
+ }
+
+ /**
+ * 生成自己的 Stream 流
+ */
+ @Test
+ public void generateTest(){
+ // 生成自己的随机数流
+ Random random = new Random();
+ Stream generateRandom = Stream.generate(random::nextInt);
+ generateRandom.limit(5).forEach(System.out::println);
+
+ // 生成自己的 UUID 流
+ Stream generate = Stream.generate(UUID::randomUUID);
+ generate.limit(5).forEach(System.out::println);
+ }
+
+
+ /**
+ * 获取 / 扔掉前 n 个元素
+ */
+ @Test
+ public void limitOrSkipTest() {
+ // 生成自己的随机数流
+ List ageList = Arrays.asList(11, 22, 13, 14, 25, 26);
+ ageList.stream()
+ .limit(3)
+ .forEach(age -> System.out.print(age+","));
+ System.out.println();
+
+ ageList.stream()
+ .skip(3)
+ .forEach(age -> System.out.print(age+","));
+ }
+
+ /**
+ * 找出偶数
+ */
+ @Test
+ public void lazyTest() {
+ // 生成自己的随机数流
+ List numberLIst = Arrays.asList(1, 2, 3, 4, 5, 6);
+ // 找出第一个偶数
+ Stream integerStream = numberLIst.stream()
+ .filter(number -> {
+ int temp = number % 2;
+ if (temp == 0 ){
+ System.out.println(number);
+ }
+ return temp == 0;
+ });
+
+ System.out.println("分割线");
+ List collect = integerStream.collect(Collectors.toList());
+ }
+
+
+ /**
+ * 并行计算
+ */
+ @Test
+ public void main() {
+ // 生成自己的随机数流,取一千万个随机数
+ Random random = new Random();
+ Stream generateRandom = Stream.generate(random::nextInt);
+ List numberList = generateRandom.limit(10000000).collect(Collectors.toList());
+
+ // 串行 - 把一千万个随机数,每个随机数 * 2 ,然后求和
+ long start = System.currentTimeMillis();
+ int sum = numberList.stream().map(number -> number * 2).mapToInt(x -> x).sum();
+ long end = System.currentTimeMillis();
+ System.out.println("串行耗时:"+(end - start)+"ms,和是:"+sum);
+
+ // 并行 - 把一千万个随机数,每个随机数 * 2 ,然后求和
+ start = System.currentTimeMillis();
+ sum = numberList.parallelStream().map(number -> number * 2).mapToInt(x -> x).sum();
+ end = System.currentTimeMillis();
+ System.out.println("并行耗时:"+(end - start)+"ms,和是:"+sum);
+
+ }
+
+ @Test
+ public void simpleTest(){
+ List numbers = Arrays.asList(1, 2, 3);
+ int[] factor = new int[] { 2 };
+ Stream stream = numbers.stream()
+ .map(e -> e * factor[0]);
+ factor[0] = 0;
+ stream.forEach(System.out::println);
+ }
+
+}
diff --git a/core-java-modules/core-java-8/src/main/java/com/wdbyte/Jdk8StreamPro.java b/core-java-modules/core-java-8/src/main/java/com/wdbyte/Jdk8StreamPro.java
new file mode 100644
index 0000000..18c400e
--- /dev/null
+++ b/core-java-modules/core-java-8/src/main/java/com/wdbyte/Jdk8StreamPro.java
@@ -0,0 +1,96 @@
+package com.wdbyte;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
+import org.junit.jupiter.api.Test;
+
+/**
+ * @author darcy
+ * @date 2020/12/04
+ */
+public class Jdk8StreamPro {
+
+ /**
+ * 计算前 N 个自然数的和
+ *
+ * @param adder
+ * @param n
+ * @return
+ */
+ public static long measureSumPerf(Function adder, long n) {
+ long fastest = Long.MAX_VALUE;
+ for (int i = 0; i < 10; i++) {
+ long start = System.nanoTime();
+ long sum = adder.apply(n);
+ long duration = (System.nanoTime() - start) / 1_000_000;
+ if (duration < fastest) { fastest = duration; }
+ }
+ return fastest;
+ }
+
+ public static long sequentialSum(long n) {
+ return Stream.iterate(1L, i -> i + 1)
+ .limit(n)
+ .reduce(0L, Long::sum);
+ }
+
+ public static void main(String[] args) {
+
+ }
+
+ public static List filter(List list, Predicate p) {
+ List results = new ArrayList<>();
+ for (T s : list) {
+ if (p.test(s)) {
+ results.add(s);
+ }
+ }
+ return results;
+ }
+
+ static List list = new ArrayList<>();
+
+ static {
+ list.add("Hello");
+ list.add("Java");
+ list.add("Python");
+ }
+
+ @Test
+ public void testPredicate() {
+ System.out.println(list);
+ System.out.println(filter(list, s -> s.length() > 4));
+ System.out.println(filter(list, String::isEmpty));
+ System.out.println(filter(list, s -> s.startsWith("J")));
+ }
+
+ public static void consumer(List