diff --git a/core-java-modules/core-java-8-2/.gitignore b/core-java-modules/core-java-8-2/.gitignore
new file mode 100644
index 0000000000..374c8bf907
--- /dev/null
+++ b/core-java-modules/core-java-8-2/.gitignore
@@ -0,0 +1,25 @@
+*.class
+
+0.*
+
+#folders#
+/target
+/neoDb*
+/data
+/src/main/webapp/WEB-INF/classes
+*/META-INF/*
+.resourceCache
+
+# Packaged files #
+*.jar
+*.war
+*.ear
+
+# Files generated by integration tests
+backup-pom.xml
+/bin/
+/temp
+
+#IntelliJ specific
+.idea/
+*.iml
\ No newline at end of file
diff --git a/core-java-modules/core-java-8-2/README.md b/core-java-modules/core-java-8-2/README.md
new file mode 100644
index 0000000000..9b6a0f1716
--- /dev/null
+++ b/core-java-modules/core-java-8-2/README.md
@@ -0,0 +1,13 @@
+## Java 8 核心(第 2 部分)
+
+本模块中包含有关 Java 8 核心新增功能特性的一些文章。
+
+### 相关文章
+
+- [Run a Java Application from the Command Line](https://www.baeldung.com/java-run-jar-with-arguments)
+- [Java 8 Stream skip() vs limit()](https://www.baeldung.com/java-stream-skip-vs-limit)
+- [Guide to Java BiFunction Interface](https://www.baeldung.com/java-bifunction-interface)
+- [Interface With Default Methods vs Abstract Class](https://www.baeldung.com/java-interface-default-method-vs-abstract-class)
+- [Convert Between Byte Array and UUID in Java](https://www.baeldung.com/java-byte-array-to-uuid)
+- [Create a Simple “Rock-Paper-Scissors” Game in Java](https://www.baeldung.com/java-rock-paper-scissors)
+- [[<-- Java 8 核心(第 1 部分)]](/core-java-modules/core-java-8)
diff --git a/core-java-modules/core-java-8-2/pom.xml b/core-java-modules/core-java-8-2/pom.xml
new file mode 100644
index 0000000000..6b3338804e
--- /dev/null
+++ b/core-java-modules/core-java-8-2/pom.xml
@@ -0,0 +1,29 @@
+
+
+ 4.0.0
+ core-java-8-2
+ 0.1.0-SNAPSHOT
+ core-java-8-2
+ jar
+
+
+ com.ossez.core-java-modules
+ core-java-modules
+ 0.0.2-SNAPSHOT
+
+
+
+
+ com.ibm.icu
+ icu4j
+ ${icu.version}
+
+
+
+
+ 64.2
+
+
+
\ No newline at end of file
diff --git a/core-java-modules/core-java-8-2/src/main/java/com/ossez/game/RockPaperScissorsGame.java b/core-java-modules/core-java-8-2/src/main/java/com/ossez/game/RockPaperScissorsGame.java
new file mode 100644
index 0000000000..688497e6e4
--- /dev/null
+++ b/core-java-modules/core-java-8-2/src/main/java/com/ossez/game/RockPaperScissorsGame.java
@@ -0,0 +1,73 @@
+package com.ossez.game;
+
+import java.util.*;
+
+class RockPaperScissorsGame {
+
+ enum Move {
+ ROCK("rock"),
+ PAPER("paper"),
+ SCISSORS("scissors");
+
+ private String value;
+
+ Move(String value) {
+ this.value = value;
+ }
+
+ public String getValue() {
+ return value;
+ }
+ }
+
+ public static void main(String[] args) {
+ Scanner scanner = new Scanner(System.in);
+ int wins = 0;
+ int losses = 0;
+
+ System.out.println("Welcome to Rock-Paper-Scissors! Please enter \"rock\", \"paper\", \"scissors\", or \"quit\" to exit.");
+
+ while (true) {
+ System.out.println("-------------------------");
+ System.out.print("Enter your move: ");
+ String playerMove = scanner.nextLine();
+
+ if (playerMove.equals("quit")) {
+ System.out.println("You won " + wins + " times and lost " + losses + " times.");
+ System.out.println("Thanks for playing! See you again.");
+ break;
+ }
+
+ if (Arrays.stream(Move.values()).noneMatch(x -> x.getValue().equals(playerMove))) {
+ System.out.println("Your move isn't valid!");
+ continue;
+ }
+
+ String computerMove = getComputerMove();
+
+ if (playerMove.equals(computerMove)) {
+ System.out.println("It's a tie!");
+ } else if (isPlayerWin(playerMove, computerMove)) {
+ System.out.println("You won!");
+ wins++;
+ } else {
+ System.out.println("You lost!");
+ losses++;
+ }
+ }
+ }
+
+ private static boolean isPlayerWin(String playerMove, String computerMove) {
+ return playerMove.equals(Move.ROCK.value) && computerMove.equals(Move.SCISSORS.value)
+ || (playerMove.equals(Move.SCISSORS.value) && computerMove.equals(Move.PAPER.value))
+ || (playerMove.equals(Move.PAPER.value) && computerMove.equals(Move.ROCK.value));
+ }
+
+ private static String getComputerMove() {
+ Random random = new Random();
+ int randomNumber = random.nextInt(3);
+ String computerMove = Move.values()[randomNumber].getValue();
+ System.out.println("Computer move: " + computerMove);
+ return computerMove;
+ }
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-8-2/src/main/java/com/ossez/interfaceVsAbstractClass/ChidlCircleInterfaceImpl.java b/core-java-modules/core-java-8-2/src/main/java/com/ossez/interfaceVsAbstractClass/ChidlCircleInterfaceImpl.java
new file mode 100644
index 0000000000..c403c7e800
--- /dev/null
+++ b/core-java-modules/core-java-8-2/src/main/java/com/ossez/interfaceVsAbstractClass/ChidlCircleInterfaceImpl.java
@@ -0,0 +1,14 @@
+package com.ossez.interfaceVsAbstractClass;
+
+public class ChidlCircleInterfaceImpl implements CircleInterface {
+ private String color;
+
+ @Override
+ public String getColor() {
+ return color;
+ }
+
+ public void setColor(String color) {
+ this.color = color;
+ }
+}
diff --git a/core-java-modules/core-java-8-2/src/main/java/com/ossez/interfaceVsAbstractClass/ChildCircleClass.java b/core-java-modules/core-java-8-2/src/main/java/com/ossez/interfaceVsAbstractClass/ChildCircleClass.java
new file mode 100644
index 0000000000..5de63ecd03
--- /dev/null
+++ b/core-java-modules/core-java-8-2/src/main/java/com/ossez/interfaceVsAbstractClass/ChildCircleClass.java
@@ -0,0 +1,5 @@
+package com.ossez.interfaceVsAbstractClass;
+
+public class ChildCircleClass extends CircleClass {
+
+}
diff --git a/core-java-modules/core-java-8-2/src/main/java/com/ossez/interfaceVsAbstractClass/CircleClass.java b/core-java-modules/core-java-8-2/src/main/java/com/ossez/interfaceVsAbstractClass/CircleClass.java
new file mode 100644
index 0000000000..da7a3c4ad2
--- /dev/null
+++ b/core-java-modules/core-java-8-2/src/main/java/com/ossez/interfaceVsAbstractClass/CircleClass.java
@@ -0,0 +1,23 @@
+package com.ossez.interfaceVsAbstractClass;
+
+import java.util.Arrays;
+import java.util.List;
+
+public abstract class CircleClass {
+
+ private String color;
+ private List allowedColors = Arrays.asList("RED", "GREEN", "BLUE");
+
+ public boolean isValid() {
+ return allowedColors.contains(getColor());
+ }
+
+ public String getColor() {
+ return color;
+ }
+
+ public void setColor(String color) {
+ this.color = color;
+ }
+
+}
diff --git a/core-java-modules/core-java-8-2/src/main/java/com/ossez/interfaceVsAbstractClass/CircleInterface.java b/core-java-modules/core-java-8-2/src/main/java/com/ossez/interfaceVsAbstractClass/CircleInterface.java
new file mode 100644
index 0000000000..ed3e69d632
--- /dev/null
+++ b/core-java-modules/core-java-8-2/src/main/java/com/ossez/interfaceVsAbstractClass/CircleInterface.java
@@ -0,0 +1,14 @@
+package com.ossez.interfaceVsAbstractClass;
+
+import java.util.Arrays;
+import java.util.List;
+
+public interface CircleInterface {
+ List allowedColors = Arrays.asList("RED", "GREEN", "BLUE");
+
+ String getColor();
+
+ public default boolean isValid() {
+ return allowedColors.contains(getColor());
+ }
+}
diff --git a/core-java-modules/core-java-8-2/src/main/java/com/ossez/jarArguments/JarExample.java b/core-java-modules/core-java-8-2/src/main/java/com/ossez/jarArguments/JarExample.java
new file mode 100644
index 0000000000..0a173a9879
--- /dev/null
+++ b/core-java-modules/core-java-8-2/src/main/java/com/ossez/jarArguments/JarExample.java
@@ -0,0 +1,18 @@
+package com.ossez.jarArguments;
+
+public class JarExample {
+
+ public static void main(String[] args) {
+ System.out.println("Hello Baeldung Reader in JarExample!");
+
+ if(args == null) {
+ System.out.println("You have not provided any arguments!");
+ }else {
+ System.out.println("There are "+args.length+" argument(s)!");
+ for(int i=0; i locales = Arrays.asList(new Locale[] { Locale.UK, Locale.ITALY, Locale.FRANCE, Locale.forLanguageTag("pl-PL") });
+ Localization.run(locales);
+ JavaSEFormat.run(locales);
+ ICUFormat.run(locales);
+ }
+
+}
diff --git a/core-java-modules/core-java-8-2/src/main/java/com/ossez/localization/ICUFormat.java b/core-java-modules/core-java-8-2/src/main/java/com/ossez/localization/ICUFormat.java
new file mode 100644
index 0000000000..7e91653830
--- /dev/null
+++ b/core-java-modules/core-java-8-2/src/main/java/com/ossez/localization/ICUFormat.java
@@ -0,0 +1,29 @@
+package com.ossez.localization;
+
+import java.util.List;
+import java.util.Locale;
+import java.util.ResourceBundle;
+
+import com.ibm.icu.text.MessageFormat;
+
+public class ICUFormat {
+
+ public static String getLabel(Locale locale, Object[] data) {
+ ResourceBundle bundle = ResourceBundle.getBundle("formats", locale);
+ String format = bundle.getString("label-icu");
+ MessageFormat formatter = new MessageFormat(format, locale);
+ return formatter.format(data);
+ }
+
+ public static void run(List locales) {
+ System.out.println("ICU formatter");
+ locales.forEach(locale -> System.out.println(getLabel(locale, new Object[] { "Alice", "female", 0 })));
+ locales.forEach(locale -> System.out.println(getLabel(locale, new Object[] { "Alice", "female", 1 })));
+ locales.forEach(locale -> System.out.println(getLabel(locale, new Object[] { "Alice", "female", 2 })));
+ locales.forEach(locale -> System.out.println(getLabel(locale, new Object[] { "Alice", "female", 3 })));
+ locales.forEach(locale -> System.out.println(getLabel(locale, new Object[] { "Bob", "male", 0 })));
+ locales.forEach(locale -> System.out.println(getLabel(locale, new Object[] { "Bob", "male", 1 })));
+ locales.forEach(locale -> System.out.println(getLabel(locale, new Object[] { "Bob", "male", 2 })));
+ locales.forEach(locale -> System.out.println(getLabel(locale, new Object[] { "Bob", "male", 3 })));
+ }
+}
diff --git a/core-java-modules/core-java-8-2/src/main/java/com/ossez/localization/JavaSEFormat.java b/core-java-modules/core-java-8-2/src/main/java/com/ossez/localization/JavaSEFormat.java
new file mode 100644
index 0000000000..cfffa70323
--- /dev/null
+++ b/core-java-modules/core-java-8-2/src/main/java/com/ossez/localization/JavaSEFormat.java
@@ -0,0 +1,24 @@
+package com.ossez.localization;
+
+import java.text.MessageFormat;
+import java.util.Date;
+import java.util.List;
+import java.util.Locale;
+import java.util.ResourceBundle;
+
+public class JavaSEFormat {
+
+ public static String getLabel(Locale locale, Object[] data) {
+ ResourceBundle bundle = ResourceBundle.getBundle("formats", locale);
+ final String pattern = bundle.getString("label");
+ final MessageFormat formatter = new MessageFormat(pattern, locale);
+ return formatter.format(data);
+ }
+
+ public static void run(List locales) {
+ System.out.println("Java formatter");
+ final Date date = new Date(System.currentTimeMillis());
+ locales.forEach(locale -> System.out.println(getLabel(locale, new Object[] { date, "Alice", 0 })));
+ locales.forEach(locale -> System.out.println(getLabel(locale, new Object[] { date, "Alice", 2 })));
+ }
+}
diff --git a/core-java-modules/core-java-8-2/src/main/java/com/ossez/localization/Localization.java b/core-java-modules/core-java-8-2/src/main/java/com/ossez/localization/Localization.java
new file mode 100644
index 0000000000..945baf4ee9
--- /dev/null
+++ b/core-java-modules/core-java-8-2/src/main/java/com/ossez/localization/Localization.java
@@ -0,0 +1,18 @@
+package com.ossez.localization;
+
+import java.util.List;
+import java.util.Locale;
+import java.util.ResourceBundle;
+
+public class Localization {
+
+ public static String getLabel(Locale locale) {
+ final ResourceBundle bundle = ResourceBundle.getBundle("messages", locale);
+ return bundle.getString("label");
+ }
+
+ public static void run(List locales) {
+ locales.forEach(locale -> System.out.println(getLabel(locale)));
+ }
+
+}
diff --git a/core-java-modules/core-java-8-2/src/main/java/com/ossez/stream/SkipLimitComparison.java b/core-java-modules/core-java-8-2/src/main/java/com/ossez/stream/SkipLimitComparison.java
new file mode 100644
index 0000000000..8ed279a060
--- /dev/null
+++ b/core-java-modules/core-java-8-2/src/main/java/com/ossez/stream/SkipLimitComparison.java
@@ -0,0 +1,46 @@
+package com.ossez.stream;
+
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+public class SkipLimitComparison {
+
+ public static void main(String[] args) {
+ skipExample();
+ limitExample();
+ limitInfiniteStreamExample();
+ getEvenNumbers(10, 10).stream()
+ .forEach(System.out::println);
+ }
+
+ public static void skipExample() {
+ Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
+ .filter(i -> i % 2 == 0)
+ .skip(2)
+ .forEach(i -> System.out.print(i + " "));
+ }
+
+ public static void limitExample() {
+ Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
+ .filter(i -> i % 2 == 0)
+ .limit(2)
+ .forEach(i -> System.out.print(i + " "));
+ }
+
+ public static void limitInfiniteStreamExample() {
+ Stream.iterate(0, i -> i + 1)
+ .filter(i -> i % 2 == 0)
+ .limit(10)
+ .forEach(System.out::println);
+ }
+
+ private static List getEvenNumbers(int offset, int limit) {
+ return Stream.iterate(0, i -> i + 1)
+ .filter(i -> i % 2 == 0)
+ .skip(offset)
+ .limit(limit)
+ .collect(Collectors.toList());
+ }
+
+}
diff --git a/core-java-modules/core-java-8-2/src/main/java/com/ossez/uuid/UuidHelper.java b/core-java-modules/core-java-8-2/src/main/java/com/ossez/uuid/UuidHelper.java
new file mode 100644
index 0000000000..bfc75d961e
--- /dev/null
+++ b/core-java-modules/core-java-8-2/src/main/java/com/ossez/uuid/UuidHelper.java
@@ -0,0 +1,33 @@
+package com.ossez.uuid;
+
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.UUID;
+
+public class UuidHelper {
+
+ public static byte[] convertUUIDToBytes(UUID uuid) {
+ ByteBuffer bb = ByteBuffer.wrap(new byte[16]);
+ bb.putLong(uuid.getMostSignificantBits());
+ bb.putLong(uuid.getLeastSignificantBits());
+ return bb.array();
+ }
+
+ public static UUID convertBytesToUUID(byte[] bytes) {
+ ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
+ long high = byteBuffer.getLong();
+ long low = byteBuffer.getLong();
+ return new UUID(high, low);
+ }
+
+ public static void main(String[] args) {
+ UUID uuid = UUID.randomUUID();
+ System.out.println("Original UUID: " + uuid);
+
+ byte[] bytes = convertUUIDToBytes(uuid);
+ System.out.println("Converted byte array: " + Arrays.toString(bytes));
+
+ UUID uuidNew = convertBytesToUUID(bytes);
+ System.out.println("Converted UUID: " + uuidNew);
+ }
+}
diff --git a/core-java-modules/core-java-8-2/src/main/resources/META-INF/persistence.xml b/core-java-modules/core-java-8-2/src/main/resources/META-INF/persistence.xml
new file mode 100644
index 0000000000..c412ca0839
--- /dev/null
+++ b/core-java-modules/core-java-8-2/src/main/resources/META-INF/persistence.xml
@@ -0,0 +1,34 @@
+
+
+
+
+ Persist Optional Return Type Demo
+ org.hibernate.jpa.HibernatePersistenceProvider
+ com.baeldung.optionalreturntype.User
+ com.baeldung.optionalreturntype.UserOptional
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/core-java-modules/core-java-8-2/src/main/resources/example_manifest.txt b/core-java-modules/core-java-8-2/src/main/resources/example_manifest.txt
new file mode 100644
index 0000000000..71abcb05fb
--- /dev/null
+++ b/core-java-modules/core-java-8-2/src/main/resources/example_manifest.txt
@@ -0,0 +1 @@
+Main-Class: com.baeldung.jarArguments.JarExample
diff --git a/core-java-modules/core-java-8-2/src/main/resources/formats_en.properties b/core-java-modules/core-java-8-2/src/main/resources/formats_en.properties
new file mode 100644
index 0000000000..41e0e00119
--- /dev/null
+++ b/core-java-modules/core-java-8-2/src/main/resources/formats_en.properties
@@ -0,0 +1,2 @@
+label=On {0, date, short} {1} has sent you {2, choice, 0#no messages|1#a message|2#two messages|2<{2,number,integer} messages}.
+label-icu={0} has sent you {2, plural, =0 {no messages} =1 {a message} other {{2, number, integer} messages}}.
\ No newline at end of file
diff --git a/core-java-modules/core-java-8-2/src/main/resources/formats_fr.properties b/core-java-modules/core-java-8-2/src/main/resources/formats_fr.properties
new file mode 100644
index 0000000000..c2d5159b32
--- /dev/null
+++ b/core-java-modules/core-java-8-2/src/main/resources/formats_fr.properties
@@ -0,0 +1,2 @@
+label={0, date, short}, {1}{2, choice, 0# ne|0<} vous a envoy {2, choice, 0#aucun message|1#un message|2#deux messages|2<{2,number,integer} messages}.
+label-icu={0} {2, plural, =0 {ne } other {}}vous a envoy {2, plural, =0 {aucun message} =1 {un message} other {{2, number, integer} messages}}.
\ No newline at end of file
diff --git a/core-java-modules/core-java-8-2/src/main/resources/formats_it.properties b/core-java-modules/core-java-8-2/src/main/resources/formats_it.properties
new file mode 100644
index 0000000000..43fd1eee1c
--- /dev/null
+++ b/core-java-modules/core-java-8-2/src/main/resources/formats_it.properties
@@ -0,0 +1,2 @@
+label={0, date, short} {1} ti ha inviato {2, choice, 0#nessun messagio|1#un messaggio|2#due messaggi|2<{2, number, integer} messaggi}.
+label-icu={0} {2, plural, =0 {non } other {}}ti ha inviato {2, plural, =0 {nessun messaggio} =1 {un messaggio} other {{2, number, integer} messaggi}}.
\ No newline at end of file
diff --git a/core-java-modules/core-java-8-2/src/main/resources/formats_pl.properties b/core-java-modules/core-java-8-2/src/main/resources/formats_pl.properties
new file mode 100644
index 0000000000..9333ec3396
--- /dev/null
+++ b/core-java-modules/core-java-8-2/src/main/resources/formats_pl.properties
@@ -0,0 +1,2 @@
+label=W {0, date, short} {1}{2, choice, 0# nie|0<} wys\u0142a\u0142a ci {2, choice, 0#\u017Cadnych wiadomo\u015Bci|1#wiadomo\u015B\u0107|2#dwie wiadomo\u015Bci|2<{2, number, integer} wiadomo\u015Bci}.
+label-icu={0} {2, plural, =0 {nie } other {}}{1, select, male {wys\u0142a\u0142} female {wys\u0142a\u0142a} other {wys\u0142a\u0142o}} ci {2, plural, =0 {\u017Cadnej wiadomo\u015Bci} =1 {wiadomo\u015B\u0107} other {{2, number, integer} wiadomo\u015Bci}}.
diff --git a/core-java-modules/core-java-8-2/src/main/resources/messages_en.properties b/core-java-modules/core-java-8-2/src/main/resources/messages_en.properties
new file mode 100644
index 0000000000..bcbca9483c
--- /dev/null
+++ b/core-java-modules/core-java-8-2/src/main/resources/messages_en.properties
@@ -0,0 +1 @@
+label=Alice has sent you a message.
diff --git a/core-java-modules/core-java-8-2/src/main/resources/messages_fr.properties b/core-java-modules/core-java-8-2/src/main/resources/messages_fr.properties
new file mode 100644
index 0000000000..6716102568
--- /dev/null
+++ b/core-java-modules/core-java-8-2/src/main/resources/messages_fr.properties
@@ -0,0 +1 @@
+label=Alice vous a envoy un message.
\ No newline at end of file
diff --git a/core-java-modules/core-java-8-2/src/main/resources/messages_it.properties b/core-java-modules/core-java-8-2/src/main/resources/messages_it.properties
new file mode 100644
index 0000000000..6929a8c091
--- /dev/null
+++ b/core-java-modules/core-java-8-2/src/main/resources/messages_it.properties
@@ -0,0 +1 @@
+label=Alice ti ha inviato un messaggio.
\ No newline at end of file
diff --git a/core-java-modules/core-java-8-2/src/main/resources/messages_pl.properties b/core-java-modules/core-java-8-2/src/main/resources/messages_pl.properties
new file mode 100644
index 0000000000..5515a9920e
--- /dev/null
+++ b/core-java-modules/core-java-8-2/src/main/resources/messages_pl.properties
@@ -0,0 +1 @@
+label=Alice wys\u0142a\u0142a ci wiadomo\u015B\u0107.
\ No newline at end of file
diff --git a/core-java-modules/core-java-8-2/src/test/java/com/ossez/bifunction/BiFunctionalInterfacesUnitTest.java b/core-java-modules/core-java-8-2/src/test/java/com/ossez/bifunction/BiFunctionalInterfacesUnitTest.java
new file mode 100644
index 0000000000..c20fcdf5a4
--- /dev/null
+++ b/core-java-modules/core-java-8-2/src/test/java/com/ossez/bifunction/BiFunctionalInterfacesUnitTest.java
@@ -0,0 +1,164 @@
+package com.ossez.bifunction;
+
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.List;
+import java.util.function.BiFunction;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class BiFunctionalInterfacesUnitTest {
+ @Test
+ public void givenStreamValues_whenMappedToNewValues() {
+ List mapped = Stream.of("hello", "world")
+ .map(word -> word + "!")
+ .collect(Collectors.toList());
+
+ assertThat(mapped).containsExactly("hello!", "world!");
+ }
+
+ @Test
+ public void givenStreamValues_whenReducedWithPrefixingOperation() {
+ String result = Stream.of("hello", "world")
+ .reduce("", (a, b) -> b + "-" + a);
+
+ assertThat(result).isEqualTo("world-hello-");
+ }
+
+ @Test
+ public void givenStreamValues_whenReducedWithPrefixingLambda_thenHasNoTrailingDash() {
+ String result = Stream.of("hello", "world")
+ .reduce("", (a, b) -> combineWithoutTrailingDash(a, b));
+
+ assertThat(result).isEqualTo("world-hello");
+ }
+
+ private String combineWithoutTrailingDash(String a, String b) {
+ if (a.isEmpty()) {
+ return b;
+ }
+ return b + "-" + a;
+ }
+
+ @Test
+ public void givenStreamValues_whenReducedWithPrefixingMethodReference_thenHasNoTrailingDash() {
+ String result = Stream.of("hello", "world")
+ .reduce("", this::combineWithoutTrailingDash);
+
+ assertThat(result).isEqualTo("world-hello");
+ }
+
+ @Test
+ public void givenTwoLists_whenCombined() {
+ List list1 = Arrays.asList("a", "b", "c");
+ List list2 = Arrays.asList(1, 2, 3);
+
+ List result = new ArrayList<>();
+ for (int i=0; i < list1.size(); i++) {
+ result.add(list1.get(i) + list2.get(i));
+ }
+
+ assertThat(result).containsExactly("a1", "b2", "c3");
+ }
+
+ @Test
+ public void givenTwoLists_whenCombinedWithGeneralPurposeCombiner() {
+ List list1 = Arrays.asList("a", "b", "c");
+ List list2 = Arrays.asList(1, 2, 3);
+
+ List result = listCombiner(list1, list2, (a, b) -> a + b);
+
+ assertThat(result).containsExactly("a1", "b2", "c3");
+ }
+
+ private static List listCombiner(List list1,
+ List list2,
+ BiFunction combiner) {
+ List result = new ArrayList<>();
+ for (int i = 0; i < list1.size(); i++) {
+ result.add(combiner.apply(list1.get(i), list2.get(i)));
+ }
+ return result;
+ }
+
+ @Test
+ public void givenTwoLists_whenComparedWithCombiningFunction() {
+ List list1 = Arrays.asList(1.0d, 2.1d, 3.3d);
+ List list2 = Arrays.asList(0.1f, 0.2f, 4f);
+
+ // algorithm to determine if the value in list1 > value in list 2
+ List result = listCombiner(list1, list2, (a, b) -> a > b);
+
+ assertThat(result).containsExactly(true, true, false);
+ }
+
+ @Test
+ public void givenTwoLists_whenComparedWithCombiningFunctionByMethodReference() {
+ List list1 = Arrays.asList(1.0d, 2.1d, 3.3d);
+ List list2 = Arrays.asList(0.1f, 0.2f, 4f);
+
+ // algorithm to determine if the value in list1 > value in list 2
+ List result = listCombiner(list1, list2, this::firstIsGreaterThanSecond);
+
+ assertThat(result).containsExactly(true, true, false);
+ }
+
+ private boolean firstIsGreaterThanSecond(Double a, Float b) {
+ return a > b;
+ }
+
+ @Test
+ public void givenTwoLists_whenComparedForEqualityByCombiningFunction() {
+ List list1 = Arrays.asList(0.1f, 0.2f, 4f);
+ List list2 = Arrays.asList(0.1f, 0.2f, 4f);
+
+ List result = listCombiner(list1, list2, (a, b) -> a.equals(b));
+
+ assertThat(result).containsExactly(true, true, true);
+ }
+
+ @Test
+ public void givenTwoLists_whenComparedForEqualityByCombiningFunctionWithMethodReference() {
+ List list1 = Arrays.asList(0.1f, 0.2f, 4f);
+ List list2 = Arrays.asList(0.1f, 0.2f, 4f);
+
+ List result = listCombiner(list1, list2, Float::equals);
+
+ assertThat(result).containsExactly(true, true, true);
+ }
+
+ @Test
+ public void givenTwoLists_whenComparedWithCombiningFunctionWithCompareTo() {
+ List list1 = Arrays.asList(1.0d, 2.1d, 3.3d);
+ List list2 = Arrays.asList(0.1d, 0.2d, 4d);
+
+ List result = listCombiner(list1, list2, Double::compareTo);
+
+ assertThat(result).containsExactly(1, 1, -1);
+ }
+
+ /**
+ * Allows you to to pass in a lambda or method reference and then
+ * get access to the BiFunction it is meant to become
+ */
+ private static BiFunction asBiFunction(BiFunction function) {
+ return function;
+ }
+
+ @Test
+ public void givenTwoLists_whenComparedWithCombiningFunctionWithComposedBiFunction() {
+ List list1 = Arrays.asList(1.0d, 2.1d, 3.3d);
+ List list2 = Arrays.asList(0.1d, 0.2d, 4d);
+
+ List result = listCombiner(list1, list2,
+ asBiFunction(Double::compareTo)
+ .andThen(i -> i > 0));
+
+ assertThat(result).containsExactly(true, true, false);
+ }
+}
diff --git a/core-java-modules/core-java-8-2/src/test/java/com/ossez/interfaceVsAbstractClass/InterfaceVsAbstractClassUnitTest.java b/core-java-modules/core-java-8-2/src/test/java/com/ossez/interfaceVsAbstractClass/InterfaceVsAbstractClassUnitTest.java
new file mode 100644
index 0000000000..8c4729a895
--- /dev/null
+++ b/core-java-modules/core-java-8-2/src/test/java/com/ossez/interfaceVsAbstractClass/InterfaceVsAbstractClassUnitTest.java
@@ -0,0 +1,21 @@
+package com.ossez.interfaceVsAbstractClass;
+
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+public class InterfaceVsAbstractClassUnitTest {
+ @Test
+ public void givenAbstractClass_whenValidCircleUsed_thenPass() {
+ CircleClass redCircle = new ChildCircleClass();
+ redCircle.setColor("RED");
+ assertTrue(redCircle.isValid());
+ }
+
+ @Test
+ public void givenInterface_whenValidCircleWithoutStateUsed_thenPass() {
+ ChidlCircleInterfaceImpl redCircleWithoutState = new ChidlCircleInterfaceImpl();
+ redCircleWithoutState.setColor("RED");
+ assertTrue(redCircleWithoutState.isValid());
+ }
+}
diff --git a/core-java-modules/core-java-8-2/src/test/java/com/ossez/localization/ICUFormatUnitTest.java b/core-java-modules/core-java-8-2/src/test/java/com/ossez/localization/ICUFormatUnitTest.java
new file mode 100644
index 0000000000..3aef525e91
--- /dev/null
+++ b/core-java-modules/core-java-8-2/src/test/java/com/ossez/localization/ICUFormatUnitTest.java
@@ -0,0 +1,72 @@
+package com.ossez.localization;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.Locale;
+
+import org.junit.Test;
+
+public class ICUFormatUnitTest {
+
+ @Test
+ public void givenInUK_whenAliceSendsNothing_thenCorrectMessage() {
+ assertEquals("Alice has sent you no messages.", ICUFormat.getLabel(Locale.UK, new Object[] { "Alice", "female", 0 }));
+ }
+
+ @Test
+ public void givenInUK_whenAliceSendsOneMessage_thenCorrectMessage() {
+ assertEquals("Alice has sent you a message.", ICUFormat.getLabel(Locale.UK, new Object[] { "Alice", "female", 1 }));
+ }
+
+ @Test
+ public void givenInUK_whenBobSendsSixMessages_thenCorrectMessage() {
+ assertEquals("Bob has sent you 6 messages.", ICUFormat.getLabel(Locale.UK, new Object[] { "Bob", "male", 6 }));
+ }
+
+ @Test
+ public void givenInItaly_whenAliceSendsNothing_thenCorrectMessage() {
+ assertEquals("Alice non ti ha inviato nessun messaggio.", ICUFormat.getLabel(Locale.ITALY, new Object[] { "Alice", "female", 0 }));
+ }
+
+ @Test
+ public void givenInItaly_whenAliceSendsOneMessage_thenCorrectMessage() {
+ assertEquals("Alice ti ha inviato un messaggio.", ICUFormat.getLabel(Locale.ITALY, new Object[] { "Alice", "female", 1 }));
+ }
+
+ @Test
+ public void givenInItaly_whenBobSendsSixMessages_thenCorrectMessage() {
+ assertEquals("Bob ti ha inviato 6 messaggi.", ICUFormat.getLabel(Locale.ITALY, new Object[] { "Bob", "male", 6 }));
+ }
+
+ @Test
+ public void givenInFrance_whenAliceSendsNothing_thenCorrectMessage() {
+ assertEquals("Alice ne vous a envoyé aucun message.", ICUFormat.getLabel(Locale.FRANCE, new Object[] { "Alice", "female", 0 }));
+ }
+
+ @Test
+ public void givenInFrance_whenAliceSendsOneMessage_thenCorrectMessage() {
+ assertEquals("Alice vous a envoyé un message.", ICUFormat.getLabel(Locale.FRANCE, new Object[] { "Alice", "female", 1 }));
+ }
+
+ @Test
+ public void givenInFrance_whenBobSendsSixMessages_thenCorrectMessage() {
+ assertEquals("Bob vous a envoyé 6 messages.", ICUFormat.getLabel(Locale.FRANCE, new Object[] { "Bob", "male", 6 }));
+ }
+
+
+ @Test
+ public void givenInPoland_whenAliceSendsNothing_thenCorrectMessage() {
+ assertEquals("Alice nie wysłała ci żadnej wiadomości.", ICUFormat.getLabel(Locale.forLanguageTag("pl-PL"), new Object[] { "Alice", "female", 0 }));
+ }
+
+ @Test
+ public void givenInPoland_whenAliceSendsOneMessage_thenCorrectMessage() {
+ assertEquals("Alice wysłała ci wiadomość.", ICUFormat.getLabel(Locale.forLanguageTag("pl-PL"), new Object[] { "Alice", "female", 1 }));
+ }
+
+ @Test
+ public void givenInPoland_whenBobSendsSixMessages_thenCorrectMessage() {
+ assertEquals("Bob wysłał ci 6 wiadomości.", ICUFormat.getLabel(Locale.forLanguageTag("pl-PL"), new Object[] { "Bob", "male", 6 }));
+ }
+
+}
diff --git a/core-java-modules/core-java-8/README.md b/core-java-modules/core-java-8/README.md
index d7a9ff7cbc..e207871def 100644
--- a/core-java-modules/core-java-8/README.md
+++ b/core-java-modules/core-java-8/README.md
@@ -1,6 +1,6 @@
## Java 8 核心
-本模块中包含有关 Java 8 核心新增功能特性的一些文章
+本模块中包含有关 Java 8 核心新增功能特性的一些文章。
### 相关文章:
- [New Features in Java 8](https://www.baeldung.com/java-8-new-features)
@@ -12,4 +12,4 @@
- [Finding Min/Max in an Array with Java](https://www.baeldung.com/java-array-min-max)
- [Internationalization and Localization in Java 8](https://www.baeldung.com/java-8-localization)
- [Generalized Target-Type Inference in Java](https://www.baeldung.com/java-generalized-target-type-inference)
-- [[More -->]](/core-java-modules/core-java-8-2)
+- [[Java 8 核心(第 2 部分) -->]](/core-java-modules/core-java-8-2)