diff --git a/.gitignore b/.gitignore
index 57822d6..168a863 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,6 +14,10 @@ target
.factorypath
.asciidoctor/
*.ttf
+*.otf
+/cfg/gems
fonts.ttf.tgz
*.icloud
+
+
diff --git a/cfg/fonts/download-fonts.sh b/cfg/fonts/download-fonts.sh
deleted file mode 100755
index 66f010d..0000000
--- a/cfg/fonts/download-fonts.sh
+++ /dev/null
@@ -1,12 +0,0 @@
-#!/usr/bin/env bash
-#
-# Download the fonts
-
-wget https://github.com/diguage/jdk-source-analysis/releases/download/source-fonts.ttf/fonts.ttf.tgz
-
-tar -zxvf fonts.ttf.tgz
-
-
-# Backup download URL: https://github.com/adobe-fonts/source-han-serif/archive/1.001R.zip
-
-# Maybe you have to convert the OTF fonts to TTF fonts by the otf2ttf tools of AFDKO(https://github.com/adobe-type-tools/afdko/)
diff --git a/cfg/gems/.gitkeep b/cfg/gems/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/cfg/theme/Source-theme.yml b/cfg/theme/Source-theme.yml
index 3800769..98b1019 100644
--- a/cfg/theme/Source-theme.yml
+++ b/cfg/theme/Source-theme.yml
@@ -2,19 +2,21 @@ font:
catalog:
merge: true
Source Han Serif SC:
- normal: SourceHanSerifSC-Regular.ttf
- bold: SourceHanSerifSC-Bold.ttf
- italic: SourceHanSerifSC-Medium.ttf
- bold_italic: SourceHanSerifSC-SemiBold.ttf
+ normal: SourceHanSerifSC-Regular.otf
+ bold: SourceHanSerifSC-Bold.otf
+ italic: SourceHanSerifSC-Medium.otf
+ bold_italic: SourceHanSerifSC-SemiBold.otf
#SourceHanSerifSC-Heavy.otf
#SourceHanSerifSC-ExtraLight.otf
#SourceHanSerifSC-Light.otf
Source Code Pro:
- normal: SourceCodePro-Regular.ttf
- bold: SourceCodePro-Semibold.ttf
- italic: SourceCodePro-It.ttf
- bold_italic: SourceCodePro-BoldIt.ttf
- Emoji: Symbola.ttf
+ normal: SourceCodePro-Regular.otf
+ bold: SourceCodePro-Semibold.otf
+ italic: SourceCodePro-It.otf
+ bold_italic: SourceCodePro-BoldIt.otf
+# Emoji: NotoColorEmoji.ttf
+ Emoji: NotoEmoji-Regular.ttf
+# Emoji: Symbola.ttf
#SourceCodePro-Black.ttf
#SourceCodePro-BlackIt.ttf
#SourceCodePro-ExtraLight.ttf
diff --git a/docs/diagram/ack.puml b/docs/diagram/ack.puml
new file mode 100644
index 0000000..83e971f
--- /dev/null
+++ b/docs/diagram/ack.puml
@@ -0,0 +1,4 @@
+@startuml
+
+
+@enduml
diff --git a/docs/java.lang.String.adoc b/docs/java.lang.String.adoc
index f3fe69e..d527555 100644
--- a/docs/java.lang.String.adoc
+++ b/docs/java.lang.String.adoc
@@ -10,3 +10,9 @@ include::{sourcedir}/StringUtils.java[]
----
include::{sourcedir}/StringUtilTest.java[]
----
+
+
+[{java_src_attr}]
+----
+include::{sourcedir}/StringTest.java[]
+----
diff --git a/docs/java.util.Iterator.adoc b/docs/java.util.Iterator.adoc
index f30100b..ccdabcb 100644
--- a/docs/java.util.Iterator.adoc
+++ b/docs/java.util.Iterator.adoc
@@ -26,9 +26,10 @@ ____
....
@startuml
'skinparam nodesep 70
+skinparam titleFontSize 30
skinparam defaultFontName Hiragino Sans GB
-title 迭代器模式
+title **迭代器模式**
abstract class Iterator {
+ {abstract} first() :Object
@@ -64,6 +65,9 @@ Iterator <|-- ConcreteIterator
ConcreteIterator -left-> ConcreteAggregate
ConcreteIterator <.. ConcreteAggregate
+skinparam footerFontSize 20
+footer D瓜哥 · https://www.diguage.com · 出品
+
@enduml
....
diff --git a/docs/java.util.concurrent.CompletableFuture.adoc b/docs/java.util.concurrent.CompletableFuture.adoc
index 1702ed0..daec70f 100644
--- a/docs/java.util.concurrent.CompletableFuture.adoc
+++ b/docs/java.util.concurrent.CompletableFuture.adoc
@@ -9,6 +9,13 @@ Java 中的 Promise。
include::{sourcedir}/concurrent/CompletableFutureTest.java[]
----
+`CompletableFuture` 实现了 `Future` 和 `CompletionStage` 两个接口。
+
+`CompletionStage` 接口声明了大量方法, `thenApply*` 接受 `Function` 对象,可以实现将任务的结果转化成另外一个对象,类似 Java Stream API 中的 `map` 操作; `thenAccept` 接受 `Consumer` 对象,见文知意,就是“消费”异步任务的结果值,类似 Java Stream API 的“终止操作”。
+
+
+
== 参考资料
. https://www.baeldung.com/java-completablefuture[Guide To CompletableFuture | Baeldung]
+. https://xie.infoq.cn/article/12fb1f7f825bb27795679ad13[Java 8 的异步利器:CompletableFuture源码解析^]
diff --git a/pom.xml b/pom.xml
index 9f06787..af6134b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -13,29 +13,37 @@
https://www.diguage.com/
- 0.16
- 1.35
- 2.8.9
+ 0.17
+ 1.36
+ 2.10.1
2.10.13
- 1.12.10
- 4.1.77.Final
- 3.21.1
+ 1.14.4
+ 4.1.92.Final
+ 3.23.1
31.1-jre
4.4
11.0.0
1.7.36
- 1.2.11
+ 1.2.12
5.8.2
3.23.1
- 2.5.4
- 2.0.6
+ 2.5.8
+ 2.3.7
1.5.1
- 2.2.3
- 2.2.2
- 9.3.4.0
+ 2.2.8
+ 0.0.16
+ 0.0.1
+ 2.2.3
+ 9.3.10.0
+ ${project.basedir}/cfg/gems
+ ${project.basedir}/cfg/fonts
+ https://github.com/diguage/open-fonts/releases/download/latest
+ 1.0.3
+ 2.0.1
+ 1.7.0
17
17
UTF-8
@@ -141,9 +149,233 @@
assertj-core
${assertj.version}
+
+
+ rubygems
+ asciidoctor-multipage
+ ${asciidoctor-multipage.version}
+ gem
+
+
+ rubygems
+ asciidoctor
+
+
+
+
+ rubygems
+ asciidoctor-comment-links
+ ${asciidoctor-comment-links.version}
+ gem
+
+
+ rubygems
+ asciidoctor
+
+
+
+
+
+ org.torquebox.mojo
+ mavengem-wagon
+ ${mavengem-wagon.version}
+
+
+
+ de.saumya.mojo
+ gem-maven-plugin
+ ${gem-maven-plugin.version}
+
+ ${jruby.version}
+
+
+ ${gem.path}
+
+
+ ${gem.path}
+
+
+
+
+ install-gems
+
+ initialize
+
+ initialize
+
+
+
+
+ com.googlecode.maven-download-plugin
+ download-maven-plugin
+ ${download-maven-plugin.version}
+
+
+ install-font-NotoEmoji-Regular
+ initialize
+
+ wget
+
+
+ ${pdf-fonts.baseuri}/NotoEmoji-Regular.ttf
+ ${pdf-fonts.path}
+ f224032937e77448b2586b171ed7d031
+
+
+
+
+
+ install-font-SourceCodePro-Regular
+ initialize
+
+ wget
+
+
+ ${pdf-fonts.baseuri}/SourceCodePro-Regular.otf
+ ${pdf-fonts.path}
+ 881bfa23a0fc625abe2a8c38b2a72180
+
+
+
+ install-font-SourceCodePro-Semibold
+ initialize
+
+ wget
+
+
+ ${pdf-fonts.baseuri}/SourceCodePro-Semibold.otf
+ ${pdf-fonts.path}
+ e09d6d82c6e77726b03f3929dd2b6961
+
+
+
+ install-font-SourceCodePro-It
+ initialize
+
+ wget
+
+
+ ${pdf-fonts.baseuri}/SourceCodePro-It.otf
+ ${pdf-fonts.path}
+ 6fc0b73a8f4b42cc9ecb5154e3b45dcd
+
+
+
+ install-font-SourceCodePro-BoldIt
+ initialize
+
+ wget
+
+
+ ${pdf-fonts.baseuri}/SourceCodePro-BoldIt.otf
+ ${pdf-fonts.path}
+ 5b7d949c95111f4a7166553db479e5e1
+
+
+
+
+
+ install-font-SourceHanSerifSC-Regular
+ initialize
+
+ wget
+
+
+ ${pdf-fonts.baseuri}/SourceHanSerifSC-Regular.otf
+ ${pdf-fonts.path}
+ 3990fae1c68e4144013f92273fca41a9
+
+
+
+ install-font-SourceHanSerifSC-Bold
+ initialize
+
+ wget
+
+
+ ${pdf-fonts.baseuri}/SourceHanSerifSC-Bold.otf
+ ${pdf-fonts.path}
+ 9bb66a8d136498b323b3549f95a53935
+
+
+
+ install-font-SourceHanSerifSC-Medium
+ initialize
+
+ wget
+
+
+ ${pdf-fonts.baseuri}/SourceHanSerifSC-Medium.otf
+ ${pdf-fonts.path}
+ 46f15d8b48f93010232fbdb46c36006b
+
+
+
+ install-font-SourceHanSerifSC-SemiBold
+ initialize
+
+ wget
+
+
+ ${pdf-fonts.baseuri}/SourceHanSerifSC-SemiBold.otf
+ ${pdf-fonts.path}
+ c27bc5f59edac6bd68d7a15d4f6a05f8
+
+
+
+
+ install-font-SourceHanSansSC-Regular
+ initialize
+
+ wget
+
+
+ ${pdf-fonts.baseuri}/SourceHanSansSC-Regular.otf
+ ${pdf-fonts.path}
+ 56195441817e7172c4cd914388710f20
+
+
+
+ install-font-SourceHanSansSC-Bold
+ initialize
+
+ wget
+
+
+ ${pdf-fonts.baseuri}/SourceHanSansSC-Bold.otf
+ ${pdf-fonts.path}
+ c76f8a8f08293d0e1c5dc8302f7062aa
+
+
+
+ install-font-SourceHanSansSC-Medium
+ initialize
+
+ wget
+
+
+ ${pdf-fonts.baseuri}/SourceHanSansSC-Medium.otf
+ ${pdf-fonts.path}
+ ebc3cd485fe89cc90b38be33464894ae
+
+
+
+ install-font-SourceHanSansSC-Heavy
+ initialize
+
+ wget
+
+
+ ${pdf-fonts.baseuri}/SourceHanSansSC-Heavy.otf
+ ${pdf-fonts.path}
+ 2dbb493c201153533bc0f92e93cee6af
+
+
+
+
org.asciidoctor
asciidoctor-maven-plugin
@@ -168,7 +400,7 @@
3
true
/usr/local/bin/dot
- linenums,indent=0,subs="attributes,verbatim,quotes"
+ indent=0,subs="attributes,verbatim,quotes"
source%nowrap,java,{source_attr}
source%nowrap,html,{source_attr}
align="center",width=100%
@@ -176,6 +408,31 @@
+
+ generate-multipage
+ package
+
+ process-asciidoc
+
+
+ multipage_html5
+ book
+
+ ${gem.path}
+
+ asciidoctor-diagram
+ asciidoctor-multipage
+ asciidoctor-comment-links
+
+
+ ${project.build.directory}/docs/multipage
+
+
+ left
+ indent=0,subs="attributes,verbatim,quotes"
+
+
+
generate-html
package
@@ -189,6 +446,7 @@
left
true
+ indent=0,subs="attributes,verbatim,quotes"
@@ -294,4 +552,12 @@
+
+
+
+ mavengems
+
+ mavengem:https://gems.ruby-china.com
+
+
diff --git a/src/main/java/com/diguage/truman/ComparatorTest.java b/src/main/java/com/diguage/truman/ComparatorTest.java
new file mode 100644
index 0000000..7efb5de
--- /dev/null
+++ b/src/main/java/com/diguage/truman/ComparatorTest.java
@@ -0,0 +1,52 @@
+package com.diguage.truman;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class ComparatorTest {
+ public static class User {
+ public User(String name, int age, int sex) {
+ this.name = name;
+ this.age = age;
+ this.sex = sex;
+ }
+
+ String name;
+ int age;
+
+ int sex;
+
+ @Override
+ public String toString() {
+ return "User{" +
+ "name='" + name + '\'' +
+ ", age=" + age +
+ ", sex=" + sex +
+ '}';
+ }
+ }
+
+ @Test
+ public void test() {
+ List users = Arrays.asList(
+ new User("u4", 4, 1),
+ new User("u2", 2, 1),
+ new User("u1", 1, 0),
+ new User("u3", 2, 0));
+ List result = users.stream()
+ .sorted((a, b) -> {
+ if (0 == a.sex) {
+ return -1;
+ }
+ if (0 == b.sex) {
+ return 1;
+ }
+ return 0;
+ })
+ .collect(Collectors.toList());
+ System.out.println(Arrays.toString(result.toArray()));
+ }
+}
diff --git a/src/main/java/com/diguage/truman/HashMapTest.java b/src/main/java/com/diguage/truman/HashMapTest.java
new file mode 100644
index 0000000..6ddcde4
--- /dev/null
+++ b/src/main/java/com/diguage/truman/HashMapTest.java
@@ -0,0 +1,18 @@
+package com.diguage.truman;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+
+public class HashMapTest {
+ @Test
+ public void test() {
+ Map map = new HashMap<>();
+ map.put("123", null);
+ assertThat(map.getOrDefault("123", "456")).isNull();
+ }
+}
diff --git a/src/main/java/com/diguage/truman/LongTest.java b/src/main/java/com/diguage/truman/LongTest.java
new file mode 100644
index 0000000..f8953da
--- /dev/null
+++ b/src/main/java/com/diguage/truman/LongTest.java
@@ -0,0 +1,12 @@
+package com.diguage.truman;
+
+import org.junit.jupiter.api.Test;
+
+public class LongTest {
+ @Test
+ public void test() {
+ System.out.println(Long.toHexString(Long.MAX_VALUE));
+ System.out.println(Long.toHexString(System.nanoTime()));
+ System.out.println(Long.toHexString(System.currentTimeMillis()));
+ }
+}
diff --git a/src/main/java/com/diguage/truman/StringTest.java b/src/main/java/com/diguage/truman/StringTest.java
new file mode 100644
index 0000000..96db0b4
--- /dev/null
+++ b/src/main/java/com/diguage/truman/StringTest.java
@@ -0,0 +1,52 @@
+package com.diguage.truman;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+public class StringTest {
+
+ @Test
+ public void testSplit() {
+ String s = "abc";
+ System.out.println(Arrays.toString(s.split("\\|")));
+
+
+ // 调用 split 方法,如果参数为 null 时,则抛异常
+ assertThatThrownBy(() -> s.split(null)).isInstanceOf(NullPointerException.class);
+ }
+
+ @Test
+ public void testReplaceAll() {
+ String value = "${abc} 是一个占位符,${abc}";
+ Set placeholders = getAllPlaceholders(value);
+
+ for (String placeholder : placeholders) {
+ System.out.println(value.replaceAll(placeholder, "ABC"));
+ }
+ }
+
+ /**
+ * 占位符正则表达式:${\w*}
+ */
+ private static final Pattern PH_PATTERN = Pattern.compile("(\\u0024\\{\\w*\\})+");
+ private static Set getAllPlaceholders(String value) {
+ Matcher matcher = PH_PATTERN.matcher(value);
+ Set placeholders = new HashSet<>();
+ int matcherStart = 0;
+ while (matcher.find(matcherStart)) {
+ String group = matcher.group();
+ placeholders.add(group);
+ matcherStart = matcher.end();
+ }
+ System.out.println(Arrays.toString(placeholders.toArray(new String[0])));
+ return placeholders;
+ }
+
+}
diff --git a/src/main/java/com/diguage/truman/concurrent/CompletedFutureTest.java b/src/main/java/com/diguage/truman/concurrent/CompletedFutureTest.java
new file mode 100644
index 0000000..515b022
--- /dev/null
+++ b/src/main/java/com/diguage/truman/concurrent/CompletedFutureTest.java
@@ -0,0 +1,126 @@
+package com.diguage.truman.concurrent;
+
+import org.junit.jupiter.api.Test;
+
+import java.time.LocalTime;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.locks.LockSupport;
+
+public class CompletedFutureTest {
+
+
+ /**
+ * 入门
+ */
+ @Test
+ public void testIntro() throws ExecutionException, InterruptedException {
+ CompletableFuture future = new CompletableFuture<>();
+ new Thread(() -> {
+ System.out.println("CompletableFuture 可以监控任务执行情况");
+ future.complete("Result: https://www.diguage.com");
+ }).start();
+ System.out.println(future.get());
+ }
+
+
+ @Test
+ public void test3() {
+ CompletableFuture future = CompletableFuture.supplyAsync(() -> {
+// try {
+// TimeUnit.SECONDS.sleep(5);
+// } catch (InterruptedException e) {
+// }
+ return 0;
+ });
+ try {
+ future.get(1, TimeUnit.SECONDS);
+ } catch (TimeoutException e) {
+ System.out.println("timeout");
+ } catch (Throwable e) {
+ }
+ try {
+ System.out.println("get task1: " + future.get());
+ } catch (Throwable e) {
+ }
+ future.thenComposeAsync(r -> CompletableFuture.supplyAsync(() -> {
+ System.out.println("get task1 result=" + r);
+ return 1;
+ }));
+ }
+
+
+ @Test
+ public void test2() {
+ CompletableFuture future = CompletableFuture.supplyAsync(() -> {
+ monteCarloMethod(Long.MAX_VALUE);
+ return 0;
+ });
+
+ try {
+ future.get(1, TimeUnit.SECONDS);
+ } catch (InterruptedException | ExecutionException | TimeoutException e) {
+ while (true) {
+ System.out.println("timeout, and then throw an error.");
+ }
+ }
+ LockSupport.park();
+ }
+
+
+ @Test
+ public void test() throws ExecutionException, InterruptedException {
+ AtomicInteger cnt = new AtomicInteger(0);
+
+ CompletableFuture cf1 = CompletableFuture.supplyAsync(() -> monteCarloMethod(10000));
+ CompletableFuture cf2 = CompletableFuture.supplyAsync(() -> monteCarloMethod(100000));
+ CompletableFuture all = CompletableFuture.allOf(cf1, cf2);
+
+
+ System.out.println("start to get result");
+ System.out.println(LocalTime.now() + " : " + cf1.get());
+ System.out.println("got the result");
+// LockSupport.park();
+ }
+
+ /**
+ * 蒙特卡罗算法
+ */
+ private static double monteCarloMethod(long count) {
+ double pi = 0;
+ int circles = 0;
+ int squares = 0;
+
+ // Total Random numbers generated = possible x
+ // values * possible y values
+ while (squares < count) {
+
+ // Randomly generated x and y values in the range [-1,1]
+ double x = Math.random() * 2 - 1;
+ double y = Math.random() * 2 - 1;
+
+ // Distance between (x, y) from the origin
+ double dist = x * x + y * y;
+
+ // Checking if (x, y) lies inside the define
+ // circle with R=1
+ if (dist <= 1) {
+ circles++;
+ }
+
+ // Total number of points generated
+ squares++;
+
+ // estimated pi after this iteration
+ pi = (4.0 * circles) / squares;
+ if (squares % 10 == 0) {
+ System.out.println(circles + " " + squares + " - " + pi);
+ }
+ }
+
+ return pi;
+ }
+}
diff --git a/src/main/java/com/diguage/truman/stream/CollectorsTest.java b/src/main/java/com/diguage/truman/stream/CollectorsTest.java
new file mode 100644
index 0000000..04fc53c
--- /dev/null
+++ b/src/main/java/com/diguage/truman/stream/CollectorsTest.java
@@ -0,0 +1,19 @@
+package com.diguage.truman.stream;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+public class CollectorsTest {
+ @Test
+ public void testToList() {
+ List ints = Arrays.asList(1, 2, 3);
+ List filtered = ints.stream()
+ .filter(i -> i > 5)
+ .collect(Collectors.toList());
+ System.out.println(Objects.isNull(filtered));
+ }
+}