From fb35c963caa49bffcc28b3ca297d757c10298b02 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Thu, 6 Sep 2018 18:50:05 -0700 Subject: [PATCH 001/132] add pairing question --- .../interviewQuestions/CirclePairing.java | 111 ++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 src/main/java/interviewQuestions/CirclePairing.java diff --git a/src/main/java/interviewQuestions/CirclePairing.java b/src/main/java/interviewQuestions/CirclePairing.java new file mode 100644 index 0000000..d4f2581 --- /dev/null +++ b/src/main/java/interviewQuestions/CirclePairing.java @@ -0,0 +1,111 @@ +package interviewQuestions; + +public class CirclePairing { + + /**warm up round: + * Given a list of words, find the longest common prefix. + * + * ["flower","flow","flight"] return "fl" + * ["dog","racecar","car"] return "" + * + * what's the time complexity of your solution? + * what's the space complexity of your solution? + * */ + + /**Solution 1: Horizontal scanning*/ + public String longestCommonPrefix_horizontalScanning(String[] strs) { + if (strs.length == 0) { + return ""; + } + String prefix = strs[0]; + for (int i = 1; i < strs.length; i++) { + while (strs[i].indexOf(prefix) != 0) { + prefix = prefix.substring(0, prefix.length() - 1); + if (prefix.isEmpty()) { + return ""; + } + } + } + return prefix; + } + + /**Solution 2: vertical scanning*/ + public String longestCommonPrefix_verticalScanning(String[] strs) { + if (strs == null || strs.length == 0) { + return ""; + } + for (int i = 0; i < strs[0].length() ; i++){ + char c = strs[0].charAt(i); + for (int j = 1; j < strs.length; j ++) { + if (i == strs[j].length() || strs[j].charAt(i) != c) + return strs[0].substring(0, i); + } + } + return strs[0]; + } + + /**Solution 2: vertical scanning, verbose version*/ + public String longestCommonPrefix_verticalScanningVerbose(String[] strs) { + if (strs == null || strs.length == 0) { + return ""; + } + String shortestWord = strs[0]; + for (String word : strs) { + if (shortestWord.length() > word.length()) { + shortestWord = word; + } + } + for (int i = 0; i < shortestWord.length(); i++) { + for (int j = 0; j < strs.length; j++) { + if (strs[j].charAt(i) != shortestWord.charAt(i)) { + return i == 0 ? "" : shortestWord.substring(0, i); + } + } + } + return shortestWord; + } + + /** + * Round 2: (if candidate passed warm-up round smoothly.) + * + * Suppose the given list of words are highly sorted and there're over 10 billion words. + * Design an algorithm that works efficiently. + * + * e.g. input: + * abandon + * ability + * able + * about + * above + * abroad + * absence + * absent + * absolute + * abusive + * academic + * ... + * zoo + * zyzzyva + * + * Trie should be the answer. + * + * what's the time complexity of your solution? + * what's the space complexity of your solution? + * */ + + + /** + * Round 3: (if candidate passed round 2 smoothly, this should be rare already.) + * + * What if the given list needs to support more than English characters? For instance, we have international markets like Japan, + * how do we support Japanase characters?*/ + + + public static void main(String... args) { + CirclePairing circlePairing = new CirclePairing(); + System.out.println("Hello world!"); + //String[] strs = new String[]{"flower","flow","flight"}; + String[] strs = new String[]{"dog","racecar","car"}; + System.out.println(circlePairing.longestCommonPrefix_verticalScanningVerbose(strs)); + } +} From 408f2cdd07ac8b3d7fa6b98c0ab08242b60cdf6a Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Mon, 15 Oct 2018 07:26:59 -0700 Subject: [PATCH 002/132] add Guice example --- pom.xml | 6 ++++ src/main/java/guice/AppInjector.java | 18 ++++++++++ src/main/java/guice/ClientApplication.java | 17 ++++++++++ src/main/java/guice/EmailService.java | 25 ++++++++++++++ src/main/java/guice/FacebookService.java | 12 +++++++ src/main/java/guice/HelloWorldInGuice.java | 10 ++++++ src/main/java/guice/MessageService.java | 8 +++++ src/main/java/guice/MockMessageService.java | 10 ++++++ src/main/java/guice/MyApplication.java | 27 +++++++++++++++ src/test/guice/MyApplicationTest.java | 37 +++++++++++++++++++++ 10 files changed, 170 insertions(+) create mode 100644 src/main/java/guice/AppInjector.java create mode 100644 src/main/java/guice/ClientApplication.java create mode 100644 src/main/java/guice/EmailService.java create mode 100644 src/main/java/guice/FacebookService.java create mode 100644 src/main/java/guice/HelloWorldInGuice.java create mode 100644 src/main/java/guice/MessageService.java create mode 100644 src/main/java/guice/MockMessageService.java create mode 100644 src/main/java/guice/MyApplication.java create mode 100644 src/test/guice/MyApplicationTest.java diff --git a/pom.xml b/pom.xml index 54c6535..7273573 100644 --- a/pom.xml +++ b/pom.xml @@ -112,6 +112,12 @@ 1.11.253 + + com.google.inject + guice + 3.0 + + diff --git a/src/main/java/guice/AppInjector.java b/src/main/java/guice/AppInjector.java new file mode 100644 index 0000000..fa9b01b --- /dev/null +++ b/src/main/java/guice/AppInjector.java @@ -0,0 +1,18 @@ +package guice; + +import com.google.inject.AbstractModule; + +/** + * Obviously google guice will not know which service to use, + * we have to configure it by extending AbstractModule abstract class + * and provide implementation for configure() method. + */ +public class AppInjector extends AbstractModule { + @Override protected void configure() { + //bind the service to implementation class + //bind(MessageService.class).to(EmailService.class); + + //bind MessageService to Facebook Message implementation + //bind(MessageService.class).to(FacebookService.class); + } +} diff --git a/src/main/java/guice/ClientApplication.java b/src/main/java/guice/ClientApplication.java new file mode 100644 index 0000000..474520f --- /dev/null +++ b/src/main/java/guice/ClientApplication.java @@ -0,0 +1,17 @@ +package guice; + +import com.google.inject.Guice; +import com.google.inject.Injector; + +/** + * created by stevesun on 10/11/18/. + */ +public class ClientApplication { + public static void main(String[] args) { + Injector injector = Guice.createInjector(new AppInjector()); + + MyApplication app = injector.getInstance(MyApplication.class); + + app.sendMessage("Hi Steve", "fishercoder@gmail.com"); + } +} diff --git a/src/main/java/guice/EmailService.java b/src/main/java/guice/EmailService.java new file mode 100644 index 0000000..91c89d7 --- /dev/null +++ b/src/main/java/guice/EmailService.java @@ -0,0 +1,25 @@ +package guice; + +import javax.inject.Singleton; + +/** + * EmailService is one of the implementation of MessageService. Notice that class is annotated with + * @Singleton annotation. + * + * Since service objects will be created through injector classes, this annotation is provided + * to let them know that the service classes should be singleton objects. + * + * Google Guice 3.0 added the support for JSR-330 and we can use annotations from + * com.google.inject + * or + * javax.inject package. + */ + +@Singleton +public class EmailService implements MessageService { + @Override public boolean sendMessage(String msg, String receipient) { + //some fancy code to send email + System.out.println("Email Message sent to " + receipient + " with message=" + msg); + return true; + } +} diff --git a/src/main/java/guice/FacebookService.java b/src/main/java/guice/FacebookService.java new file mode 100644 index 0000000..3721197 --- /dev/null +++ b/src/main/java/guice/FacebookService.java @@ -0,0 +1,12 @@ +package guice; + +/** + * created by stevesun on 10/11/18/. + */ +public class FacebookService implements MessageService { + @Override public boolean sendMessage(String msg, String receipient) { + //some complex code to send Facebook message + System.out.println("Message sent to Facebook user "+receipient+" with message="+msg); + return true; + } +} diff --git a/src/main/java/guice/HelloWorldInGuice.java b/src/main/java/guice/HelloWorldInGuice.java new file mode 100644 index 0000000..befbbcc --- /dev/null +++ b/src/main/java/guice/HelloWorldInGuice.java @@ -0,0 +1,10 @@ +package guice; + +/** + * created by stevesun on 10/11/18/. + */ +public class HelloWorldInGuice { + public static void main(String... args) { + System.out.println("Hello world in Guice!"); + } +} diff --git a/src/main/java/guice/MessageService.java b/src/main/java/guice/MessageService.java new file mode 100644 index 0000000..90df8ef --- /dev/null +++ b/src/main/java/guice/MessageService.java @@ -0,0 +1,8 @@ +package guice; + +/** + * created by stevesun on 10/11/18/. + */ +public interface MessageService { + boolean sendMessage(String msg, String receipient); +} diff --git a/src/main/java/guice/MockMessageService.java b/src/main/java/guice/MockMessageService.java new file mode 100644 index 0000000..1d890a7 --- /dev/null +++ b/src/main/java/guice/MockMessageService.java @@ -0,0 +1,10 @@ +package guice; + +/** + * created by stevesun on 10/11/18/. + */ +public class MockMessageService implements MessageService { + @Override public boolean sendMessage(String msg, String receipient) { + return true; + } +} diff --git a/src/main/java/guice/MyApplication.java b/src/main/java/guice/MyApplication.java new file mode 100644 index 0000000..ddd7e77 --- /dev/null +++ b/src/main/java/guice/MyApplication.java @@ -0,0 +1,27 @@ +package guice; + +import javax.inject.Inject; + +/** + * This is our application class that consumes the service looks like below. + */ +public class MyApplication { + private MessageService service; + + // constructor based injector + @Inject + public MyApplication(MessageService svc){ + this.service=svc; + } + + //setter method injector + //@Inject + //public void setService(MessageService svc) { + // this.service = svc; + //} + + public boolean sendMessage(String msg, String rec) { + //some business logic here + return service.sendMessage(msg, rec); + } +} diff --git a/src/test/guice/MyApplicationTest.java b/src/test/guice/MyApplicationTest.java new file mode 100644 index 0000000..8920606 --- /dev/null +++ b/src/test/guice/MyApplicationTest.java @@ -0,0 +1,37 @@ +package guice; + +import com.google.inject.AbstractModule; +import com.google.inject.Guice; +import com.google.inject.Injector; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class MyApplicationTest { + + private Injector injector; + + @Before + public void setUp() { + injector = Guice.createInjector(new AbstractModule() { + + @Override + protected void configure() { + bind(MessageService.class).to(MockMessageService.class); + } + }); + } + + @After + public void tearDown() { + injector = null; + } + + @Test + public void test() { + MyApplication appTest = injector.getInstance(MyApplication.class); + Assert.assertEquals(true, appTest.sendMessage("Hi Steve", "fishercoder@gmail.com")); + ; + } +} From 031ed8f6beeb156e8f2b52750e267d3798d224a4 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Mon, 15 Oct 2018 07:27:29 -0700 Subject: [PATCH 003/132] update interview question --- .../interviewQuestions/CirclePairing.java | 84 +++++++++++++++++-- 1 file changed, 78 insertions(+), 6 deletions(-) diff --git a/src/main/java/interviewQuestions/CirclePairing.java b/src/main/java/interviewQuestions/CirclePairing.java index d4f2581..b0b8bb9 100644 --- a/src/main/java/interviewQuestions/CirclePairing.java +++ b/src/main/java/interviewQuestions/CirclePairing.java @@ -2,14 +2,16 @@ public class CirclePairing { - /**warm up round: - * Given a list of words, find the longest common prefix. + /**Round 1: give two words, find the longest common prefix between the two. + * This should be super easy. Just to warm up the candidate. + * + * Round 2: what if you're given N words * * ["flower","flow","flight"] return "fl" * ["dog","racecar","car"] return "" * - * what's the time complexity of your solution? - * what's the space complexity of your solution? + * what's the time complexity of your solution? O(S) where S is all the chars in all strings, since in the worst case, all the strings are the same + * what's the space complexity of your solution? O(1) no additional space needed. * */ /**Solution 1: Horizontal scanning*/ @@ -66,7 +68,7 @@ public String longestCommonPrefix_verticalScanningVerbose(String[] strs) { } /** - * Round 2: (if candidate passed warm-up round smoothly.) + * Round 3: * * Suppose the given list of words are highly sorted and there're over 10 billion words. * Design an algorithm that works efficiently. @@ -93,14 +95,84 @@ public String longestCommonPrefix_verticalScanningVerbose(String[] strs) { * what's the space complexity of your solution? * */ + public static class Solution1 { + class TrieNode { + + char val; + boolean isWord; + TrieNode[] children = new TrieNode[26]; + + // Initialize your data structure here. + public TrieNode() { + } + + public TrieNode(char c) { + this.val = c; + } + } + + public class Trie { + private TrieNode root; + + public Trie() { + root = new TrieNode(); + root.val = ' ';//initialize root to be an empty char, this is a common practice as how Wiki defines Trie data structure as well + } + + // Inserts a word into the trie. + public void insert(String word) { + TrieNode node = root; + for (int i = 0; i < word.length(); i++) { + if (node.children[word.charAt(i) - 'a'] == null) { + node.children[word.charAt(i) - 'a'] = new TrieNode(word.charAt(i)); + } + node = node.children[word.charAt(i) - 'a']; + } + node.isWord = true; + } + + // Returns if the word is in the trie. + public boolean search(String word) { + TrieNode node = root; + for (int i = 0; i < word.length(); i++) { + if (node.children[word.charAt(i) - 'a'] == null) { + return false; + } + node = node.children[word.charAt(i) - 'a']; + } + return node.isWord; + } + + // Returns if there is any word in the trie + // that starts with the given prefix. + public boolean startsWith(String prefix) { + TrieNode node = root; + for (int i = 0; i < prefix.length(); i++) { + if (node.children[prefix.charAt(i) - 'a'] == null) { + return false; + } + node = node.children[prefix.charAt(i) - 'a']; + } + return true; + } + } + + // Your Trie object will be instantiated and called as such: + // Trie trie = new Trie(); + // trie.insert("somestring"); + // trie.search("key"); + } /** - * Round 3: (if candidate passed round 2 smoothly, this should be rare already.) + * Round 4: * * What if the given list needs to support more than English characters? For instance, we have international markets like Japan, * how do we support Japanase characters?*/ + /** Round 5: How to support constantly adding new words and removing existing words, also return longest common prefix at any given timestamp*/ + + public static void main(String... args) { CirclePairing circlePairing = new CirclePairing(); System.out.println("Hello world!"); From db5743caadd6401f08e6e6995a0eef8a4e46fbb1 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Mon, 26 Nov 2018 12:26:43 -0800 Subject: [PATCH 004/132] safe to stream on empty collection --- src/main/java/abstractClass/StreamExample.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 src/main/java/abstractClass/StreamExample.java diff --git a/src/main/java/abstractClass/StreamExample.java b/src/main/java/abstractClass/StreamExample.java new file mode 100644 index 0000000..bd5d582 --- /dev/null +++ b/src/main/java/abstractClass/StreamExample.java @@ -0,0 +1,18 @@ +package abstractClass; + +import java.util.ArrayList; +import java.util.List; + +/** + * created by stevesun on 11/26/18/. + */ +public class StreamExample { + public static void main(String... args) { + + /**This simple example shows that it's safe to run stream operation on an empty list.*/ + List list = new ArrayList<>(); + list.stream() + .map(i -> i + 1); + System.out.println("Finished."); + } +} From 22ce43cc86058adece9c3bdf6951c59864d59af4 Mon Sep 17 00:00:00 2001 From: Steve Sun Date: Sat, 7 Sep 2019 18:27:49 -0700 Subject: [PATCH 005/132] relearn Guice --- .../java/guice/relearn_2019_09/MainApp.java | 26 +++++++++++++++++++ .../guice/relearn_2019_09/SpellChecker.java | 4 +++ .../guice/relearn_2019_09/TextEditor.java | 22 ++++++++++++++++ .../relearn_2019_09/TextEditorModule.java | 20 ++++++++++++++ .../relearn_2019_09/WinWordSpellChecker.java | 4 +++ 5 files changed, 76 insertions(+) create mode 100644 src/main/java/guice/relearn_2019_09/MainApp.java create mode 100644 src/main/java/guice/relearn_2019_09/SpellChecker.java create mode 100644 src/main/java/guice/relearn_2019_09/TextEditor.java create mode 100644 src/main/java/guice/relearn_2019_09/TextEditorModule.java create mode 100644 src/main/java/guice/relearn_2019_09/WinWordSpellChecker.java diff --git a/src/main/java/guice/relearn_2019_09/MainApp.java b/src/main/java/guice/relearn_2019_09/MainApp.java new file mode 100644 index 0000000..a066191 --- /dev/null +++ b/src/main/java/guice/relearn_2019_09/MainApp.java @@ -0,0 +1,26 @@ +package guice.relearn_2019_09; + +import com.google.inject.Guice; +import com.google.inject.Injector; +import lombok.extern.slf4j.Slf4j; + +/** + * An injector is the object-graph builder + * and a Module is its core building block. + * Thus, the first step is to create an injector and then use the injector to get the objects.*/ +public class MainApp { + public static void main(String[] args) { + /* + * Guice.createInjector() takes Modules, and returns a new Injector + * instance. This method is to be called once during application startup. + */ + + Injector injector = Guice.createInjector(new TextEditorModule()); + /* + * Build object using injector + */ + TextEditor textEditor = injector.getInstance(TextEditor.class); + + System.out.println("textEditor: " + textEditor); + } +} diff --git a/src/main/java/guice/relearn_2019_09/SpellChecker.java b/src/main/java/guice/relearn_2019_09/SpellChecker.java new file mode 100644 index 0000000..7b3e3f4 --- /dev/null +++ b/src/main/java/guice/relearn_2019_09/SpellChecker.java @@ -0,0 +1,4 @@ +package guice.relearn_2019_09; + +public class SpellChecker { +} diff --git a/src/main/java/guice/relearn_2019_09/TextEditor.java b/src/main/java/guice/relearn_2019_09/TextEditor.java new file mode 100644 index 0000000..f669f92 --- /dev/null +++ b/src/main/java/guice/relearn_2019_09/TextEditor.java @@ -0,0 +1,22 @@ +package guice.relearn_2019_09; + +import javax.inject.Inject; + +public class TextEditor { + private SpellChecker spellChecker; + + /**Consider you have an application which has a text editor component and you want to provide a spell check. Your standard code would look something like this. + * Note that here we have created a dependency between the TextEditor and the SpellChecker.*/ + public TextEditor() { + spellChecker = new SpellChecker(); + } + + /**In an inversion of control scenario, we would instead do something like this: + * + * Here, the TextEditor should not worry about SpellChecker implementation. + * The SpellChecker will be implemented independently and will be provided to the TextEditor at the time of TextEditor instantiation.*/ + @Inject + public TextEditor(SpellChecker spellChecker) { + this.spellChecker = spellChecker; + } +} diff --git a/src/main/java/guice/relearn_2019_09/TextEditorModule.java b/src/main/java/guice/relearn_2019_09/TextEditorModule.java new file mode 100644 index 0000000..5b67996 --- /dev/null +++ b/src/main/java/guice/relearn_2019_09/TextEditorModule.java @@ -0,0 +1,20 @@ +package guice.relearn_2019_09; + +import com.google.inject.AbstractModule; + +/** + * Dependency Injection is controlled by the Guice Bindings. + * Guice uses bindings to map object types to their actual implementations. + * These bindings are defined a module. + * A module is a collection of bindings as shown below − + * */ +public class TextEditorModule extends AbstractModule { + @Override + protected void configure() { + /* + * Bind SpellChecker binding to WinWordSpellChecker implementation + * whenever spellChecker dependency is used. + */ + bind(SpellChecker.class).to(WinWordSpellChecker.class); + } +} diff --git a/src/main/java/guice/relearn_2019_09/WinWordSpellChecker.java b/src/main/java/guice/relearn_2019_09/WinWordSpellChecker.java new file mode 100644 index 0000000..2b3750b --- /dev/null +++ b/src/main/java/guice/relearn_2019_09/WinWordSpellChecker.java @@ -0,0 +1,4 @@ +package guice.relearn_2019_09; + +public class WinWordSpellChecker extends SpellChecker { +} From c47b1b4befb5c19fe0acb0b210b4d41c72a3c080 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Sat, 7 Sep 2019 18:33:45 -0700 Subject: [PATCH 006/132] minor change --- src/main/java/guice/relearn_2019_09/MainApp.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/main/java/guice/relearn_2019_09/MainApp.java b/src/main/java/guice/relearn_2019_09/MainApp.java index a066191..d97fcb0 100644 --- a/src/main/java/guice/relearn_2019_09/MainApp.java +++ b/src/main/java/guice/relearn_2019_09/MainApp.java @@ -2,12 +2,16 @@ import com.google.inject.Guice; import com.google.inject.Injector; -import lombok.extern.slf4j.Slf4j; /** * An injector is the object-graph builder * and a Module is its core building block. - * Thus, the first step is to create an injector and then use the injector to get the objects.*/ + * Thus, the first step is to create an injector and then use the injector to get the objects. + * + * + * In the this example, + * TextEditor class object graph is constructed by Guice and + * this graph contains TextEditor object and its dependency as WinWordSpellChecker object.*/ public class MainApp { public static void main(String[] args) { /* @@ -21,6 +25,6 @@ public static void main(String[] args) { */ TextEditor textEditor = injector.getInstance(TextEditor.class); - System.out.println("textEditor: " + textEditor); + System.out.println("textEditor is instantiated."); } } From a09477ae1473b75a44e5e998f3e9d997689032dd Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Sat, 7 Sep 2019 18:37:03 -0700 Subject: [PATCH 007/132] a simple binding --- src/main/java/guice/relearn_2019_09/MainApp.java | 1 + src/main/java/guice/relearn_2019_09/SpellChecker.java | 3 ++- src/main/java/guice/relearn_2019_09/TextEditor.java | 10 +++++++--- .../guice/relearn_2019_09/WinWordSpellChecker.java | 6 +++++- 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/main/java/guice/relearn_2019_09/MainApp.java b/src/main/java/guice/relearn_2019_09/MainApp.java index d97fcb0..d1bfcbe 100644 --- a/src/main/java/guice/relearn_2019_09/MainApp.java +++ b/src/main/java/guice/relearn_2019_09/MainApp.java @@ -24,6 +24,7 @@ public static void main(String[] args) { * Build object using injector */ TextEditor textEditor = injector.getInstance(TextEditor.class); + textEditor.makeSpellCheck(); System.out.println("textEditor is instantiated."); } diff --git a/src/main/java/guice/relearn_2019_09/SpellChecker.java b/src/main/java/guice/relearn_2019_09/SpellChecker.java index 7b3e3f4..d496bdd 100644 --- a/src/main/java/guice/relearn_2019_09/SpellChecker.java +++ b/src/main/java/guice/relearn_2019_09/SpellChecker.java @@ -1,4 +1,5 @@ package guice.relearn_2019_09; -public class SpellChecker { +public interface SpellChecker { + void checkSpelling(); } diff --git a/src/main/java/guice/relearn_2019_09/TextEditor.java b/src/main/java/guice/relearn_2019_09/TextEditor.java index f669f92..ef451cb 100644 --- a/src/main/java/guice/relearn_2019_09/TextEditor.java +++ b/src/main/java/guice/relearn_2019_09/TextEditor.java @@ -7,9 +7,9 @@ public class TextEditor { /**Consider you have an application which has a text editor component and you want to provide a spell check. Your standard code would look something like this. * Note that here we have created a dependency between the TextEditor and the SpellChecker.*/ - public TextEditor() { - spellChecker = new SpellChecker(); - } +// public TextEditor() { +// spellChecker = new SpellChecker(); +// } /**In an inversion of control scenario, we would instead do something like this: * @@ -19,4 +19,8 @@ public TextEditor() { public TextEditor(SpellChecker spellChecker) { this.spellChecker = spellChecker; } + + public void makeSpellCheck() { + spellChecker.checkSpelling(); + } } diff --git a/src/main/java/guice/relearn_2019_09/WinWordSpellChecker.java b/src/main/java/guice/relearn_2019_09/WinWordSpellChecker.java index 2b3750b..8ab2652 100644 --- a/src/main/java/guice/relearn_2019_09/WinWordSpellChecker.java +++ b/src/main/java/guice/relearn_2019_09/WinWordSpellChecker.java @@ -1,4 +1,8 @@ package guice.relearn_2019_09; -public class WinWordSpellChecker extends SpellChecker { +public class WinWordSpellChecker implements SpellChecker { + @Override + public void checkSpelling() { + System.out.println("Inside checkSpelling implementation." ); + } } From de156237a59e7bd35a49f21cc5f3d5ed76e14d15 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Sat, 7 Sep 2019 18:48:20 -0700 Subject: [PATCH 008/132] Inject using @Named annotation --- .../java/guice/relearn_2019_09/MainApp.java | 3 ++- .../guice/relearn_2019_09/TextEditor.java | 26 ++++++++++++++++--- .../relearn_2019_09/TextEditorModule.java | 2 ++ 3 files changed, 26 insertions(+), 5 deletions(-) diff --git a/src/main/java/guice/relearn_2019_09/MainApp.java b/src/main/java/guice/relearn_2019_09/MainApp.java index d1bfcbe..2beedea 100644 --- a/src/main/java/guice/relearn_2019_09/MainApp.java +++ b/src/main/java/guice/relearn_2019_09/MainApp.java @@ -24,7 +24,8 @@ public static void main(String[] args) { * Build object using injector */ TextEditor textEditor = injector.getInstance(TextEditor.class); - textEditor.makeSpellCheck(); +// textEditor.makeSpellCheck(); + textEditor.makeConnection(); System.out.println("textEditor is instantiated."); } diff --git a/src/main/java/guice/relearn_2019_09/TextEditor.java b/src/main/java/guice/relearn_2019_09/TextEditor.java index ef451cb..e1dc428 100644 --- a/src/main/java/guice/relearn_2019_09/TextEditor.java +++ b/src/main/java/guice/relearn_2019_09/TextEditor.java @@ -1,6 +1,7 @@ package guice.relearn_2019_09; import javax.inject.Inject; +import javax.inject.Named; public class TextEditor { private SpellChecker spellChecker; @@ -15,12 +16,29 @@ public class TextEditor { * * Here, the TextEditor should not worry about SpellChecker implementation. * The SpellChecker will be implemented independently and will be provided to the TextEditor at the time of TextEditor instantiation.*/ +// @Inject +// public TextEditor(SpellChecker spellChecker) { +// this.spellChecker = spellChecker; +// } +// +// public void makeSpellCheck() { +// spellChecker.checkSpelling(); +// } + + + + /** + * Inject using @Named annotation + * + * This can be achived using toInstance() method.*/ + private String dbUrl; + @Inject - public TextEditor(SpellChecker spellChecker) { - this.spellChecker = spellChecker; + public TextEditor(@Named("JDBC") String dbUrl) { + this.dbUrl = dbUrl; } - public void makeSpellCheck() { - spellChecker.checkSpelling(); + public void makeConnection() { + System.out.println(dbUrl); } } diff --git a/src/main/java/guice/relearn_2019_09/TextEditorModule.java b/src/main/java/guice/relearn_2019_09/TextEditorModule.java index 5b67996..98df6f6 100644 --- a/src/main/java/guice/relearn_2019_09/TextEditorModule.java +++ b/src/main/java/guice/relearn_2019_09/TextEditorModule.java @@ -1,6 +1,7 @@ package guice.relearn_2019_09; import com.google.inject.AbstractModule; +import com.google.inject.name.Names; /** * Dependency Injection is controlled by the Guice Bindings. @@ -16,5 +17,6 @@ protected void configure() { * whenever spellChecker dependency is used. */ bind(SpellChecker.class).to(WinWordSpellChecker.class); + bind(String.class).annotatedWith(Names.named("JDBC")).toInstance("jdbc:mysql://localhost:5326/emp"); } } From 284597baff7a2d01b0de47826493f34d741b68db Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Sat, 7 Sep 2019 18:57:18 -0700 Subject: [PATCH 009/132] separate two binding examples into their individual packages --- .../MainApp.java | 3 +- .../SpellChecker.java | 5 +++ .../named_annotation_example/TextEditor.java | 21 ++++++++++ .../TextEditorModule.java | 3 +- .../WinWordSpellChecker.java | 8 ++++ .../simple_binding_example/MainApp.java | 33 ++++++++++++++++ .../SpellChecker.java | 2 +- .../TextEditor.java | 38 ++++++------------- .../TextEditorModule.java | 20 ++++++++++ .../WinWordSpellChecker.java | 2 +- 10 files changed, 102 insertions(+), 33 deletions(-) rename src/main/java/guice/relearn_2019_09/{ => named_annotation_example}/MainApp.java (93%) create mode 100644 src/main/java/guice/relearn_2019_09/named_annotation_example/SpellChecker.java create mode 100644 src/main/java/guice/relearn_2019_09/named_annotation_example/TextEditor.java rename src/main/java/guice/relearn_2019_09/{ => named_annotation_example}/TextEditorModule.java (87%) create mode 100644 src/main/java/guice/relearn_2019_09/named_annotation_example/WinWordSpellChecker.java create mode 100644 src/main/java/guice/relearn_2019_09/simple_binding_example/MainApp.java rename src/main/java/guice/relearn_2019_09/{ => simple_binding_example}/SpellChecker.java (53%) rename src/main/java/guice/relearn_2019_09/{ => simple_binding_example}/TextEditor.java (52%) create mode 100644 src/main/java/guice/relearn_2019_09/simple_binding_example/TextEditorModule.java rename src/main/java/guice/relearn_2019_09/{ => simple_binding_example}/WinWordSpellChecker.java (77%) diff --git a/src/main/java/guice/relearn_2019_09/MainApp.java b/src/main/java/guice/relearn_2019_09/named_annotation_example/MainApp.java similarity index 93% rename from src/main/java/guice/relearn_2019_09/MainApp.java rename to src/main/java/guice/relearn_2019_09/named_annotation_example/MainApp.java index 2beedea..14d34f2 100644 --- a/src/main/java/guice/relearn_2019_09/MainApp.java +++ b/src/main/java/guice/relearn_2019_09/named_annotation_example/MainApp.java @@ -1,4 +1,4 @@ -package guice.relearn_2019_09; +package guice.relearn_2019_09.named_annotation_example; import com.google.inject.Guice; import com.google.inject.Injector; @@ -24,7 +24,6 @@ public static void main(String[] args) { * Build object using injector */ TextEditor textEditor = injector.getInstance(TextEditor.class); -// textEditor.makeSpellCheck(); textEditor.makeConnection(); System.out.println("textEditor is instantiated."); diff --git a/src/main/java/guice/relearn_2019_09/named_annotation_example/SpellChecker.java b/src/main/java/guice/relearn_2019_09/named_annotation_example/SpellChecker.java new file mode 100644 index 0000000..0cf5f77 --- /dev/null +++ b/src/main/java/guice/relearn_2019_09/named_annotation_example/SpellChecker.java @@ -0,0 +1,5 @@ +package guice.relearn_2019_09.named_annotation_example; + +public interface SpellChecker { + void checkSpelling(); +} diff --git a/src/main/java/guice/relearn_2019_09/named_annotation_example/TextEditor.java b/src/main/java/guice/relearn_2019_09/named_annotation_example/TextEditor.java new file mode 100644 index 0000000..59d1d68 --- /dev/null +++ b/src/main/java/guice/relearn_2019_09/named_annotation_example/TextEditor.java @@ -0,0 +1,21 @@ +package guice.relearn_2019_09.named_annotation_example; + +import javax.inject.Inject; +import javax.inject.Named; + +public class TextEditor { + /** + * Inject using @Named annotation + * + * This can be achived using toInstance() method.*/ + private String dbUrl; + + @Inject + public TextEditor(@Named("JDBC") String dbUrl) { + this.dbUrl = dbUrl; + } + + public void makeConnection() { + System.out.println(dbUrl); + } +} diff --git a/src/main/java/guice/relearn_2019_09/TextEditorModule.java b/src/main/java/guice/relearn_2019_09/named_annotation_example/TextEditorModule.java similarity index 87% rename from src/main/java/guice/relearn_2019_09/TextEditorModule.java rename to src/main/java/guice/relearn_2019_09/named_annotation_example/TextEditorModule.java index 98df6f6..85226ac 100644 --- a/src/main/java/guice/relearn_2019_09/TextEditorModule.java +++ b/src/main/java/guice/relearn_2019_09/named_annotation_example/TextEditorModule.java @@ -1,4 +1,4 @@ -package guice.relearn_2019_09; +package guice.relearn_2019_09.named_annotation_example; import com.google.inject.AbstractModule; import com.google.inject.name.Names; @@ -16,7 +16,6 @@ protected void configure() { * Bind SpellChecker binding to WinWordSpellChecker implementation * whenever spellChecker dependency is used. */ - bind(SpellChecker.class).to(WinWordSpellChecker.class); bind(String.class).annotatedWith(Names.named("JDBC")).toInstance("jdbc:mysql://localhost:5326/emp"); } } diff --git a/src/main/java/guice/relearn_2019_09/named_annotation_example/WinWordSpellChecker.java b/src/main/java/guice/relearn_2019_09/named_annotation_example/WinWordSpellChecker.java new file mode 100644 index 0000000..ef0c4df --- /dev/null +++ b/src/main/java/guice/relearn_2019_09/named_annotation_example/WinWordSpellChecker.java @@ -0,0 +1,8 @@ +package guice.relearn_2019_09.named_annotation_example; + +public class WinWordSpellChecker implements SpellChecker { + @Override + public void checkSpelling() { + System.out.println("Inside checkSpelling implementation." ); + } +} diff --git a/src/main/java/guice/relearn_2019_09/simple_binding_example/MainApp.java b/src/main/java/guice/relearn_2019_09/simple_binding_example/MainApp.java new file mode 100644 index 0000000..cb1c09e --- /dev/null +++ b/src/main/java/guice/relearn_2019_09/simple_binding_example/MainApp.java @@ -0,0 +1,33 @@ +package guice.relearn_2019_09.simple_binding_example; + +import com.google.inject.Guice; +import com.google.inject.Injector; +import guice.relearn_2019_09.named_annotation_example.TextEditor; +import guice.relearn_2019_09.named_annotation_example.TextEditorModule; + +/** + * An injector is the object-graph builder + * and a Module is its core building block. + * Thus, the first step is to create an injector and then use the injector to get the objects. + * + * + * In the this example, + * TextEditor class object graph is constructed by Guice and + * this graph contains TextEditor object and its dependency as WinWordSpellChecker object.*/ +public class MainApp { + public static void main(String[] args) { + /* + * Guice.createInjector() takes Modules, and returns a new Injector + * instance. This method is to be called once during application startup. + */ + + Injector injector = Guice.createInjector(new TextEditorModule()); + /* + * Build object using injector + */ + TextEditor textEditor = injector.getInstance(TextEditor.class); + textEditor.makeConnection(); + + System.out.println("textEditor is instantiated."); + } +} diff --git a/src/main/java/guice/relearn_2019_09/SpellChecker.java b/src/main/java/guice/relearn_2019_09/simple_binding_example/SpellChecker.java similarity index 53% rename from src/main/java/guice/relearn_2019_09/SpellChecker.java rename to src/main/java/guice/relearn_2019_09/simple_binding_example/SpellChecker.java index d496bdd..c8b1a62 100644 --- a/src/main/java/guice/relearn_2019_09/SpellChecker.java +++ b/src/main/java/guice/relearn_2019_09/simple_binding_example/SpellChecker.java @@ -1,4 +1,4 @@ -package guice.relearn_2019_09; +package guice.relearn_2019_09.simple_binding_example; public interface SpellChecker { void checkSpelling(); diff --git a/src/main/java/guice/relearn_2019_09/TextEditor.java b/src/main/java/guice/relearn_2019_09/simple_binding_example/TextEditor.java similarity index 52% rename from src/main/java/guice/relearn_2019_09/TextEditor.java rename to src/main/java/guice/relearn_2019_09/simple_binding_example/TextEditor.java index e1dc428..e56c628 100644 --- a/src/main/java/guice/relearn_2019_09/TextEditor.java +++ b/src/main/java/guice/relearn_2019_09/simple_binding_example/TextEditor.java @@ -1,7 +1,6 @@ -package guice.relearn_2019_09; +package guice.relearn_2019_09.simple_binding_example; import javax.inject.Inject; -import javax.inject.Named; public class TextEditor { private SpellChecker spellChecker; @@ -12,33 +11,18 @@ public class TextEditor { // spellChecker = new SpellChecker(); // } - /**In an inversion of control scenario, we would instead do something like this: - * - * Here, the TextEditor should not worry about SpellChecker implementation. - * The SpellChecker will be implemented independently and will be provided to the TextEditor at the time of TextEditor instantiation.*/ -// @Inject -// public TextEditor(SpellChecker spellChecker) { -// this.spellChecker = spellChecker; -// } -// -// public void makeSpellCheck() { -// spellChecker.checkSpelling(); -// } - - - /** - * Inject using @Named annotation - * - * This can be achived using toInstance() method.*/ - private String dbUrl; - + * In an inversion of control scenario, we would instead do something like this: + *

+ * Here, the TextEditor should not worry about SpellChecker implementation. + * The SpellChecker will be implemented independently and will be provided to the TextEditor at the time of TextEditor instantiation. + */ @Inject - public TextEditor(@Named("JDBC") String dbUrl) { - this.dbUrl = dbUrl; + public TextEditor(SpellChecker spellChecker) { + this.spellChecker = spellChecker; } - public void makeConnection() { - System.out.println(dbUrl); + public void makeSpellCheck() { + spellChecker.checkSpelling(); } -} +} \ No newline at end of file diff --git a/src/main/java/guice/relearn_2019_09/simple_binding_example/TextEditorModule.java b/src/main/java/guice/relearn_2019_09/simple_binding_example/TextEditorModule.java new file mode 100644 index 0000000..9b77dcd --- /dev/null +++ b/src/main/java/guice/relearn_2019_09/simple_binding_example/TextEditorModule.java @@ -0,0 +1,20 @@ +package guice.relearn_2019_09.simple_binding_example; + +import com.google.inject.AbstractModule; + +/** + * Dependency Injection is controlled by the Guice Bindings. + * Guice uses bindings to map object types to their actual implementations. + * These bindings are defined a module. + * A module is a collection of bindings as shown below − + * */ +public class TextEditorModule extends AbstractModule { + @Override + protected void configure() { + /* + * Bind SpellChecker binding to WinWordSpellChecker implementation + * whenever spellChecker dependency is used. + */ + bind(SpellChecker.class).to(WinWordSpellChecker.class); + } +} diff --git a/src/main/java/guice/relearn_2019_09/WinWordSpellChecker.java b/src/main/java/guice/relearn_2019_09/simple_binding_example/WinWordSpellChecker.java similarity index 77% rename from src/main/java/guice/relearn_2019_09/WinWordSpellChecker.java rename to src/main/java/guice/relearn_2019_09/simple_binding_example/WinWordSpellChecker.java index 8ab2652..cd841f0 100644 --- a/src/main/java/guice/relearn_2019_09/WinWordSpellChecker.java +++ b/src/main/java/guice/relearn_2019_09/simple_binding_example/WinWordSpellChecker.java @@ -1,4 +1,4 @@ -package guice.relearn_2019_09; +package guice.relearn_2019_09.simple_binding_example; public class WinWordSpellChecker implements SpellChecker { @Override From 58bf1680fa869828319a20331dfef9221be0c323 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Sun, 8 Sep 2019 09:36:47 -0700 Subject: [PATCH 010/132] rename packages --- .../MainApp.java | 6 +++--- .../SpellChecker.java | 2 +- .../TextEditor.java | 2 +- .../TextEditorModule.java | 2 +- .../WinWordSpellChecker.java | 2 +- .../MainApp.java | 2 +- .../SpellChecker.java | 2 +- .../TextEditor.java | 2 +- .../TextEditorModule.java | 2 +- .../WinWordSpellChecker.java | 2 +- 10 files changed, 12 insertions(+), 12 deletions(-) rename src/main/java/guice/relearn_2019_09/{simple_binding_example => _1_simple_binding_example}/MainApp.java (83%) rename src/main/java/guice/relearn_2019_09/{simple_binding_example => _1_simple_binding_example}/SpellChecker.java (51%) rename src/main/java/guice/relearn_2019_09/{simple_binding_example => _1_simple_binding_example}/TextEditor.java (94%) rename src/main/java/guice/relearn_2019_09/{simple_binding_example => _1_simple_binding_example}/TextEditorModule.java (91%) rename src/main/java/guice/relearn_2019_09/{named_annotation_example => _1_simple_binding_example}/WinWordSpellChecker.java (76%) rename src/main/java/guice/relearn_2019_09/{named_annotation_example => _2_named_annotation_example}/MainApp.java (94%) rename src/main/java/guice/relearn_2019_09/{named_annotation_example => _2_named_annotation_example}/SpellChecker.java (50%) rename src/main/java/guice/relearn_2019_09/{named_annotation_example => _2_named_annotation_example}/TextEditor.java (87%) rename src/main/java/guice/relearn_2019_09/{named_annotation_example => _2_named_annotation_example}/TextEditorModule.java (92%) rename src/main/java/guice/relearn_2019_09/{simple_binding_example => _2_named_annotation_example}/WinWordSpellChecker.java (75%) diff --git a/src/main/java/guice/relearn_2019_09/simple_binding_example/MainApp.java b/src/main/java/guice/relearn_2019_09/_1_simple_binding_example/MainApp.java similarity index 83% rename from src/main/java/guice/relearn_2019_09/simple_binding_example/MainApp.java rename to src/main/java/guice/relearn_2019_09/_1_simple_binding_example/MainApp.java index cb1c09e..bf2f5fa 100644 --- a/src/main/java/guice/relearn_2019_09/simple_binding_example/MainApp.java +++ b/src/main/java/guice/relearn_2019_09/_1_simple_binding_example/MainApp.java @@ -1,9 +1,9 @@ -package guice.relearn_2019_09.simple_binding_example; +package guice.relearn_2019_09._1_simple_binding_example; import com.google.inject.Guice; import com.google.inject.Injector; -import guice.relearn_2019_09.named_annotation_example.TextEditor; -import guice.relearn_2019_09.named_annotation_example.TextEditorModule; +import guice.relearn_2019_09._2_named_annotation_example.TextEditor; +import guice.relearn_2019_09._2_named_annotation_example.TextEditorModule; /** * An injector is the object-graph builder diff --git a/src/main/java/guice/relearn_2019_09/simple_binding_example/SpellChecker.java b/src/main/java/guice/relearn_2019_09/_1_simple_binding_example/SpellChecker.java similarity index 51% rename from src/main/java/guice/relearn_2019_09/simple_binding_example/SpellChecker.java rename to src/main/java/guice/relearn_2019_09/_1_simple_binding_example/SpellChecker.java index c8b1a62..7145329 100644 --- a/src/main/java/guice/relearn_2019_09/simple_binding_example/SpellChecker.java +++ b/src/main/java/guice/relearn_2019_09/_1_simple_binding_example/SpellChecker.java @@ -1,4 +1,4 @@ -package guice.relearn_2019_09.simple_binding_example; +package guice.relearn_2019_09._1_simple_binding_example; public interface SpellChecker { void checkSpelling(); diff --git a/src/main/java/guice/relearn_2019_09/simple_binding_example/TextEditor.java b/src/main/java/guice/relearn_2019_09/_1_simple_binding_example/TextEditor.java similarity index 94% rename from src/main/java/guice/relearn_2019_09/simple_binding_example/TextEditor.java rename to src/main/java/guice/relearn_2019_09/_1_simple_binding_example/TextEditor.java index e56c628..b09efd5 100644 --- a/src/main/java/guice/relearn_2019_09/simple_binding_example/TextEditor.java +++ b/src/main/java/guice/relearn_2019_09/_1_simple_binding_example/TextEditor.java @@ -1,4 +1,4 @@ -package guice.relearn_2019_09.simple_binding_example; +package guice.relearn_2019_09._1_simple_binding_example; import javax.inject.Inject; diff --git a/src/main/java/guice/relearn_2019_09/simple_binding_example/TextEditorModule.java b/src/main/java/guice/relearn_2019_09/_1_simple_binding_example/TextEditorModule.java similarity index 91% rename from src/main/java/guice/relearn_2019_09/simple_binding_example/TextEditorModule.java rename to src/main/java/guice/relearn_2019_09/_1_simple_binding_example/TextEditorModule.java index 9b77dcd..64f16ca 100644 --- a/src/main/java/guice/relearn_2019_09/simple_binding_example/TextEditorModule.java +++ b/src/main/java/guice/relearn_2019_09/_1_simple_binding_example/TextEditorModule.java @@ -1,4 +1,4 @@ -package guice.relearn_2019_09.simple_binding_example; +package guice.relearn_2019_09._1_simple_binding_example; import com.google.inject.AbstractModule; diff --git a/src/main/java/guice/relearn_2019_09/named_annotation_example/WinWordSpellChecker.java b/src/main/java/guice/relearn_2019_09/_1_simple_binding_example/WinWordSpellChecker.java similarity index 76% rename from src/main/java/guice/relearn_2019_09/named_annotation_example/WinWordSpellChecker.java rename to src/main/java/guice/relearn_2019_09/_1_simple_binding_example/WinWordSpellChecker.java index ef0c4df..e4e85b1 100644 --- a/src/main/java/guice/relearn_2019_09/named_annotation_example/WinWordSpellChecker.java +++ b/src/main/java/guice/relearn_2019_09/_1_simple_binding_example/WinWordSpellChecker.java @@ -1,4 +1,4 @@ -package guice.relearn_2019_09.named_annotation_example; +package guice.relearn_2019_09._1_simple_binding_example; public class WinWordSpellChecker implements SpellChecker { @Override diff --git a/src/main/java/guice/relearn_2019_09/named_annotation_example/MainApp.java b/src/main/java/guice/relearn_2019_09/_2_named_annotation_example/MainApp.java similarity index 94% rename from src/main/java/guice/relearn_2019_09/named_annotation_example/MainApp.java rename to src/main/java/guice/relearn_2019_09/_2_named_annotation_example/MainApp.java index 14d34f2..925b2a6 100644 --- a/src/main/java/guice/relearn_2019_09/named_annotation_example/MainApp.java +++ b/src/main/java/guice/relearn_2019_09/_2_named_annotation_example/MainApp.java @@ -1,4 +1,4 @@ -package guice.relearn_2019_09.named_annotation_example; +package guice.relearn_2019_09._2_named_annotation_example; import com.google.inject.Guice; import com.google.inject.Injector; diff --git a/src/main/java/guice/relearn_2019_09/named_annotation_example/SpellChecker.java b/src/main/java/guice/relearn_2019_09/_2_named_annotation_example/SpellChecker.java similarity index 50% rename from src/main/java/guice/relearn_2019_09/named_annotation_example/SpellChecker.java rename to src/main/java/guice/relearn_2019_09/_2_named_annotation_example/SpellChecker.java index 0cf5f77..6b878ea 100644 --- a/src/main/java/guice/relearn_2019_09/named_annotation_example/SpellChecker.java +++ b/src/main/java/guice/relearn_2019_09/_2_named_annotation_example/SpellChecker.java @@ -1,4 +1,4 @@ -package guice.relearn_2019_09.named_annotation_example; +package guice.relearn_2019_09._2_named_annotation_example; public interface SpellChecker { void checkSpelling(); diff --git a/src/main/java/guice/relearn_2019_09/named_annotation_example/TextEditor.java b/src/main/java/guice/relearn_2019_09/_2_named_annotation_example/TextEditor.java similarity index 87% rename from src/main/java/guice/relearn_2019_09/named_annotation_example/TextEditor.java rename to src/main/java/guice/relearn_2019_09/_2_named_annotation_example/TextEditor.java index 59d1d68..f08a32c 100644 --- a/src/main/java/guice/relearn_2019_09/named_annotation_example/TextEditor.java +++ b/src/main/java/guice/relearn_2019_09/_2_named_annotation_example/TextEditor.java @@ -1,4 +1,4 @@ -package guice.relearn_2019_09.named_annotation_example; +package guice.relearn_2019_09._2_named_annotation_example; import javax.inject.Inject; import javax.inject.Named; diff --git a/src/main/java/guice/relearn_2019_09/named_annotation_example/TextEditorModule.java b/src/main/java/guice/relearn_2019_09/_2_named_annotation_example/TextEditorModule.java similarity index 92% rename from src/main/java/guice/relearn_2019_09/named_annotation_example/TextEditorModule.java rename to src/main/java/guice/relearn_2019_09/_2_named_annotation_example/TextEditorModule.java index 85226ac..0d0bac2 100644 --- a/src/main/java/guice/relearn_2019_09/named_annotation_example/TextEditorModule.java +++ b/src/main/java/guice/relearn_2019_09/_2_named_annotation_example/TextEditorModule.java @@ -1,4 +1,4 @@ -package guice.relearn_2019_09.named_annotation_example; +package guice.relearn_2019_09._2_named_annotation_example; import com.google.inject.AbstractModule; import com.google.inject.name.Names; diff --git a/src/main/java/guice/relearn_2019_09/simple_binding_example/WinWordSpellChecker.java b/src/main/java/guice/relearn_2019_09/_2_named_annotation_example/WinWordSpellChecker.java similarity index 75% rename from src/main/java/guice/relearn_2019_09/simple_binding_example/WinWordSpellChecker.java rename to src/main/java/guice/relearn_2019_09/_2_named_annotation_example/WinWordSpellChecker.java index cd841f0..cfa504f 100644 --- a/src/main/java/guice/relearn_2019_09/simple_binding_example/WinWordSpellChecker.java +++ b/src/main/java/guice/relearn_2019_09/_2_named_annotation_example/WinWordSpellChecker.java @@ -1,4 +1,4 @@ -package guice.relearn_2019_09.simple_binding_example; +package guice.relearn_2019_09._2_named_annotation_example; public class WinWordSpellChecker implements SpellChecker { @Override From 801ed189cb36020f45c4bfaa9bc5fcb1fc680934 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Sun, 8 Sep 2019 12:33:54 -0700 Subject: [PATCH 011/132] add @Provides annotation example --- .../GuiceTester.java | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 src/main/java/guice/relearn_2019_09/_3_provides_annotation_example/GuiceTester.java diff --git a/src/main/java/guice/relearn_2019_09/_3_provides_annotation_example/GuiceTester.java b/src/main/java/guice/relearn_2019_09/_3_provides_annotation_example/GuiceTester.java new file mode 100644 index 0000000..30576f1 --- /dev/null +++ b/src/main/java/guice/relearn_2019_09/_3_provides_annotation_example/GuiceTester.java @@ -0,0 +1,83 @@ +package guice.relearn_2019_09._3_provides_annotation_example; + +import com.google.inject.AbstractModule; +import com.google.inject.Guice; +import com.google.inject.Injector; +import com.google.inject.Provides; + +import javax.inject.Inject; + +/** + * Guice provides a way to create bindings with complex objects using @provides method. + * + * This method is being part of Binding Module and provides the complex object to be mapped. + * + * See the complete example below.*/ +public class GuiceTester { + public static void main(String[] args) { + Injector injector = Guice.createInjector(new TextEditorModule()); + TextEditor editor = injector.getInstance(TextEditor.class); + editor.makeSpellCheck(); + System.out.println("Program ended."); + } +} + +class TextEditor { + private SpellChecker spellChecker; + + @Inject + public TextEditor(SpellChecker spellChecker) { + this.spellChecker = spellChecker; + } + + public void makeSpellCheck() { + spellChecker.checkSpelling(); + } +} + +//Binding Module +class TextEditorModule extends AbstractModule { + @Override + protected void configure() { + } + + @Provides + public SpellChecker provideSpellChecker() { + String dbUrl = "jdbc:mysql://localhost:5326/emp"; + String user = "user"; + int timeout = 100; + + SpellChecker SpellChecker = new SpellCheckerImpl(dbUrl, user, timeout); + return SpellChecker; + } +} + +//spell checker interface +interface SpellChecker { + public void checkSpelling(); +} + +//spell checker implementation +class SpellCheckerImpl implements SpellChecker { + + private String dbUrl; + private String user; + private Integer timeout; + + @Inject + public SpellCheckerImpl(String dbUrl, + String user, + Integer timeout) { + this.dbUrl = dbUrl; + this.user = user; + this.timeout = timeout; + } + + @Override + public void checkSpelling() { + System.out.println("Inside checkSpelling."); + System.out.println(dbUrl); + System.out.println(user); + System.out.println(timeout); + } +} From 88cb11bc5e9f3db64ed2151bfead408b48d6b99d Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Sun, 8 Sep 2019 12:48:54 -0700 Subject: [PATCH 012/132] add provider class example --- .../GuiceTester.java | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 src/main/java/guice/relearn_2019_09/_4_provider_class_example/GuiceTester.java diff --git a/src/main/java/guice/relearn_2019_09/_4_provider_class_example/GuiceTester.java b/src/main/java/guice/relearn_2019_09/_4_provider_class_example/GuiceTester.java new file mode 100644 index 0000000..c5305eb --- /dev/null +++ b/src/main/java/guice/relearn_2019_09/_4_provider_class_example/GuiceTester.java @@ -0,0 +1,84 @@ +package guice.relearn_2019_09._4_provider_class_example; + +import com.google.inject.AbstractModule; +import com.google.inject.Guice; +import com.google.inject.Injector; +import com.google.inject.Provider; + +import javax.inject.Inject; + +/** + * As @provides method becomes more complex, this method can be moved to separate classes using Provider interface. + * */ +public class GuiceTester { + public static void main(String[] args) { + Injector injector = Guice.createInjector(new TextEditorModule()); + TextEditor editor = injector.getInstance(TextEditor.class); + editor.makeSpellCheck(); + System.out.println("Program ended."); + } +} + +class TextEditor { + private SpellChecker spellChecker; + + @Inject + public TextEditor(SpellChecker spellChecker) { + this.spellChecker = spellChecker; + } + + public void makeSpellCheck() { + spellChecker.checkSpelling(); + } +} + +//Binding Module +class TextEditorModule extends AbstractModule { + /**you have to map the provider to type.*/ + @Override + protected void configure() { + bind(SpellChecker.class).toProvider(SpellCheckerProvider.class); + } +} + +//spell checker interface +interface SpellChecker { + public void checkSpelling(); +} + +//spell checker implementation +class SpellCheckerImpl implements SpellChecker { + + private String dbUrl; + private String user; + private Integer timeout; + + @Inject + public SpellCheckerImpl(String dbUrl, + String user, + Integer timeout) { + this.dbUrl = dbUrl; + this.user = user; + this.timeout = timeout; + } + + @Override + public void checkSpelling() { + System.out.println("Inside checkSpelling."); + System.out.println(dbUrl); + System.out.println(user); + System.out.println(timeout); + } +} + +class SpellCheckerProvider implements Provider { + @Override + public SpellChecker get() { + String dbUrl = "jdbc:mysql://localhost:5326/emp"; + String user = "user"; + int timeout = 100; + + SpellChecker SpellChecker = new SpellCheckerImpl(dbUrl, user, timeout); + return SpellChecker; + } +} From 502128a5fc959b39911f69cdfdee4111c5dea959 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Sun, 8 Sep 2019 12:53:14 -0700 Subject: [PATCH 013/132] add constructor binding example --- .../GuiceTester.java | 71 +++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 src/main/java/guice/relearn_2019_09/_5_constructor_binding_example/GuiceTester.java diff --git a/src/main/java/guice/relearn_2019_09/_5_constructor_binding_example/GuiceTester.java b/src/main/java/guice/relearn_2019_09/_5_constructor_binding_example/GuiceTester.java new file mode 100644 index 0000000..465f239 --- /dev/null +++ b/src/main/java/guice/relearn_2019_09/_5_constructor_binding_example/GuiceTester.java @@ -0,0 +1,71 @@ +package guice.relearn_2019_09._5_constructor_binding_example; + +import com.google.inject.AbstractModule; +import com.google.inject.Guice; +import com.google.inject.Inject; +import com.google.inject.Injector; +import com.google.inject.name.Named; +import com.google.inject.name.Names; + +/** + * Guice provides a way to create bindings with specific constructor of an object using toConstructor() method. + */ +public class GuiceTester { + public static void main(String[] args) { + Injector injector = Guice.createInjector(new TextEditorModule()); + TextEditor editor = injector.getInstance(TextEditor.class); + editor.makeSpellCheck(); + } +} + +class TextEditor { + private SpellChecker spellChecker; + + @Inject + public TextEditor(SpellChecker spellChecker) { + this.spellChecker = spellChecker; + } + + public void makeSpellCheck() { + spellChecker.checkSpelling(); + } +} + +//Binding Module +class TextEditorModule extends AbstractModule { + @Override + protected void configure() { + try { + bind(SpellChecker.class).toConstructor(SpellCheckerImpl.class.getConstructor(String.class)); + } catch (NoSuchMethodException | SecurityException e) { + System.out.println("Required constructor missing"); + } + + bind(String.class).annotatedWith(Names.named("JDBC")).toInstance("jdbc:mysql://localhost:5326/emp"); + } +} + +//spell checker interface +interface SpellChecker { + public void checkSpelling(); +} + +//spell checker implementation +class SpellCheckerImpl implements SpellChecker { + private String dbUrl; + + public SpellCheckerImpl() { + System.out.println("In default constructor."); + } + + public SpellCheckerImpl(@Named("JDBC") String dbUrl) { + this.dbUrl = dbUrl; + System.out.println("In constructor with a string param."); + } + + @Override + public void checkSpelling() { + System.out.println("Inside checkSpelling."); + System.out.println(dbUrl); + } +} From bd57780367c3d69b3bf3bed4949e1ab5cd3335da Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Sun, 8 Sep 2019 13:06:36 -0700 Subject: [PATCH 014/132] add method injection example --- .../GuiceTester.java | 71 +++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 src/main/java/guice/relearn_2019_09/_6_method_injection_example/GuiceTester.java diff --git a/src/main/java/guice/relearn_2019_09/_6_method_injection_example/GuiceTester.java b/src/main/java/guice/relearn_2019_09/_6_method_injection_example/GuiceTester.java new file mode 100644 index 0000000..50cfd3a --- /dev/null +++ b/src/main/java/guice/relearn_2019_09/_6_method_injection_example/GuiceTester.java @@ -0,0 +1,71 @@ +package guice.relearn_2019_09._6_method_injection_example; + +import com.google.inject.AbstractModule; +import com.google.inject.Guice; +import com.google.inject.ImplementedBy; +import com.google.inject.Inject; +import com.google.inject.Injector; +import com.google.inject.name.Named; +import com.google.inject.name.Names; + +/** + * Injection is a process of injecting dependency into an object. + * Method injection is used to set value object as dependency to the object. + * + * Observe the example given below. + * */ +public class GuiceTester { + public static void main(String[] args) { + Injector injector = Guice.createInjector(new TextEditorModule()); + TextEditor editor = injector.getInstance(TextEditor.class); + editor.makeSpellCheck(); + System.out.println("Program ended."); + } +} + +class TextEditor { + private SpellChecker spellChecker; + + @Inject + public TextEditor(SpellChecker spellChecker) { + this.spellChecker = spellChecker; + } + + public void makeSpellCheck() { + spellChecker.checkSpelling(); + } +} + +//Binding Module +class TextEditorModule extends AbstractModule { + @Override + protected void configure() { + bind(String.class) + .annotatedWith(Names.named("JDBC")) + .toInstance("jdbc:mysql://localhost:5326/emp"); + } +} + +@ImplementedBy(SpellCheckerImpl.class) +interface SpellChecker { + public void checkSpelling(); +} + +//spell checker implementation +class SpellCheckerImpl implements SpellChecker { + private String dbUrl; + + public SpellCheckerImpl() { + } + + @Inject + public void setDbUrl(@Named("JDBC") String dbUrl) { + this.dbUrl = dbUrl; + } + + @Override + public void checkSpelling() { + System.out.println("Inside checkSpelling."); + System.out.println(dbUrl); + } +} From 5b73351632d3b5d130b5fc8a1e8f602bd17d1e36 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Sun, 8 Sep 2019 13:14:52 -0700 Subject: [PATCH 015/132] add singleton scope example --- .../_7_scope_example/GuiceTester.java | 89 +++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 src/main/java/guice/relearn_2019_09/_7_scope_example/GuiceTester.java diff --git a/src/main/java/guice/relearn_2019_09/_7_scope_example/GuiceTester.java b/src/main/java/guice/relearn_2019_09/_7_scope_example/GuiceTester.java new file mode 100644 index 0000000..8d47369 --- /dev/null +++ b/src/main/java/guice/relearn_2019_09/_7_scope_example/GuiceTester.java @@ -0,0 +1,89 @@ +package guice.relearn_2019_09._7_scope_example; + +import com.google.inject.AbstractModule; +import com.google.inject.Guice; +import com.google.inject.Inject; +import com.google.inject.Injector; +import com.google.inject.Singleton; + +import static org.junit.Assert.assertEquals; + +/** + * Guice returns a new instance every time it supplies a value as its DEFAULT behavior. + * It is configurable via scopes. The various scopes that Guice supports are − + * + * @Singleton − Single instance for lifetime of the application. @Singleton object needs to be threadsafe. + * @SessionScoped − Single instance for a particular session of the web application. @SessionScoped object needs to be threadsafe. + * @RequestScoped − Single instance for a particular request of the web application. @RequestScoped object does not need to be threadsafe. + */ +public class GuiceTester { + public static void main(String[] args) { + Injector injector = Guice.createInjector(new TextEditorModule()); + SpellChecker spellChecker = new SpellCheckerImpl(); + injector.injectMembers(spellChecker); + + TextEditor editor = injector.getInstance(TextEditor.class); + double id = editor.getSpellCheckerId(); + System.out.println(id); + + TextEditor editor1 = injector.getInstance(TextEditor.class); + double id1 = editor1.getSpellCheckerId(); + System.out.println(id1); + + /**Because it's a singleton, so these two values will be the same.*/ + assertEquals(0, id, id1); + } +} + +class TextEditor { + private SpellChecker spellChecker; + + @Inject + public void setSpellChecker(SpellChecker spellChecker) { + this.spellChecker = spellChecker; + } + + public TextEditor() { + } + + public void makeSpellCheck() { + spellChecker.checkSpelling(); + } + + public double getSpellCheckerId() { + return spellChecker.getId(); + } +} + +//Binding Module +class TextEditorModule extends AbstractModule { + @Override + protected void configure() { + bind(SpellChecker.class).to(SpellCheckerImpl.class); + } +} + +interface SpellChecker { + public double getId(); + + public void checkSpelling(); +} + +@Singleton +class SpellCheckerImpl implements SpellChecker { + double id; + + public SpellCheckerImpl() { + id = Math.random(); + } + + @Override + public void checkSpelling() { + System.out.println("Inside checkSpelling."); + } + + @Override + public double getId() { + return id; + } +} From 4332b6cd2ab0511b15439d9a229035f8cc8870b7 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Sun, 8 Sep 2019 13:19:28 -0700 Subject: [PATCH 016/132] method name doesn't impact method injection --- .../_6_method_injection_example/GuiceTester.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/guice/relearn_2019_09/_6_method_injection_example/GuiceTester.java b/src/main/java/guice/relearn_2019_09/_6_method_injection_example/GuiceTester.java index 50cfd3a..e649cb4 100644 --- a/src/main/java/guice/relearn_2019_09/_6_method_injection_example/GuiceTester.java +++ b/src/main/java/guice/relearn_2019_09/_6_method_injection_example/GuiceTester.java @@ -58,8 +58,9 @@ class SpellCheckerImpl implements SpellChecker { public SpellCheckerImpl() { } + //the method name does not impact injection @Inject - public void setDbUrl(@Named("JDBC") String dbUrl) { + public void helloWorldSetDbUrl(@Named("JDBC") String dbUrl) { this.dbUrl = dbUrl; } From bcd1419ca6edc092d8f6682babfecd174eada0cc Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Wed, 11 Sep 2019 07:02:13 -0700 Subject: [PATCH 017/132] ObjectMapper parse tree example --- .../ObjectMapperExample.java | 73 +++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 src/main/java/object_mapper_example/ObjectMapperExample.java diff --git a/src/main/java/object_mapper_example/ObjectMapperExample.java b/src/main/java/object_mapper_example/ObjectMapperExample.java new file mode 100644 index 0000000..bcbc344 --- /dev/null +++ b/src/main/java/object_mapper_example/ObjectMapperExample.java @@ -0,0 +1,73 @@ +package object_mapper_example; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.io.IOException; + +import static org.junit.Assert.assertNotNull; + +public class ObjectMapperExample { + public static void main(String... args) throws IOException { + System.out.println("Hello world!"); + String str = "{\n" + + " \"Records\": [\n" + + " {\n" + + " \"eventVersion\": \"2.1\",\n" + + " \"eventSource\": \"aws:s3\",\n" + + " \"awsRegion\": \"us-east-1\",\n" + + " \"eventTime\": \"2019-09-10T23:02:48.052Z\",\n" + + " \"eventName\": \"ObjectCreated:Put\",\n" + + " \"userIdentity\": {\n" + + " \"principalId\": \"AWS:SOMETHING_COOL:i-1234\"\n" + + " },\n" + + " \"requestParameters\": {\n" + + " \"sourceIPAddress\": \"12.34.56.78\"\n" + + " },\n" + + " \"responseElements\": {\n" + + " \"x-amz-request-id\": \"SUPER_COOL_ID\",\n" + + " \"x-amz-id-2\": \"SOMETHING_AWESOME_CTU=\"\n" + + " },\n" + + " \"s3\": {\n" + + " \"s3SchemaVersion\": \"1.0\",\n" + + " \"configurationId\": \"QuarantineListAvailableSNS\",\n" + + " \"bucket\": {\n" + + " \"name\": \"staging-data-pact\",\n" + + " \"ownerIdentity\": {\n" + + " \"principalId\": \"WAS_IST_ES\"\n" + + " },\n" + + " \"arn\": \"arn:aws:s3:::staging-data-pact\"\n" + + " },\n" + + " \"object\": {\n" + + " \"key\": \"quarantined_classes/quar_out_2019-09-10-22-00-00.csv\",\n" + + " \"size\": 455211,\n" + + " \"eTag\": \"b39e0617b483c86500ec5319e0951d07\",\n" + + " \"sequencer\": \"005D782B97CD61A2EC\"\n" + + " }\n" + + " }\n" + + " }\n" + + " ]\n" + + "}"; + ObjectMapper mapper = new ObjectMapper(); + JsonNode treeObject = mapper.readTree(str); + assertNotNull(treeObject); + JsonNode records = treeObject.get("Records"); + System.out.println("records: " + records); + + JsonNode s3 = records.get(0); + System.out.println("s3: " + s3); + + JsonNode value = s3.get("s3"); + System.out.println("value: " + value); + + JsonNode object = value.get("object"); + System.out.println("object: " + object); + + String bucket = value.get("bucket").get("name").toString(); + System.out.println("bucket: " + bucket); + + String key = object.get("key").toString(); + System.out.println("key: " + key); + + } +} From 517fa6d68a28f27df77ee8a1941e97606eee07bb Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Mon, 23 Sep 2019 09:31:11 -0700 Subject: [PATCH 018/132] add code refactor question --- src/main/java/sporadic/GeneralizeExample.java | 101 ++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 src/main/java/sporadic/GeneralizeExample.java diff --git a/src/main/java/sporadic/GeneralizeExample.java b/src/main/java/sporadic/GeneralizeExample.java new file mode 100644 index 0000000..389a523 --- /dev/null +++ b/src/main/java/sporadic/GeneralizeExample.java @@ -0,0 +1,101 @@ +package sporadic; + +import java.util.Set; + +public class GeneralizeExample { + + /**Apparently the logic in specificMethod is duplicated, how can we generalize them and make it extensible? In case there's SetThree, SetFour in the future that needs to be added to this method?*/ + public void specificMethod(DDBRecord ddbRecord, Set incomingSetOne, Set incomingSetTwo, String incomingString) { + Set existingSetOne = ddbRecord.getSetOne(); + if (existingSetOne == null) { + if (!incomingSetOne.isEmpty()) { + ddbRecord.setSetOne(incomingSetOne); + ddbRecord.setSetOneCount(incomingSetOne.size()); + existingSetOne = incomingSetOne; + } + } else if (existingSetOne != null) { + if (incomingSetOne.isEmpty()) { + //remove this string from this set if it exists + existingSetOne.remove(incomingString); + int updatedSetOneCount = existingSetOne.size(); + ddbRecord.setSetOneCount(updatedSetOneCount); + if (updatedSetOneCount == 0) { + existingSetOne.add("N/A"); + } + ddbRecord.setSetOne(existingSetOne); + } else if (!incomingSetOne.isEmpty()) { + if (existingSetOne.contains("N/A")) { + existingSetOne.remove("N/A"); + } + //add this incoming set in + existingSetOne.addAll(incomingSetOne); + + ddbRecord.setSetOne(existingSetOne); + ddbRecord.setSetOneCount(existingSetOne.size()); + } + } + + Set existingSetTwo = ddbRecord.getSetTwo(); + if (existingSetTwo == null) { + if (!incomingSetTwo.isEmpty()) { + ddbRecord.setSetTwo(incomingSetTwo); + ddbRecord.setSetTwoCount(incomingSetTwo.size()); + existingSetTwo = incomingSetTwo; + } + } else if (existingSetTwo != null) { + if (incomingSetTwo.isEmpty()) { + //remove this string from this set if it exists + existingSetTwo.remove(incomingString); + int updatedSetTwoCount = existingSetTwo.size(); + ddbRecord.setSetTwoCount(updatedSetTwoCount); + if (updatedSetTwoCount == 0) { + existingSetTwo.add("N/A"); + } + ddbRecord.setSetTwo(existingSetTwo); + } else if (!incomingSetTwo.isEmpty()) { + if (existingSetTwo.contains("N/A")) { + existingSetTwo.remove("N/A"); + } + //add this incoming offer set in + existingSetTwo.addAll(incomingSetTwo); + + ddbRecord.setSetTwo(existingSetTwo); + ddbRecord.setSetTwoCount(existingSetTwo.size()); + } + } + + //do something w/ existingSetOne and existingSetTwo afterwards + } + + class DDBRecord { + private Set setOne; + private Set setTwo; + private int setOneCount; + private int setTwoCount; + + public Set getSetOne() { + return setOne; + } + + public void setSetOne(Set setOne) { + this.setOne = setOne; + } + + public void setSetOneCount(int count) { + this.setOneCount = count; + } + + public Set getSetTwo() { + return setTwo; + } + + public void setSetTwo(Set setTwo) { + this.setTwo = setTwo; + } + + public void setSetTwoCount(int count) { + this.setTwoCount = count; + } + } + +} From 5129e74da12acf045274389d84217217efde614c Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Mon, 23 Sep 2019 09:31:57 -0700 Subject: [PATCH 019/132] add StackOverflow question link --- src/main/java/sporadic/GeneralizeExample.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/sporadic/GeneralizeExample.java b/src/main/java/sporadic/GeneralizeExample.java index 389a523..2c87e71 100644 --- a/src/main/java/sporadic/GeneralizeExample.java +++ b/src/main/java/sporadic/GeneralizeExample.java @@ -2,6 +2,9 @@ import java.util.Set; +/**Posted the question here: + * https://softwareengineering.stackexchange.com/questions/398727/how-to-generalize-this-method-for-its-duplicate-common-logic/398731#398731 + * */ public class GeneralizeExample { /**Apparently the logic in specificMethod is duplicated, how can we generalize them and make it extensible? In case there's SetThree, SetFour in the future that needs to be added to this method?*/ From d367a3ec1b94102d3482bfa860c813be8667b824 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Mon, 18 Nov 2019 08:21:49 -0800 Subject: [PATCH 020/132] add one more Guice injector example, not working yet --- pom.xml | 15 + .../PrivateModuleTest.java | 554 ++++++++++++++++++ .../AmazonDynamoDB.java | 14 + .../ClassA.java | 10 + .../ClassB.java | 10 + .../CustomerDbDao.java | 19 + .../DynamoDBMapper.java | 13 + .../MainApp.java | 20 + .../Worker.java | 7 + .../Worker1.java | 26 + .../Worker1Module.java | 47 ++ .../Worker2.java | 23 + .../Worker2Module.java | 46 ++ .../WorkersModule.java | 12 + .../WorkersRunner.java | 38 ++ 15 files changed, 854 insertions(+) create mode 100644 src/main/java/guice/relearn_2019_09/_8_already_configured_exception/PrivateModuleTest.java create mode 100644 src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/AmazonDynamoDB.java create mode 100644 src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/ClassA.java create mode 100644 src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/ClassB.java create mode 100644 src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/CustomerDbDao.java create mode 100644 src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/DynamoDBMapper.java create mode 100644 src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/MainApp.java create mode 100644 src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/Worker.java create mode 100644 src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/Worker1.java create mode 100644 src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/Worker1Module.java create mode 100644 src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/Worker2.java create mode 100644 src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/Worker2Module.java create mode 100644 src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/WorkersModule.java create mode 100644 src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/WorkersRunner.java diff --git a/pom.xml b/pom.xml index 7273573..7693caf 100644 --- a/pom.xml +++ b/pom.xml @@ -118,6 +118,21 @@ 3.0 + + + com.google.collections + google-collections + 1.0 + + + + + com.google.inject + guice + LATEST + + + diff --git a/src/main/java/guice/relearn_2019_09/_8_already_configured_exception/PrivateModuleTest.java b/src/main/java/guice/relearn_2019_09/_8_already_configured_exception/PrivateModuleTest.java new file mode 100644 index 0000000..4cc0551 --- /dev/null +++ b/src/main/java/guice/relearn_2019_09/_8_already_configured_exception/PrivateModuleTest.java @@ -0,0 +1,554 @@ +package guice.relearn_2019_09._8_already_configured_exception; + +import static com.google.inject.name.Names.named; + +import com.google.inject.AbstractModule; +import com.google.inject.ConfigurationException; +import com.google.inject.CreationException; +import com.google.inject.Exposed; +import com.google.inject.Guice; +import com.google.inject.Inject; +import com.google.inject.Injector; +import com.google.inject.Key; +import com.google.inject.PrivateBinder; +import com.google.inject.PrivateModule; +import com.google.inject.Provider; +import com.google.inject.Provides; +import com.google.inject.name.Named; +import com.google.inject.name.Names; +import com.google.inject.spi.Dependency; +import com.google.inject.spi.ExposedBinding; +import com.google.inject.spi.PrivateElements; +import com.google.inject.util.Types; + +import junit.framework.TestCase; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +public class PrivateModuleTest extends TestCase { + + public void testBasicUsage() { + Injector injector = Guice.createInjector(new AbstractModule() { + @Override protected void configure() { + bind(String.class).annotatedWith(named("a")).toInstance("public"); + + install(new PrivateModule() { + @Override public void configure() { + bind(String.class).annotatedWith(named("b")).toInstance("i"); + + bind(AB.class).annotatedWith(named("one")).to(AB.class); + expose(AB.class).annotatedWith(named("one")); + } + }); + + install(new PrivateModule() { + @Override public void configure() { + bind(String.class).annotatedWith(named("b")).toInstance("ii"); + + bind(AB.class).annotatedWith(named("two")).to(AB.class); + expose(AB.class).annotatedWith(named("two")); + } + }); + } + }); + + AB ab1 = injector.getInstance(Key.get(AB.class, named("one"))); + assertEquals("public", ab1.a); + assertEquals("i", ab1.b); + + AB ab2 = injector.getInstance(Key.get(AB.class, named("two"))); + assertEquals("public", ab2.a); + assertEquals("ii", ab2.b); + } + + public void testWithoutPrivateModules() { + Injector injector = Guice.createInjector(new AbstractModule() { + @Override protected void configure() { + PrivateBinder bindA = binder().newPrivateBinder(); + bindA.bind(String.class).annotatedWith(named("a")).toInstance("i"); + bindA.expose(String.class).annotatedWith(named("a")); + bindA.bind(String.class).annotatedWith(named("c")).toInstance("private to A"); + + PrivateBinder bindB = binder().newPrivateBinder(); + bindB.bind(String.class).annotatedWith(named("b")).toInstance("ii"); + bindB.expose(String.class).annotatedWith(named("b")); + bindB.bind(String.class).annotatedWith(named("c")).toInstance("private to B"); + } + }); + + assertEquals("i", injector.getInstance(Key.get(String.class, named("a")))); + assertEquals("ii", injector.getInstance(Key.get(String.class, named("b")))); + } + + public void testMisplacedExposedAnnotation() { + try { + Guice.createInjector(new AbstractModule() { + @Override protected void configure() {} + + @Provides + @Exposed + String provideString() { + return "i"; + } + }); + fail(); + } catch (CreationException expected) { + System.out.println(expected.getMessage() + "Cannot expose java.lang.String on a standard binder. " + + "Exposed bindings are only applicable to private binders." + + " at " + PrivateModuleTest.class.getName() + "provideString(PrivateModuleTest.java:"); + } + } + + public void testMisplacedExposeStatement() { + try { + Guice.createInjector(new AbstractModule() { + @Override protected void configure() { + ((PrivateBinder) binder()).expose(String.class).annotatedWith(named("a")); + } + }); + fail(); + } catch (CreationException expected) { + System.out.println(expected.getMessage() + "Cannot expose java.lang.String on a standard binder. " + + "Exposed bindings are only applicable to private binders." + + " at " + PrivateModuleTest.class.getName() + getClass()); + } + } + + public void testPrivateModulesAndProvidesMethods() { + Injector injector = Guice.createInjector(new AbstractModule() { + @Override protected void configure() { + install(new PrivateModule() { + @Override public void configure() { + expose(String.class).annotatedWith(named("a")); + } + + @Provides @Named("a") String providePublicA() { + return "i"; + } + + @Provides @Named("b") String providePrivateB() { + return "private"; + } + }); + + install(new PrivateModule() { + @Override public void configure() {} + + @Provides @Named("c") String providePrivateC() { + return "private"; + } + + @Provides @Exposed @Named("d") String providePublicD() { + return "ii"; + } + }); + } + }); + + assertEquals("i", injector.getInstance(Key.get(String.class, named("a")))); + + try { + injector.getInstance(Key.get(String.class, named("b"))); + fail(); + } catch(ConfigurationException expected) { + } + + try { + injector.getInstance(Key.get(String.class, named("c"))); + fail(); + } catch(ConfigurationException expected) { + } + + assertEquals("ii", injector.getInstance(Key.get(String.class, named("d")))); + } + + public void testCannotBindAKeyExportedByASibling() { + try { + Guice.createInjector(new AbstractModule() { + @Override protected void configure() { + install(new PrivateModule() { + @Override public void configure() { + bind(String.class).toInstance("public"); + expose(String.class); + } + }); + + install(new PrivateModule() { + @Override public void configure() { + bind(String.class).toInstance("private"); + } + }); + } + }); + fail(); + } catch (CreationException expected) { +// assertContains(expected.getMessage(), +// "A binding to java.lang.String was already configured at ", +// getClass().getName(), getDeclaringSourcePart(getClass()), +// " at " + getClass().getName(), getDeclaringSourcePart(getClass())); + } + } + + public void testExposeButNoBind() { + try { + Guice.createInjector(new AbstractModule() { + @Override protected void configure() { + bind(String.class).annotatedWith(named("a")).toInstance("a"); + bind(String.class).annotatedWith(named("b")).toInstance("b"); + + install(new PrivateModule() { + @Override public void configure() { + expose(AB.class); + } + }); + } + }); + fail("AB was exposed but not bound"); + } catch (CreationException expected) { +// assertContains(expected.getMessage(), +// "Could not expose() " + AB.class.getName() + ", it must be explicitly bound", +// getDeclaringSourcePart(getClass())); + } + } + + /** + * Ensure that when we've got errors in different private modules, Guice presents all errors + * in a unified message. + */ + public void testMessagesFromPrivateModulesAreNicelyIntegrated() { + try { + Guice.createInjector( + new PrivateModule() { + @Override public void configure() { + bind(C.class); + } + }, + new PrivateModule() { + @Override public void configure() { + bind(AB.class); + } + } + ); + fail(); + } catch (CreationException expected) { +// assertContains(expected.getMessage(), +// "1) No implementation for " + C.class.getName() + " was bound.", +// "at " + getClass().getName(), getDeclaringSourcePart(getClass()), +// "2) No implementation for " + String.class.getName(), "Named(value=a) was bound.", +// "for field at " + AB.class.getName() + ".a(PrivateModuleTest.java:", +// "3) No implementation for " + String.class.getName(), "Named(value=b) was bound.", +// "for field at " + AB.class.getName() + ".b(PrivateModuleTest.java:", +// "3 errors"); + } + } + + public void testNestedPrivateInjectors() { + Injector injector = Guice.createInjector(new PrivateModule() { + @Override public void configure() { + expose(String.class); + + install(new PrivateModule() { + @Override public void configure() { + bind(String.class).toInstance("nested"); + expose(String.class); + } + }); + } + }); + + assertEquals("nested", injector.getInstance(String.class)); + } + + public void testInstallingRegularModulesFromPrivateModules() { + Injector injector = Guice.createInjector(new PrivateModule() { + @Override public void configure() { + expose(String.class); + + install(new AbstractModule() { + @Override protected void configure() { + bind(String.class).toInstance("nested"); + } + }); + } + }); + + assertEquals("nested", injector.getInstance(String.class)); + } + + public void testNestedPrivateModulesWithSomeKeysUnexposed() { + Injector injector = Guice.createInjector(new PrivateModule() { + @Override public void configure() { + bind(String.class).annotatedWith(named("bound outer, exposed outer")).toInstance("boeo"); + expose(String.class).annotatedWith(named("bound outer, exposed outer")); + bind(String.class).annotatedWith(named("bound outer, exposed none")).toInstance("boen"); + expose(String.class).annotatedWith(named("bound inner, exposed both")); + + install(new PrivateModule() { + @Override public void configure() { + bind(String.class).annotatedWith(named("bound inner, exposed both")).toInstance("bieb"); + expose(String.class).annotatedWith(named("bound inner, exposed both")); + bind(String.class).annotatedWith(named("bound inner, exposed none")).toInstance("bien"); + } + }); + } + }); + + assertEquals("boeo", + injector.getInstance(Key.get(String.class, named("bound outer, exposed outer")))); + assertEquals("bieb", + injector.getInstance(Key.get(String.class, named("bound inner, exposed both")))); + + try { + injector.getInstance(Key.get(String.class, named("bound outer, exposed none"))); + fail(); + } catch (ConfigurationException expected) { + } + + try { + injector.getInstance(Key.get(String.class, named("bound inner, exposed none"))); + fail(); + } catch (ConfigurationException expected) { + } + } + + public void testDependenciesBetweenPrivateAndPublic() { + Injector injector = Guice.createInjector( + new PrivateModule() { + @Override protected void configure() {} + + @Provides @Exposed @Named("a") String provideA() { + return "A"; + } + + @Provides @Exposed @Named("abc") String provideAbc(@Named("ab") String ab) { + return ab + "C"; + } + }, + new AbstractModule() { + @Override protected void configure() {} + + @Provides @Named("ab") String provideAb(@Named("a") String a) { + return a + "B"; + } + + @Provides @Named("abcd") String provideAbcd(@Named("abc") String abc) { + return abc + "D"; + } + } + ); + + assertEquals("ABCD", injector.getInstance(Key.get(String.class, named("abcd")))); + } + + public void testDependenciesBetweenPrivateAndPublicWithPublicEagerSingleton() { + Injector injector = Guice.createInjector( + new PrivateModule() { + @Override protected void configure() {} + + @Provides @Exposed @Named("a") String provideA() { + return "A"; + } + + @Provides @Exposed @Named("abc") String provideAbc(@Named("ab") String ab) { + return ab + "C"; + } + }, + new AbstractModule() { + @Override protected void configure() { + bind(String.class).annotatedWith(named("abcde")).toProvider(new Provider() { + @Inject @Named("abcd") String abcd; + + public String get() { + return abcd + "E"; + } + }).asEagerSingleton(); + } + + @Provides @Named("ab") String provideAb(@Named("a") String a) { + return a + "B"; + } + + @Provides @Named("abcd") String provideAbcd(@Named("abc") String abc) { + return abc + "D"; + } + } + ); + + assertEquals("ABCDE", injector.getInstance(Key.get(String.class, named("abcde")))); + } + + public void testDependenciesBetweenPrivateAndPublicWithPrivateEagerSingleton() { + Injector injector = Guice.createInjector( + new AbstractModule() { + @Override protected void configure() {} + + @Provides @Named("ab") String provideAb(@Named("a") String a) { + return a + "B"; + } + + @Provides @Named("abcd") String provideAbcd(@Named("abc") String abc) { + return abc + "D"; + } + }, + new PrivateModule() { + @Override protected void configure() { + bind(String.class).annotatedWith(named("abcde")).toProvider(new Provider() { + @Inject @Named("abcd") String abcd; + + public String get() { + return abcd + "E"; + } + }).asEagerSingleton(); + expose(String.class).annotatedWith(named("abcde")); + } + + @Provides @Exposed @Named("a") String provideA() { + return "A"; + } + + @Provides @Exposed @Named("abc") String provideAbc(@Named("ab") String ab) { + return ab + "C"; + } + } + ); + + assertEquals("ABCDE", injector.getInstance(Key.get(String.class, named("abcde")))); + } + + static class AB { + @Inject @Named("a") String a; + @Inject @Named("b") String b; + } + + interface C {} + + public void testSpiAccess() { + Injector injector = Guice.createInjector(new PrivateModule() { + @Override public void configure() { + bind(String.class).annotatedWith(named("a")).toInstance("private"); + bind(String.class).annotatedWith(named("b")).toInstance("exposed"); + expose(String.class).annotatedWith(named("b")); + } + }); + + ExposedBinding binding + = (ExposedBinding) injector.getBinding(Key.get(String.class, Names.named("b"))); +// assertEquals(ImmutableSet..", +// "It was already configured on one or more child injectors or private modules", +// "bound at " + FailingPrivateModule.class.getName() + ".configure(", +// asModuleChain(ManyPrivateModules.class, FailingPrivateModule.class), +// "bound at " + SecondFailingPrivateModule.class.getName() + ".configure(", +// asModuleChain(ManyPrivateModules.class, SecondFailingPrivateModule.class), +// "If it was in a PrivateModule, did you forget to expose the binding?", +// "while locating com.google.inject.Provider"); + } + } + + public void testParentBindingToPrivateJitBinding() { + Injector injector = Guice.createInjector(new ManyPrivateModules()); + try { + injector.getBinding(PrivateFoo.class); + fail(); + } catch(ConfigurationException expected) { + assertEquals(1, expected.getErrorMessages().size()); +// assertContains(expected.toString(), +// "Unable to create binding for " + PrivateFoo.class.getName(), +// "It was already configured on one or more child injectors or private modules", +// "(bound by a just-in-time binding)", +// "If it was in a PrivateModule, did you forget to expose the binding?", +// "while locating " + PrivateFoo.class.getName()); + } + } + + private static class FailingModule extends AbstractModule { + @Override protected void configure() { + bind(Collection.class).to(List.class); + install(new ManyPrivateModules()); + } + } + + private static class ManyPrivateModules extends AbstractModule { + @Override protected void configure() { + // make sure duplicate sources are collapsed + install(new FailingPrivateModule()); + install(new FailingPrivateModule()); + // but additional sources are listed + install(new SecondFailingPrivateModule()); + } + } + + private static class FailingPrivateModule extends PrivateModule { + @Override protected void configure() { + bind(List.class).toInstance(new ArrayList()); + + // Add the Provider binding, created just-in-time, + // to make sure our linked JIT bindings have the correct source. + getProvider(Key.get(Types.providerOf(List.class))); + + // Request a JIT binding for PrivateFoo, which can only + // be created in the private module because it depends + // on List. + getProvider(PrivateFoo.class); + } + } + + /** A second class, so we can see another name in the source list. */ + private static class SecondFailingPrivateModule extends PrivateModule { + @Override protected void configure() { + bind(List.class).toInstance(new ArrayList()); + + // Add the Provider binding, created just-in-time, + // to make sure our linked JIT bindings have the correct source. + getProvider(Key.get(Types.providerOf(List.class))); + + // Request a JIT binding for PrivateFoo, which can only + // be created in the private module because it depends + // on List. + getProvider(PrivateFoo.class); + } + } + + private static class PrivateFoo { + @Inject List list; + } +} diff --git a/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/AmazonDynamoDB.java b/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/AmazonDynamoDB.java new file mode 100644 index 0000000..e489c6e --- /dev/null +++ b/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/AmazonDynamoDB.java @@ -0,0 +1,14 @@ +package guice.relearn_2019_09._9_inject_the_same_object_in_two_modules; + +public class AmazonDynamoDB { + /** + * This is a dummy class since AWS DynamoDB Maven depdency cannot be resolved in my local. + */ + private final String awsRegion; + private final String ddbEndPoint; + + public AmazonDynamoDB(String awsRegion, String ddbEndPoint) { + this.awsRegion = awsRegion; + this.ddbEndPoint = ddbEndPoint; + } +} diff --git a/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/ClassA.java b/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/ClassA.java new file mode 100644 index 0000000..54cb795 --- /dev/null +++ b/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/ClassA.java @@ -0,0 +1,10 @@ +package guice.relearn_2019_09._9_inject_the_same_object_in_two_modules; + +import com.google.inject.Inject; +import lombok.AllArgsConstructor; + +@AllArgsConstructor(onConstructor = @__(@Inject)) +public class ClassA { + private final CustomerDbDao customerDbDao; + private static final String message = "This is from ClassA!"; +} diff --git a/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/ClassB.java b/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/ClassB.java new file mode 100644 index 0000000..4e28135 --- /dev/null +++ b/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/ClassB.java @@ -0,0 +1,10 @@ +package guice.relearn_2019_09._9_inject_the_same_object_in_two_modules; + +import com.google.inject.Inject; +import lombok.AllArgsConstructor; + +@AllArgsConstructor(onConstructor = @__(@Inject)) +public class ClassB { + private final CustomerDbDao customerDbDao; + private static final String message = "This is from ClassB!"; +} diff --git a/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/CustomerDbDao.java b/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/CustomerDbDao.java new file mode 100644 index 0000000..311cca0 --- /dev/null +++ b/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/CustomerDbDao.java @@ -0,0 +1,19 @@ +package guice.relearn_2019_09._9_inject_the_same_object_in_two_modules; + +import com.google.inject.Inject; +import com.google.inject.name.Named; + +public class CustomerDbDao { + public static final String CUSTOMER_DDB = "Customer.DDB"; + + private final DynamoDBMapper dynamoDBMapper; + + @Inject + public CustomerDbDao(@Named(CUSTOMER_DDB) DynamoDBMapper dynamoDBMapper) { + this.dynamoDBMapper = dynamoDBMapper; + } + + public void work() { + System.out.println("CustomerDbDao object is talking to Amazon DynamoDB and doing its work!"); + } +} diff --git a/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/DynamoDBMapper.java b/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/DynamoDBMapper.java new file mode 100644 index 0000000..9deb89d --- /dev/null +++ b/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/DynamoDBMapper.java @@ -0,0 +1,13 @@ +package guice.relearn_2019_09._9_inject_the_same_object_in_two_modules; + +public class DynamoDBMapper { + /** + * This is a dummy class since AWS DynamoDB Maven depdency cannot be resolved in my local. + */ + + private final AmazonDynamoDB dynamodb; + + public DynamoDBMapper(AmazonDynamoDB dynamodb) { + this.dynamodb = dynamodb; + } +} diff --git a/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/MainApp.java b/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/MainApp.java new file mode 100644 index 0000000..5e87ba5 --- /dev/null +++ b/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/MainApp.java @@ -0,0 +1,20 @@ +package guice.relearn_2019_09._9_inject_the_same_object_in_two_modules; + +import com.google.inject.Guice; +import com.google.inject.Injector; + +public class MainApp { + + public static void main(String... args) { + try { + Injector injector = Guice.createInjector(new WorkersModule()); + System.out.println("created injector: " + injector); + WorkersRunner workersRunner = injector.getInstance(WorkersRunner.class); + System.out.println("got workersRunner: " + workersRunner); + workersRunner.start(); + workersRunner.shutdown(); + } catch (Exception e) { + System.out.println("caught exception, e: " + e); + } + } +} diff --git a/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/Worker.java b/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/Worker.java new file mode 100644 index 0000000..72eefb7 --- /dev/null +++ b/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/Worker.java @@ -0,0 +1,7 @@ +package guice.relearn_2019_09._9_inject_the_same_object_in_two_modules; + +public interface Worker { + void start(); + + void shutdown(); +} diff --git a/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/Worker1.java b/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/Worker1.java new file mode 100644 index 0000000..cc44d66 --- /dev/null +++ b/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/Worker1.java @@ -0,0 +1,26 @@ +package guice.relearn_2019_09._9_inject_the_same_object_in_two_modules; + +import com.google.inject.Inject; +import com.google.inject.name.Named; + +import static guice.relearn_2019_09._9_inject_the_same_object_in_two_modules.Worker1Module.WORKER1; + +public class Worker1 implements Worker { + private final CustomerDbDao customerDbDao; + + @Inject + public Worker1(@Named(WORKER1) CustomerDbDao customerDbDao) { + this.customerDbDao = customerDbDao; + } + + @Override + public void start() { + System.out.println("Worker1 started working!"); + } + + @Override + public void shutdown() { + System.out.println("Worker1 has shut down!"); + } + +} diff --git a/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/Worker1Module.java b/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/Worker1Module.java new file mode 100644 index 0000000..d2ef13e --- /dev/null +++ b/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/Worker1Module.java @@ -0,0 +1,47 @@ +package guice.relearn_2019_09._9_inject_the_same_object_in_two_modules; + +import com.google.inject.PrivateModule; +import com.google.inject.Provides; +import com.google.inject.Singleton; +import com.google.inject.multibindings.Multibinder; +import com.google.inject.name.Named; +import com.google.inject.name.Names; + +import static guice.relearn_2019_09._9_inject_the_same_object_in_two_modules.CustomerDbDao.CUSTOMER_DDB; + +public class Worker1Module extends PrivateModule { + + public static final String WORKER1 = "Worker1"; + private static final String DDB_END_POINT = "dynamodb.us-west-2.amazonaws.com"; + private static final String AWS_REGION = "us-west-2"; + + @Override + protected void configure() { + final Multibinder multibinder = Multibinder.newSetBinder(binder(), Worker.class); + multibinder.addBinding().to(Worker1.class); + + bind(String.class).annotatedWith(Names.named(AWS_REGION)).toInstance("cool"); + bind(String.class).annotatedWith(Names.named(DDB_END_POINT)).toInstance("cool1"); + } + + @Provides + @Singleton + @Named(WORKER1) + public CustomerDbDao providesCustomerDbDao(@Named(CUSTOMER_DDB) DynamoDBMapper dynamoDBMapper) { + return new CustomerDbDao(dynamoDBMapper); + } + + @Provides + @Singleton + @Named(CUSTOMER_DDB) + public DynamoDBMapper provideDynamoDBMapper(@Named(CUSTOMER_DDB) AmazonDynamoDB dynamodb) { + return new DynamoDBMapper(dynamodb); + } + + @Provides + @Singleton + @Named(CUSTOMER_DDB) + public AmazonDynamoDB provideDynamoDBClient(final @Named(AWS_REGION) String awsRegion, final @Named(DDB_END_POINT) String ddbEndPoint) { + return new AmazonDynamoDB(awsRegion, ddbEndPoint); + } +} diff --git a/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/Worker2.java b/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/Worker2.java new file mode 100644 index 0000000..78ef7bf --- /dev/null +++ b/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/Worker2.java @@ -0,0 +1,23 @@ +package guice.relearn_2019_09._9_inject_the_same_object_in_two_modules; + +import com.google.inject.Inject; +import com.google.inject.name.Named; + +public class Worker2 implements Worker { + private final CustomerDbDao customerDbDao; + + @Inject + public Worker2(@Named("Worker2") CustomerDbDao customerDbDao) { + this.customerDbDao = customerDbDao; + } + + @Override + public void start() { + System.out.println("Worker2 started working!"); + } + + @Override + public void shutdown() { + System.out.println("Worker2 has shut down!"); + } +} diff --git a/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/Worker2Module.java b/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/Worker2Module.java new file mode 100644 index 0000000..473a041 --- /dev/null +++ b/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/Worker2Module.java @@ -0,0 +1,46 @@ +package guice.relearn_2019_09._9_inject_the_same_object_in_two_modules; + +import com.google.inject.PrivateModule; +import com.google.inject.Provides; +import com.google.inject.Singleton; +import com.google.inject.multibindings.Multibinder; +import com.google.inject.name.Named; +import com.google.inject.name.Names; + +import static guice.relearn_2019_09._9_inject_the_same_object_in_two_modules.CustomerDbDao.CUSTOMER_DDB; + +public class Worker2Module extends PrivateModule { + + public static final String WORKER2 = "Worker2"; + private static final String DDB_END_POINT = "dynamodb.us-west-2.amazonaws.com"; + private static final String AWS_REGION = "us-west-2"; + + @Override + protected void configure() { +// final Multibinder multibinder = Multibinder.newSetBinder(binder(), Worker.class); +// multibinder.addBinding().to(Worker2.class); +// bind(String.class).annotatedWith(Names.named(AWS_REGION)).toInstance("cool"); +// bind(String.class).annotatedWith(Names.named(DDB_END_POINT)).toInstance("cool1"); + } + + @Provides + @Singleton + @Named(WORKER2) + public CustomerDbDao providesCustomerDbDao(@Named(CUSTOMER_DDB) DynamoDBMapper dynamoDBMapper) { + return new CustomerDbDao(dynamoDBMapper); + } + + @Provides + @Singleton + @Named(CUSTOMER_DDB) + public DynamoDBMapper provideDynamoDBMapper(@Named(CUSTOMER_DDB) AmazonDynamoDB dynamodb) { + return new DynamoDBMapper(dynamodb); + } + + @Provides + @Singleton + @Named(CUSTOMER_DDB) + public AmazonDynamoDB provideDynamoDBClient(final @Named(AWS_REGION) String awsRegion, final @Named(DDB_END_POINT) String ddbEndPoint) { + return new AmazonDynamoDB(awsRegion, ddbEndPoint); + } +} diff --git a/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/WorkersModule.java b/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/WorkersModule.java new file mode 100644 index 0000000..e3213b0 --- /dev/null +++ b/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/WorkersModule.java @@ -0,0 +1,12 @@ +package guice.relearn_2019_09._9_inject_the_same_object_in_two_modules; + +import com.google.inject.AbstractModule; + +public class WorkersModule extends AbstractModule { + + @Override + protected void configure() { + install(new Worker1Module()); +// install(new Worker2Module()); + } +} diff --git a/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/WorkersRunner.java b/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/WorkersRunner.java new file mode 100644 index 0000000..898ed33 --- /dev/null +++ b/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/WorkersRunner.java @@ -0,0 +1,38 @@ +package guice.relearn_2019_09._9_inject_the_same_object_in_two_modules; + +import lombok.extern.slf4j.Slf4j; +import lombok.val; + +import javax.inject.Inject; +import java.util.Set; +import java.util.stream.Collectors; + +@Slf4j +public class WorkersRunner { + + @Inject + private Set workers; + + public void start() { + log.info("Starting up Background Workers: " + workers.stream() + .map((w) -> w.getClass().getSimpleName()) + .collect(Collectors.joining(","))); + + val now = System.currentTimeMillis(); + + workers.forEach((w) -> { + log.info("Starting up " + w.getClass().getName() + "..."); + w.start(); + log.info("Start up took " + (System.currentTimeMillis() - now) + " ms"); + }); + } + + /** + * Shutdown workers gracefully + */ + public void shutdown() { + workers.forEach((w) -> { + w.shutdown(); + }); + } +} From beea7f5a0a3c702002e84e733c42f8b1096d8a29 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Mon, 18 Nov 2019 08:56:39 -0800 Subject: [PATCH 021/132] add bitwise operator example --- src/main/java/bitoperators/MainApp.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 src/main/java/bitoperators/MainApp.java diff --git a/src/main/java/bitoperators/MainApp.java b/src/main/java/bitoperators/MainApp.java new file mode 100644 index 0000000..4001fe1 --- /dev/null +++ b/src/main/java/bitoperators/MainApp.java @@ -0,0 +1,15 @@ +package bitoperators; + +public class MainApp { + + public static void main(String... args) { + int value1 = 3; + int value2 = 4; + System.out.println(Integer.toBinaryString(value1)); + System.out.println(Integer.toBinaryString(value2)); + + int result = value1 ^ value2; + System.out.println(result); + System.out.println(Integer.toBinaryString(result)); + } +} From 6eeb77c1d59a0859976ec5d290ba850f912eceb7 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Mon, 18 Nov 2019 09:23:24 -0800 Subject: [PATCH 022/132] upgrade lombok to fix mvn build error --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 7693caf..faa1ff1 100644 --- a/pom.xml +++ b/pom.xml @@ -37,7 +37,7 @@ org.projectlombok lombok - 1.16.12 + 1.18.2 provided From 58a76df8fc784239eb9481ffc3ac6d19846832d0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Jul 2020 17:41:40 +0000 Subject: [PATCH 023/132] Bump log4j-core from 2.7 to 2.13.2 Bumps log4j-core from 2.7 to 2.13.2. Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index faa1ff1..f0f5123 100644 --- a/pom.xml +++ b/pom.xml @@ -31,7 +31,7 @@ org.apache.logging.log4j log4j-core - 2.7 + 2.13.2 From 06066bd785d55a8a553e224e353244de29b5d595 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 12 Oct 2020 17:58:42 +0000 Subject: [PATCH 024/132] Bump junit from 4.11 to 4.13.1 Bumps [junit](https://github.com/junit-team/junit4) from 4.11 to 4.13.1. - [Release notes](https://github.com/junit-team/junit4/releases) - [Changelog](https://github.com/junit-team/junit4/blob/main/doc/ReleaseNotes4.11.md) - [Commits](https://github.com/junit-team/junit4/compare/r4.11...r4.13.1) Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index f0f5123..1d44c89 100644 --- a/pom.xml +++ b/pom.xml @@ -44,7 +44,7 @@ junit junit - 4.11 + 4.13.1 From 3154ae30d2827c1d39309c510dc5bee42633a2f4 Mon Sep 17 00:00:00 2001 From: Steve Sun Date: Mon, 17 May 2021 11:47:53 -0700 Subject: [PATCH 025/132] update README.md --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index a10548f..885874f 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,10 @@ This is a Maven project containing a bunch of Random Java programs that I used, wrote from time to time. Build instructions: -If you get compile/run/IntelliJ errors, e.g. ClassNotFoundException when running in IntelliJ, just rm your package from your local machine, use IntelliJ to directly open: +* `git clone` this repo to your local, then open this application as a Maven project. +* If you get compile/run/IntelliJ errors, e.g. ClassNotFoundException when running in IntelliJ, just rm your package from your local machine, use IntelliJ to directly open: File -> New -> Project from Version Control -> GitHub, then configure JDK8, then you'll fly with colors! ^ ^ +* Please use JDK8 to run this application, due to https://stackoverflow.com/a/51169519/4117496 | Package/Theme | Code |----------------|--------------- From 71d918cbb25f70c6549789dc47e7c28cf02a0429 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Tue, 18 May 2021 09:49:45 -0700 Subject: [PATCH 026/132] add a spark example --- README.md | 4 +- pom.xml | 14 +++++ .../Chapter3.java | 51 ------------------- src/main/java/sparkExamples/Input1.txt | 5 ++ .../java/sparkExamples/SparkExample1.java | 44 ++++++++++++++++ 5 files changed, 65 insertions(+), 53 deletions(-) delete mode 100644 src/main/java/java8_for_the_really_impatient/Chapter3.java create mode 100644 src/main/java/sparkExamples/Input1.txt create mode 100644 src/main/java/sparkExamples/SparkExample1.java diff --git a/README.md b/README.md index 885874f..d02d1ec 100644 --- a/README.md +++ b/README.md @@ -5,8 +5,8 @@ Build instructions: * `git clone` this repo to your local, then open this application as a Maven project. * If you get compile/run/IntelliJ errors, e.g. ClassNotFoundException when running in IntelliJ, just rm your package from your local machine, use IntelliJ to directly open: File -> New -> Project from Version Control -> GitHub, then configure JDK8, then you'll fly with colors! ^ ^ -* Please use JDK8 to run this application, due to https://stackoverflow.com/a/51169519/4117496 - +* run `mvn install` to install depedencies on your machine +* In your Intellij, click the Maven icon and click on Reload all Maven projects | Package/Theme | Code |----------------|--------------- |Avro|[Avro code](../master/src/main/java/avro) diff --git a/pom.xml b/pom.xml index 1d44c89..645d5cf 100644 --- a/pom.xml +++ b/pom.xml @@ -112,6 +112,20 @@ 1.11.253 + + + org.apache.spark + spark-core_2.12 + 3.1.1 + + + + org.apache.spark + spark-sql_2.12 + 3.0.1 + provided + + com.google.inject guice diff --git a/src/main/java/java8_for_the_really_impatient/Chapter3.java b/src/main/java/java8_for_the_really_impatient/Chapter3.java deleted file mode 100644 index b196363..0000000 --- a/src/main/java/java8_for_the_really_impatient/Chapter3.java +++ /dev/null @@ -1,51 +0,0 @@ -package java8_for_the_really_impatient; - -import java.util.function.BiFunction; -import javafx.application.Application; -import javafx.scene.Scene; -import javafx.scene.image.Image; -import javafx.scene.image.ImageView; -import javafx.scene.image.WritableImage; -import javafx.scene.layout.HBox; -import javafx.scene.paint.Color; -import javafx.stage.Stage; - -public class Chapter3 extends Application { - - /** - * 3.4 Returning functions instead of just simple values in Java - * - * Exercise 6 - */ - public static Image transform(Image in, BiFunction f, T arg) { - int width = (int) in.getWidth(); - int height = (int) in.getHeight(); - WritableImage out = new WritableImage(width, height); - for (int x = 0; x < width; x++) { - for (int y = 0; y < height; y++) { - out.getPixelWriter().setColor(x, y, - f.apply(in.getPixelReader().getColor(x, y), arg)); - } - } - return out; - } - - @Override - public void start(Stage stage) throws Exception { - Image image = new Image("queen-mary.png"); - Image newImage = transform(image, - (c, factor) -> c.deriveColor(0, 1, factor, 1), 0.05 - ); - stage.setScene(new Scene(new HBox(new ImageView(image), new ImageView(newImage)))); - stage.show(); - } - - - public static void main(String... args) { - Application.launch(args); - } - - - /** 3.5 Composition: saves the storage of an intermediate stage. */ - -} diff --git a/src/main/java/sparkExamples/Input1.txt b/src/main/java/sparkExamples/Input1.txt new file mode 100644 index 0000000..42f3bbc --- /dev/null +++ b/src/main/java/sparkExamples/Input1.txt @@ -0,0 +1,5 @@ +A wonderful king is Hadoop. +The elephant plays well with Sqoop. +But what helps him to thrive +Are Impala, and Hive, +And HDFS in the group. \ No newline at end of file diff --git a/src/main/java/sparkExamples/SparkExample1.java b/src/main/java/sparkExamples/SparkExample1.java new file mode 100644 index 0000000..4281c0b --- /dev/null +++ b/src/main/java/sparkExamples/SparkExample1.java @@ -0,0 +1,44 @@ +package sparkExamples; + +import org.apache.spark.api.java.JavaPairRDD; +import org.apache.spark.api.java.JavaRDD; +import org.apache.spark.sql.SparkSession; +import scala.Tuple2; + +import java.util.Arrays; +import java.util.regex.Pattern; + +public class SparkExample1 { + /** + * How to run this program: + * 1. mvn compile + * 2. mvn exec:java -Dexec.mainClass=sparkExamples.SparkExample1 -Dexec.args="sparkExamples/File1.txt sparkExamples/Output1.txt" + *

+ * TODO: right now, it throws java.lang.NoClassDefFoundError: org/apache/spark/sql/SparkSession, fix it. + */ + + private static final Pattern SPACE = Pattern.compile(" "); + + public static void main(String[] args) { + System.out.println("Hello world!"); + System.out.println("args.length:" + args.length); + if (args.length < 2) { + System.err.println("Usage: JavaWordCount "); + System.exit(1); + } + + SparkSession spark = SparkSession + .builder() + .appName("SparkJob") + .getOrCreate(); + + JavaRDD textFile = spark.read().textFile(args[0]).toJavaRDD(); + + JavaPairRDD counts = textFile + .flatMap(s -> Arrays.asList(SPACE.split(s)).iterator()) + .mapToPair(s -> new Tuple2<>(s, 1)) + .reduceByKey((a, b) -> a + b); + + counts.saveAsTextFile(args[1]); + } +} From 2a366ec27cbd06f2bfe4353baf7a10755a6e2990 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Tue, 18 May 2021 09:50:45 -0700 Subject: [PATCH 027/132] fix README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index d02d1ec..5732606 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,7 @@ Build instructions: File -> New -> Project from Version Control -> GitHub, then configure JDK8, then you'll fly with colors! ^ ^ * run `mvn install` to install depedencies on your machine * In your Intellij, click the Maven icon and click on Reload all Maven projects + | Package/Theme | Code |----------------|--------------- |Avro|[Avro code](../master/src/main/java/avro) From 058bb4816774d7c621542351b7412fc5dab28af5 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Tue, 18 May 2021 10:24:29 -0700 Subject: [PATCH 028/132] fix run --- pom.xml | 1 - src/main/java/sparkExamples/SparkExample1.java | 6 ++---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/pom.xml b/pom.xml index 645d5cf..5f7968e 100644 --- a/pom.xml +++ b/pom.xml @@ -123,7 +123,6 @@ org.apache.spark spark-sql_2.12 3.0.1 - provided diff --git a/src/main/java/sparkExamples/SparkExample1.java b/src/main/java/sparkExamples/SparkExample1.java index 4281c0b..61d64ac 100644 --- a/src/main/java/sparkExamples/SparkExample1.java +++ b/src/main/java/sparkExamples/SparkExample1.java @@ -11,10 +11,7 @@ public class SparkExample1 { /** * How to run this program: - * 1. mvn compile - * 2. mvn exec:java -Dexec.mainClass=sparkExamples.SparkExample1 -Dexec.args="sparkExamples/File1.txt sparkExamples/Output1.txt" - *

- * TODO: right now, it throws java.lang.NoClassDefFoundError: org/apache/spark/sql/SparkSession, fix it. + * mvn compile && mvn exec:java -Dexec.mainClass=sparkExamples.SparkExample1 -Dexec.args="sparkExamples/File1.txt sparkExamples/Output1.txt" */ private static final Pattern SPACE = Pattern.compile(" "); @@ -26,6 +23,7 @@ public static void main(String[] args) { System.err.println("Usage: JavaWordCount "); System.exit(1); } + System.out.println("args.[0]:" + args[0] + ", args[1]: " + args[1]); SparkSession spark = SparkSession .builder() From 79fc9fa71b66e227c34de4f2ca77d20720c11b27 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Tue, 18 May 2021 10:25:00 -0700 Subject: [PATCH 029/132] fix broken run dur to master URL not set issue --- src/main/java/sparkExamples/SparkExample1.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/sparkExamples/SparkExample1.java b/src/main/java/sparkExamples/SparkExample1.java index 61d64ac..b23b128 100644 --- a/src/main/java/sparkExamples/SparkExample1.java +++ b/src/main/java/sparkExamples/SparkExample1.java @@ -28,6 +28,7 @@ public static void main(String[] args) { SparkSession spark = SparkSession .builder() .appName("SparkJob") + .config("spark.master", "local") .getOrCreate(); JavaRDD textFile = spark.read().textFile(args[0]).toJavaRDD(); From 6c5a27ec5085e3135e5b0320dbf466a61a392b5a Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Tue, 18 May 2021 10:35:36 -0700 Subject: [PATCH 030/132] add more debug statements --- .../java/sparkExamples/SparkExample1.java | 37 +++++++++++-------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/src/main/java/sparkExamples/SparkExample1.java b/src/main/java/sparkExamples/SparkExample1.java index b23b128..43a6ec4 100644 --- a/src/main/java/sparkExamples/SparkExample1.java +++ b/src/main/java/sparkExamples/SparkExample1.java @@ -24,20 +24,27 @@ public static void main(String[] args) { System.exit(1); } System.out.println("args.[0]:" + args[0] + ", args[1]: " + args[1]); - - SparkSession spark = SparkSession - .builder() - .appName("SparkJob") - .config("spark.master", "local") - .getOrCreate(); - - JavaRDD textFile = spark.read().textFile(args[0]).toJavaRDD(); - - JavaPairRDD counts = textFile - .flatMap(s -> Arrays.asList(SPACE.split(s)).iterator()) - .mapToPair(s -> new Tuple2<>(s, 1)) - .reduceByKey((a, b) -> a + b); - - counts.saveAsTextFile(args[1]); + try { + SparkSession spark = SparkSession + .builder() + .appName("SparkJob") + .config("spark.master", "local") + .getOrCreate(); + System.out.println("SparkSession is initated."); + + JavaRDD textFile = spark.read().textFile(args[0]).toJavaRDD(); + System.out.println("Finished reading this textFile: " + args[0]); + + JavaPairRDD counts = textFile + .flatMap(s -> Arrays.asList(SPACE.split(s)).iterator()) + .mapToPair(s -> new Tuple2<>(s, 1)) + .reduceByKey((a, b) -> a + b); + System.out.println("Finished doing MapReduce option on this textFile: " + args[0]); + + counts.saveAsTextFile(args[1]); + System.out.println("Finished saving output to this textFile: " + args[1]); + } catch (Exception e) { + System.out.println("Caught exception when processing: " + e); + } } } From 3a39f9e35677ff490d9cfffa8eb999e2893713ee Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Tue, 18 May 2021 11:23:30 -0700 Subject: [PATCH 031/132] add another Spark example --- src/main/java/sparkExamples/JavaSparkPi.java | 57 ++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 src/main/java/sparkExamples/JavaSparkPi.java diff --git a/src/main/java/sparkExamples/JavaSparkPi.java b/src/main/java/sparkExamples/JavaSparkPi.java new file mode 100644 index 0000000..2309e43 --- /dev/null +++ b/src/main/java/sparkExamples/JavaSparkPi.java @@ -0,0 +1,57 @@ +package sparkExamples; + +import org.apache.spark.SparkConf; +import org.apache.spark.api.java.JavaRDD; +import org.apache.spark.api.java.JavaSparkContext; +import org.apache.spark.api.java.function.Function; +import org.apache.spark.api.java.function.Function2; + +import java.util.ArrayList; +import java.util.List; + +/** + * Computes an approximation to pi + * Usage: JavaSparkPi [slices] + * + * TODO: it's throwing Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 28499 when running locally through Intellij. + */ +public final class JavaSparkPi { + + public static void main(String[] args) throws Exception { + SparkConf sparkConf = new SparkConf() + .setAppName("JavaSparkPi") + .setMaster("local"); + JavaSparkContext jsc = new JavaSparkContext(sparkConf); + System.out.println("JavaSparkContext is initiated."); + + int slices = (args.length == 1) ? Integer.parseInt(args[0]) : 2; + int n = 1000 * slices; + List list = new ArrayList<>(n); + for (int i = 0; i < n; i++) { + list.add(i); + } + System.out.println("Got list.size() is: " + list.size()); + + JavaRDD dataSet = jsc.parallelize(list, slices); + System.out.println("dataSet.count() is: " + dataSet.count()); + + int count = dataSet.map(new Function() { + @Override + public Integer call(Integer integer) { + double x = Math.random() * 2 - 1; + double y = Math.random() * 2 - 1; + return (x * x + y * y < 1) ? 1 : 0; + } + }).reduce(new Function2() { + @Override + public Integer call(Integer integer, Integer integer2) { + return integer + integer2; + } + }); + + System.out.println("Pi is roughly " + 4.0 * count / n); + + jsc.stop(); + } +} + From 3277ab10e823c7984f2e436f16f60ec42c56dac8 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Tue, 18 May 2021 14:46:53 -0700 Subject: [PATCH 032/132] add more instructions --- src/main/java/sparkExamples/Input1.txt | 10 +++++----- src/main/java/sparkExamples/SparkExample1.java | 10 ++++++++-- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/main/java/sparkExamples/Input1.txt b/src/main/java/sparkExamples/Input1.txt index 42f3bbc..e490523 100644 --- a/src/main/java/sparkExamples/Input1.txt +++ b/src/main/java/sparkExamples/Input1.txt @@ -1,5 +1,5 @@ -A wonderful king is Hadoop. -The elephant plays well with Sqoop. -But what helps him to thrive -Are Impala, and Hive, -And HDFS in the group. \ No newline at end of file +A wonderful king is Hadoop. - Ada +The elephant plays well with Sqoop. - Rachel +But what helps him to thrive - Ada +Are Impala, and Hive, - Rachel +And HDFS in the group. - Ada \ No newline at end of file diff --git a/src/main/java/sparkExamples/SparkExample1.java b/src/main/java/sparkExamples/SparkExample1.java index 43a6ec4..e46893e 100644 --- a/src/main/java/sparkExamples/SparkExample1.java +++ b/src/main/java/sparkExamples/SparkExample1.java @@ -11,7 +11,13 @@ public class SparkExample1 { /** * How to run this program: - * mvn compile && mvn exec:java -Dexec.mainClass=sparkExamples.SparkExample1 -Dexec.args="sparkExamples/File1.txt sparkExamples/Output1.txt" + * 1. locally: mvn compile && mvn exec:java -Dexec.mainClass=sparkExamples.SparkExample1 -Dexec.args="sparkExamples/Input1.txt sparkExamples/Output1.txt" + * 2. on AWS EMR cluster: + * upload the compiled jar file: RandomJava-1.0-SNAPSHOT.jar to an S3 bucket + * click add steps to a ready cluster on AWS EMR + * --class sparkExamples.SparkExample1 + * specify the jar in your S3 location + * --s3://sunstev-test/Input1.txt --s3://sunstev-test/Output1.txt (in your arguments section) */ private static final Pattern SPACE = Pattern.compile(" "); @@ -28,7 +34,7 @@ public static void main(String[] args) { SparkSession spark = SparkSession .builder() .appName("SparkJob") - .config("spark.master", "local") + .config("spark.master", "local")//keep this one commented out if you want to run in cluster mode .getOrCreate(); System.out.println("SparkSession is initated."); From 4b5b2f85f1d43f6957c4649ac881f9f7cb842b1d Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Tue, 18 May 2021 15:18:01 -0700 Subject: [PATCH 033/132] update run notes --- src/main/java/sparkExamples/JavaSparkPi.java | 11 +++++++++-- src/main/java/sparkExamples/SparkExample1.java | 3 ++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/main/java/sparkExamples/JavaSparkPi.java b/src/main/java/sparkExamples/JavaSparkPi.java index 2309e43..f634fe4 100644 --- a/src/main/java/sparkExamples/JavaSparkPi.java +++ b/src/main/java/sparkExamples/JavaSparkPi.java @@ -13,14 +13,21 @@ * Computes an approximation to pi * Usage: JavaSparkPi [slices] * - * TODO: it's throwing Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 28499 when running locally through Intellij. + * NOTE: it's throwing Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 28499 when running locally through Intellij. + * But it runs fine on AWS EMR, here's how to run it on AWS EMR: + * mvn package + * upload the compiled jar file: RandomJava-1.0-SNAPSHOT.jar to an S3 bucket + * click add steps to a ready cluster on AWS EMR + * --class sparkExamples.JavaSparkPi + * specify the jar in your S3 location */ public final class JavaSparkPi { public static void main(String[] args) throws Exception { SparkConf sparkConf = new SparkConf() .setAppName("JavaSparkPi") - .setMaster("local"); +// .setMaster("local")//uncomment this if you run it on AWS EMR in cluster mode + ; JavaSparkContext jsc = new JavaSparkContext(sparkConf); System.out.println("JavaSparkContext is initiated."); diff --git a/src/main/java/sparkExamples/SparkExample1.java b/src/main/java/sparkExamples/SparkExample1.java index e46893e..e03cf78 100644 --- a/src/main/java/sparkExamples/SparkExample1.java +++ b/src/main/java/sparkExamples/SparkExample1.java @@ -11,8 +11,9 @@ public class SparkExample1 { /** * How to run this program: - * 1. locally: mvn compile && mvn exec:java -Dexec.mainClass=sparkExamples.SparkExample1 -Dexec.args="sparkExamples/Input1.txt sparkExamples/Output1.txt" + * 1. locally: mvn package && mvn exec:java -Dexec.mainClass=sparkExamples.SparkExample1 -Dexec.args="sparkExamples/Input1.txt sparkExamples/Output1.txt" * 2. on AWS EMR cluster: + * mvn package * upload the compiled jar file: RandomJava-1.0-SNAPSHOT.jar to an S3 bucket * click add steps to a ready cluster on AWS EMR * --class sparkExamples.SparkExample1 From 1e50a4c6da7a82595c0853542d33f714b974241a Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Tue, 18 May 2021 15:43:51 -0700 Subject: [PATCH 034/132] update comment --- src/main/java/sparkExamples/SparkExample1.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/sparkExamples/SparkExample1.java b/src/main/java/sparkExamples/SparkExample1.java index e03cf78..c6f8a80 100644 --- a/src/main/java/sparkExamples/SparkExample1.java +++ b/src/main/java/sparkExamples/SparkExample1.java @@ -35,7 +35,7 @@ public static void main(String[] args) { SparkSession spark = SparkSession .builder() .appName("SparkJob") - .config("spark.master", "local")//keep this one commented out if you want to run in cluster mode +// .config("spark.master", "local")//keep this one commented out if you want to run in cluster mode .getOrCreate(); System.out.println("SparkSession is initated."); From 34e70bdeebb6fd1bd86d830d55c9d4bc2cf7ed7a Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Tue, 18 May 2021 15:44:14 -0700 Subject: [PATCH 035/132] add logging dependency --- pom.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pom.xml b/pom.xml index 5f7968e..37d654f 100644 --- a/pom.xml +++ b/pom.xml @@ -145,6 +145,11 @@ LATEST + + org.slf4j + slf4j-simple + 1.7.30 + From 9da1addd0396b75e6df83e7e08ce62beb46dda58 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Tue, 18 May 2021 16:28:31 -0700 Subject: [PATCH 036/132] add Spark Parquet example --- .../sparkExamples/JavaParquetExample1.java | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 src/main/java/sparkExamples/JavaParquetExample1.java diff --git a/src/main/java/sparkExamples/JavaParquetExample1.java b/src/main/java/sparkExamples/JavaParquetExample1.java new file mode 100644 index 0000000..f2f5da0 --- /dev/null +++ b/src/main/java/sparkExamples/JavaParquetExample1.java @@ -0,0 +1,49 @@ +package sparkExamples; + +import org.apache.spark.api.java.JavaRDD; +import org.apache.spark.sql.Dataset; +import org.apache.spark.sql.Row; +import org.apache.spark.sql.SparkSession; + +import java.util.Arrays; +import java.util.regex.Pattern; + +public class JavaParquetExample1 { + /** + * How to run this program: + * 1. locally: mvn package && mvn exec:java -Dexec.mainClass=sparkExamples.SparkExample1 -Dexec.args="sparkExamples/Input1.txt sparkExamples/Output1.txt" + * 2. on AWS EMR cluster: + * mvn package + * upload the compiled jar file: RandomJava-1.0-SNAPSHOT.jar to an S3 bucket + * click add steps to a ready cluster on AWS EMR + * --class sparkExamples.JavaParquetExample1 + * specify the jar in your S3 location + * --s3://sunstev-test/your-file.parquet (in your arguments section) + */ + + private static final Pattern SPACE = Pattern.compile(" "); + + public static void main(String[] args) { + System.out.println("Hello world!"); + System.out.println("args.length:" + args.length); + if (args.length > 0) { + Arrays.stream(args).map(arg -> "arg: " + arg).forEach(System.out::println); + } + try { + SparkSession spark = SparkSession + .builder() + .appName("SparkJob") + .config("spark.eventLog.enabled", "true") +// .config("spark.master", "local")//keep this one commented out if you want to run in cluster mode + .getOrCreate(); + System.out.println("SparkSession is initated."); + + Dataset parquetFileDF = spark.read().parquet(args[0]); + JavaRDD rdd = parquetFileDF.toJavaRDD(); + rdd.saveAsTextFile(args[1]); + } catch (Exception e) { + System.out.println("Caught exception when processing: " + e); + } + + } +} From 9d7c244b3a2f3c4ac3ad7a3b46fcb9cd6c9280ce Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Fri, 16 Jul 2021 10:39:27 -0700 Subject: [PATCH 037/132] add an example to illustrate method scope --- src/main/java/randomExamples/MainClass.java | 25 +++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 src/main/java/randomExamples/MainClass.java diff --git a/src/main/java/randomExamples/MainClass.java b/src/main/java/randomExamples/MainClass.java new file mode 100644 index 0000000..7fa1aaa --- /dev/null +++ b/src/main/java/randomExamples/MainClass.java @@ -0,0 +1,25 @@ +package randomExamples; + +public class MainClass { + + public static class A { + int a; + + public A(int a) { + this.a = a; + } + } + + public static void method1(A a) { + a = new A(2); + } + + public static void main(String... args) { + System.out.println("Program started."); + A a = new A(9); + System.out.println(a.a);//should print out 9 + method1(new A(10)); + System.out.println(a.a);//should print out 9 as well because as soon as the function method1's scope exits, the changed object of a within method1 undoes the change. + System.out.println("Program finished."); + } +} From 05918bb73f58774e8b6c70d4d63fdc0d4c30c53e Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Sat, 17 Jul 2021 16:43:42 -0700 Subject: [PATCH 038/132] rename file --- .../randomExamples/{MainClass.java => ClassInstance.java} | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) rename src/main/java/randomExamples/{MainClass.java => ClassInstance.java} (82%) diff --git a/src/main/java/randomExamples/MainClass.java b/src/main/java/randomExamples/ClassInstance.java similarity index 82% rename from src/main/java/randomExamples/MainClass.java rename to src/main/java/randomExamples/ClassInstance.java index 7fa1aaa..89fa1c0 100644 --- a/src/main/java/randomExamples/MainClass.java +++ b/src/main/java/randomExamples/ClassInstance.java @@ -1,6 +1,6 @@ package randomExamples; -public class MainClass { +public class ClassInstance { public static class A { int a; @@ -16,10 +16,11 @@ public static void method1(A a) { public static void main(String... args) { System.out.println("Program started."); - A a = new A(9); + ClassInstance.A a = new ClassInstance.A(9); System.out.println(a.a);//should print out 9 - method1(new A(10)); + method1(new ClassInstance.A(10)); System.out.println(a.a);//should print out 9 as well because as soon as the function method1's scope exits, the changed object of a within method1 undoes the change. System.out.println("Program finished."); } + } From c0f53fc0bfb2a2f391ffa668240178bb30e1d911 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Sat, 17 Jul 2021 16:47:29 -0700 Subject: [PATCH 039/132] add a size class to refresh CS basics --- src/main/java/randomExamples/Size.java | 99 ++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 src/main/java/randomExamples/Size.java diff --git a/src/main/java/randomExamples/Size.java b/src/main/java/randomExamples/Size.java new file mode 100644 index 0000000..714580b --- /dev/null +++ b/src/main/java/randomExamples/Size.java @@ -0,0 +1,99 @@ +package randomExamples; + +import java.io.UnsupportedEncodingException; + +public class Size { + public static void main(String... args) throws UnsupportedEncodingException { + System.out.println("Program started."); + System.out.println(Integer.MAX_VALUE);//2,147,483,647 + System.out.println(Integer.MIN_VALUE);//-2,147,483,648 + System.out.println(getByteBits());//8 + System.out.println(getShortBits());//16 + System.out.println(getIntegerBits());//32 + System.out.println(getLongBits());//64 + System.out.println(is64bit0());//check if the machine that this program runs on is 64-bit + System.out.println(Integer.toBinaryString(-1)); + System.out.println(Integer.toBinaryString(-1).length());//32 + System.out.println(Integer.toBinaryString(1).length());//1 + + // The input string for this test + final String string = "Hello World"; + + // Check length, in characters + System.out.println(string.length()); // prints "11" + + // Check encoded sizes + final byte[] utf8Bytes = string.getBytes("UTF-8"); + System.out.println(utf8Bytes.length); // prints "11" + + final byte[] utf16Bytes = string.getBytes("UTF-16"); + System.out.println(utf16Bytes.length); // prints "24" + + final byte[] utf32Bytes = string.getBytes("UTF-32"); + System.out.println(utf32Bytes.length); // prints "44" + + final byte[] isoBytes = string.getBytes("ISO-8859-1"); + System.out.println(isoBytes.length); // prints "11" + + final byte[] winBytes = string.getBytes("CP1252"); + System.out.println(winBytes.length); // prints "11" + + + System.out.println("Program finished."); + } + + private static boolean is64bit0() { + String systemProp = System.getProperty("com.ibm.vm.bitmode"); + if (systemProp != null) { + return "64".equals(systemProp); + } + systemProp = System.getProperty("sun.arch.data.model"); + if (systemProp != null) { + return "64".equals(systemProp); + } + systemProp = System.getProperty("java.vm.version"); + return systemProp != null && systemProp.contains("_64"); + } + + public static int getByteBits() { + int i = 1; + byte j = 1; + for (; (j = (byte) (j << 1)) > 0; i++) { + } + //Compensation of the sign bit 1 + return i + 1; + } + + public static int getShortBits() { + int i = 1; + short j = 1; + + for (; (j = (short) (j << 1)) > 0; i++) + ; + + //Compensation of the sign bit 1 + return i + 1; + } + + public static int getIntegerBits() { + int i = 1; + int j = 1; + + for (; (j = j << 1) > 0; i++) + ; + + //Compensation of the sign bit 1 + return i + 1; + } + + public static int getLongBits() { + int i = 1; + long j = 1; + + for (; (j = j << 1) > 0; i++) + ; + + //Compensation of the sign bit 1 + return i + 1; + } +} From 46407c06fd884cba186006d7f2c0250d13932683 Mon Sep 17 00:00:00 2001 From: Steve Sun Date: Sun, 1 Aug 2021 08:40:27 -0700 Subject: [PATCH 040/132] minor commit --- src/main/java/multithread/ThreadLocalExample.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/multithread/ThreadLocalExample.java b/src/main/java/multithread/ThreadLocalExample.java index 2a1d687..16c267a 100644 --- a/src/main/java/multithread/ThreadLocalExample.java +++ b/src/main/java/multithread/ThreadLocalExample.java @@ -23,7 +23,7 @@ public class ThreadLocalExample { public static class MyRunnable implements Runnable { - private ThreadLocal threadLocal = new ThreadLocal(); + private ThreadLocal threadLocal = new ThreadLocal<>(); @Override public void run() { From e3d1353dc75602f46a9db8fa173dc3bd202143d4 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Sun, 1 Aug 2021 08:43:16 -0700 Subject: [PATCH 041/132] add more comments --- .../java/multithread/ThreadLocalExample.java | 59 ++++++++++--------- 1 file changed, 31 insertions(+), 28 deletions(-) diff --git a/src/main/java/multithread/ThreadLocalExample.java b/src/main/java/multithread/ThreadLocalExample.java index 16c267a..ea31a38 100644 --- a/src/main/java/multithread/ThreadLocalExample.java +++ b/src/main/java/multithread/ThreadLocalExample.java @@ -5,45 +5,48 @@ * be read and written by the same thread. Thus, even if two threads are * executing the same code, and the code has a reference to a ThreadLocal * variable, then the two threads cannot see each other's ThreadLocal variables. - * + *

* Since values set on a ThreadLocal object only are visible to the thread who * set the value, no thread can set an initial value on a ThreadLocal using * set() which is visible to all threads. * Instead you can specify an initial value for a ThreadLocal object by * subclassing ThreadLocal and overriding the initialValue() method. Here is how * that looks: - * + *

* private ThreadLocal myThreadLocal = new ThreadLocal() { - * @Override - * protected String initialValue() { return "This is the initial value"; } + * + * @Override protected String initialValue() { return "This is the initial value"; } * }; */ public class ThreadLocalExample { - public static class MyRunnable implements Runnable { - - private ThreadLocal threadLocal = new ThreadLocal<>(); - - @Override - public void run() { - threadLocal.set((int) (Math.random() * 100D)); - try { - Thread.sleep(2000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - System.out.println("threadLocal.get() is: " + threadLocal.get()); - } - - public static void main(String... args) { - MyRunnable sharedRunnableInstance = new MyRunnable(); - Thread t1 = new Thread(sharedRunnableInstance); - Thread t2 = new Thread(sharedRunnableInstance); - - t1.start(); - t2.start(); - } - } + public static class MyRunnable implements Runnable { + + private ThreadLocal threadLocal = new ThreadLocal<>(); + + @Override + public void run() { + Integer value = (int) (Math.random() * 100D); + System.out.println("value = " + value); + threadLocal.set(value); + try { + Thread.sleep(2000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + System.out.println("threadLocal.get() is: " + threadLocal.get()); + } + + public static void main(String... args) { + System.out.println("Program started."); + MyRunnable sharedRunnableInstance = new MyRunnable(); + Thread t1 = new Thread(sharedRunnableInstance); + Thread t2 = new Thread(sharedRunnableInstance); + t1.start(); + t2.start(); + System.out.println("Program finished."); + } + } } From 5e2987cf0d0a316dda541211a73ced6ce6891553 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Fri, 6 Aug 2021 00:56:49 -0700 Subject: [PATCH 042/132] add a solution to an interesting problem --- .../distributeProceeds/Associate.java | 9 ++ .../DistributeProceedsService.java | 5 + .../DistributeProceedsServiceImpl.java | 92 +++++++++++++++++++ .../DistributionResponse.java | 11 +++ .../distributeProceeds/EntryClass.java | 44 +++++++++ .../distributeProceeds/GeneralPartner.java | 12 +++ .../distributeProceeds/ManagingPartner.java | 9 ++ .../PayOutAndShareClass.java | 19 ++++ .../distributeProceeds/PayoutAndPerson.java | 19 ++++ .../distributeProceeds/PayoutByPerson.java | 11 +++ .../PayoutByShareclass.java | 11 +++ .../distributeProceeds/Person.java | 45 +++++++++ .../distributeProceeds/Role.java | 9 ++ 13 files changed, 296 insertions(+) create mode 100644 src/main/java/interviewQuestions/distributeProceeds/Associate.java create mode 100644 src/main/java/interviewQuestions/distributeProceeds/DistributeProceedsService.java create mode 100644 src/main/java/interviewQuestions/distributeProceeds/DistributeProceedsServiceImpl.java create mode 100644 src/main/java/interviewQuestions/distributeProceeds/DistributionResponse.java create mode 100644 src/main/java/interviewQuestions/distributeProceeds/EntryClass.java create mode 100644 src/main/java/interviewQuestions/distributeProceeds/GeneralPartner.java create mode 100644 src/main/java/interviewQuestions/distributeProceeds/ManagingPartner.java create mode 100644 src/main/java/interviewQuestions/distributeProceeds/PayOutAndShareClass.java create mode 100644 src/main/java/interviewQuestions/distributeProceeds/PayoutAndPerson.java create mode 100644 src/main/java/interviewQuestions/distributeProceeds/PayoutByPerson.java create mode 100644 src/main/java/interviewQuestions/distributeProceeds/PayoutByShareclass.java create mode 100644 src/main/java/interviewQuestions/distributeProceeds/Person.java create mode 100644 src/main/java/interviewQuestions/distributeProceeds/Role.java diff --git a/src/main/java/interviewQuestions/distributeProceeds/Associate.java b/src/main/java/interviewQuestions/distributeProceeds/Associate.java new file mode 100644 index 0000000..5cade65 --- /dev/null +++ b/src/main/java/interviewQuestions/distributeProceeds/Associate.java @@ -0,0 +1,9 @@ +package interviewQuestions.distributeProceeds; + +public class Associate extends Role { + public static final String ASSOCIATE = "ASSOCIATE"; + + public Associate() { + this.name = ASSOCIATE; + } +} diff --git a/src/main/java/interviewQuestions/distributeProceeds/DistributeProceedsService.java b/src/main/java/interviewQuestions/distributeProceeds/DistributeProceedsService.java new file mode 100644 index 0000000..c496abb --- /dev/null +++ b/src/main/java/interviewQuestions/distributeProceeds/DistributeProceedsService.java @@ -0,0 +1,5 @@ +package interviewQuestions.distributeProceeds; + +public interface DistributeProceedsService { + DistributionResponse distributeProceeds(Double proceed); +} diff --git a/src/main/java/interviewQuestions/distributeProceeds/DistributeProceedsServiceImpl.java b/src/main/java/interviewQuestions/distributeProceeds/DistributeProceedsServiceImpl.java new file mode 100644 index 0000000..6952a9b --- /dev/null +++ b/src/main/java/interviewQuestions/distributeProceeds/DistributeProceedsServiceImpl.java @@ -0,0 +1,92 @@ +package interviewQuestions.distributeProceeds; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +public class DistributeProceedsServiceImpl implements DistributeProceedsService { + + private static final String ASSOCIATE = "ASSOCIATE"; + private static final String GENERAL_PARTNER = "GENERAL_PARTNER"; + private static final String MANAGING_PARTNER = "MANAGING_PARTNER"; + + private final List shareholders; + + public DistributeProceedsServiceImpl(List shareholders) { + this.shareholders = shareholders; + } + + public DistributionResponse distributeProceeds(Double proceed) { + Double totalClassBFunds = 0.0; + int totalClassBUnits = 0; + int totalUnits = 0; + for (Person person : shareholders) { + Map assumedRolesToShareCount = person.getAssumedRolesToShareCount(); + for (Role role : assumedRolesToShareCount.keySet()) { + if (role.name.equals(GENERAL_PARTNER)) { + totalClassBFunds += ((GeneralPartner) role).initInvestment; + totalClassBUnits += assumedRolesToShareCount.get(role); + } + totalUnits += assumedRolesToShareCount.get(role); + } + } + Double remaining = 0.0; + Double totalClassBProceeds; + if (proceed > totalClassBFunds) { + remaining = proceed - totalClassBFunds; + totalClassBProceeds = totalClassBFunds; + } else { + totalClassBProceeds = proceed; + } + //distribute to ClassB holders first + for (Person person : shareholders) { + Map assumedRolesToShareCount = person.getAssumedRolesToShareCount(); + for (Role role : assumedRolesToShareCount.keySet()) { + if (role.getName().equals(GENERAL_PARTNER)) { + Double percentage = assumedRolesToShareCount.get(role) * 1.0 / totalClassBUnits; + double classBProceed = percentage * totalClassBProceeds; + Map assumedRolesAndProceeds = person.getAssumedRolesAndProceeds(); + assumedRolesAndProceeds.put(role, classBProceed); + person.setAssumedRolesAndProceeds(assumedRolesAndProceeds); + break; + } + } + } + Double totalClassAProceeds = 0.0; + Double totalClassCProceeds = 0.0; + if (remaining > 0) { + //distribute among all classes if there's any remaining + for (Person person : shareholders) { + Map assumedRolesToShareCount = person.getAssumedRolesToShareCount(); + for (Role role : assumedRolesToShareCount.keySet()) { + Double percentage = assumedRolesToShareCount.get(role) * 1.0 / totalUnits; + Double classProceeds = 0.0; + if (role.getName().equals(ASSOCIATE)) { + classProceeds = percentage * remaining; + totalClassAProceeds += classProceeds; + } else if (role.getName().equals(MANAGING_PARTNER)) { + classProceeds = percentage * remaining; + totalClassCProceeds += classProceeds; + } else if (role.getName().equals(GENERAL_PARTNER)) { + classProceeds = percentage * remaining; + totalClassBProceeds += classProceeds; + } + Map assumedRolesAndProceeds = person.getAssumedRolesAndProceeds(); + assumedRolesAndProceeds.put(role, assumedRolesAndProceeds.getOrDefault(role, 0.0) + classProceeds); + person.setAssumedRolesAndProceeds(assumedRolesAndProceeds); + } + } + } + + List payOutAndShareClassList = Arrays.asList( + new PayOutAndShareClass(Math.round(totalClassAProceeds * 100) / 100.0, "Class A"), + new PayOutAndShareClass(Math.round(totalClassBProceeds * 100) / 100.0, "Class B"), + new PayOutAndShareClass(Math.round(totalClassCProceeds * 100) / 100.0, "Class C")); + List payoutAndPersonList = shareholders.stream().map(person -> new PayoutAndPerson(person.getName(), person.getTotalPayout())).collect(Collectors.toList()); + DistributionResponse distributionResponse = new DistributionResponse( + new PayoutByPerson(payoutAndPersonList), new PayoutByShareclass(payOutAndShareClassList)); + return distributionResponse; + } + +} diff --git a/src/main/java/interviewQuestions/distributeProceeds/DistributionResponse.java b/src/main/java/interviewQuestions/distributeProceeds/DistributionResponse.java new file mode 100644 index 0000000..750eeee --- /dev/null +++ b/src/main/java/interviewQuestions/distributeProceeds/DistributionResponse.java @@ -0,0 +1,11 @@ +package interviewQuestions.distributeProceeds; + +public class DistributionResponse { + public DistributionResponse(PayoutByPerson payoutByPerson, PayoutByShareclass payoutByShareclass) { + this.payoutByPerson = payoutByPerson; + this.payoutByShareclass = payoutByShareclass; + } + + PayoutByPerson payoutByPerson; + PayoutByShareclass payoutByShareclass; +} diff --git a/src/main/java/interviewQuestions/distributeProceeds/EntryClass.java b/src/main/java/interviewQuestions/distributeProceeds/EntryClass.java new file mode 100644 index 0000000..e82ba5b --- /dev/null +++ b/src/main/java/interviewQuestions/distributeProceeds/EntryClass.java @@ -0,0 +1,44 @@ +package interviewQuestions.distributeProceeds; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +public class EntryClass { + + public static void main(String... args) { + EntryClass entryClass = new EntryClass(); + List shareholders = entryClass.initShareholders(); + DistributeProceedsService distributeProceedsService = new DistributeProceedsServiceImpl(shareholders); + if (args.length > 0) { + System.out.println(args[0]); + System.out.println(distributeProceedsService.distributeProceeds(Double.parseDouble(args[0]))); + } + DistributionResponse response = distributeProceedsService.distributeProceeds(1000.0); + List payoutAndPersonList = response.payoutByPerson.payoutAndPersonList; + System.out.println(payoutAndPersonList.toString()); + List payOutAndShareClassList = response.payoutByShareclass.payOutAndShareClassList; + System.out.println(payOutAndShareClassList.toString()); + System.out.println("Finished running the program."); + } + + private List initShareholders() { + Person alex = new Person("Alex"); + Map alexRoles = alex.getAssumedRolesToShareCount(); + alexRoles.put(new GeneralPartner(250l), 10); + alex.setAssumedRoles(alexRoles); + + Person becky = new Person("Becky"); + Map beckyRoles = becky.getAssumedRolesToShareCount(); + beckyRoles.put(new GeneralPartner(250l), 10); + beckyRoles.put(new ManagingPartner(), 5); + becky.setAssumedRoles(beckyRoles); + + Person david = new Person("David"); + Map davidRoles = david.getAssumedRolesToShareCount(); + davidRoles.put(new Associate(), 10); + david.setAssumedRoles(davidRoles); + + return Arrays.asList(alex, becky, david); + } +} diff --git a/src/main/java/interviewQuestions/distributeProceeds/GeneralPartner.java b/src/main/java/interviewQuestions/distributeProceeds/GeneralPartner.java new file mode 100644 index 0000000..81348f8 --- /dev/null +++ b/src/main/java/interviewQuestions/distributeProceeds/GeneralPartner.java @@ -0,0 +1,12 @@ +package interviewQuestions.distributeProceeds; + +public class GeneralPartner extends Role { + public static final String GENERAL_PARTNER = "GENERAL_PARTNER"; + + public GeneralPartner(Long initInvestment) { + this.initInvestment = initInvestment; + this.name = GENERAL_PARTNER; + } + + Long initInvestment; +} diff --git a/src/main/java/interviewQuestions/distributeProceeds/ManagingPartner.java b/src/main/java/interviewQuestions/distributeProceeds/ManagingPartner.java new file mode 100644 index 0000000..7a47abe --- /dev/null +++ b/src/main/java/interviewQuestions/distributeProceeds/ManagingPartner.java @@ -0,0 +1,9 @@ +package interviewQuestions.distributeProceeds; + +public class ManagingPartner extends Role { + public static final String MANAGING_PARTNER = "MANAGING_PARTNER"; + + public ManagingPartner() { + this.name = MANAGING_PARTNER; + } +} diff --git a/src/main/java/interviewQuestions/distributeProceeds/PayOutAndShareClass.java b/src/main/java/interviewQuestions/distributeProceeds/PayOutAndShareClass.java new file mode 100644 index 0000000..e56d7a3 --- /dev/null +++ b/src/main/java/interviewQuestions/distributeProceeds/PayOutAndShareClass.java @@ -0,0 +1,19 @@ +package interviewQuestions.distributeProceeds; + +public class PayOutAndShareClass { + Double payoutAmount; + String shareClass; + + public PayOutAndShareClass(Double payoutAmount, String shareClass) { + this.payoutAmount = payoutAmount; + this.shareClass = shareClass; + } + + @Override + public String toString() { + return "PayOutAndShareClass{" + + "payoutAmount=" + payoutAmount + + ", shareClass='" + shareClass + '\'' + + '}'; + } +} diff --git a/src/main/java/interviewQuestions/distributeProceeds/PayoutAndPerson.java b/src/main/java/interviewQuestions/distributeProceeds/PayoutAndPerson.java new file mode 100644 index 0000000..b0ae0b2 --- /dev/null +++ b/src/main/java/interviewQuestions/distributeProceeds/PayoutAndPerson.java @@ -0,0 +1,19 @@ +package interviewQuestions.distributeProceeds; + +public class PayoutAndPerson { + String name; + Double payoutAmount; + + public PayoutAndPerson(String name, Double payoutAmount) { + this.name = name; + this.payoutAmount = payoutAmount; + } + + @Override + public String toString() { + return "PayoutAndPerson{" + + "name='" + name + '\'' + + ", payoutAmount=" + payoutAmount + + '}'; + } +} diff --git a/src/main/java/interviewQuestions/distributeProceeds/PayoutByPerson.java b/src/main/java/interviewQuestions/distributeProceeds/PayoutByPerson.java new file mode 100644 index 0000000..259c107 --- /dev/null +++ b/src/main/java/interviewQuestions/distributeProceeds/PayoutByPerson.java @@ -0,0 +1,11 @@ +package interviewQuestions.distributeProceeds; + +import java.util.List; + +public class PayoutByPerson { + List payoutAndPersonList; + + public PayoutByPerson(List payoutAndPersonList) { + this.payoutAndPersonList = payoutAndPersonList; + } +} diff --git a/src/main/java/interviewQuestions/distributeProceeds/PayoutByShareclass.java b/src/main/java/interviewQuestions/distributeProceeds/PayoutByShareclass.java new file mode 100644 index 0000000..5151e87 --- /dev/null +++ b/src/main/java/interviewQuestions/distributeProceeds/PayoutByShareclass.java @@ -0,0 +1,11 @@ +package interviewQuestions.distributeProceeds; + +import java.util.List; + +public class PayoutByShareclass { + List payOutAndShareClassList; + + public PayoutByShareclass(List payOutAndShareClassList) { + this.payOutAndShareClassList = payOutAndShareClassList; + } +} diff --git a/src/main/java/interviewQuestions/distributeProceeds/Person.java b/src/main/java/interviewQuestions/distributeProceeds/Person.java new file mode 100644 index 0000000..dd1fa52 --- /dev/null +++ b/src/main/java/interviewQuestions/distributeProceeds/Person.java @@ -0,0 +1,45 @@ +package interviewQuestions.distributeProceeds; + +import java.util.HashMap; +import java.util.Map; + +public class Person { + + private String name; + private Map assumedRolesAndShareCount; + private Map assumedRolesAndProceeds; + + public void setAssumedRolesAndProceeds(Map assumedRolesAndProceeds) { + this.assumedRolesAndProceeds = assumedRolesAndProceeds; + } + + public String getName() { + return name; + } + + public Map getAssumedRolesAndProceeds() { + return this.assumedRolesAndProceeds; + } + + public void setAssumedRoles(Map assumedRoles) { + this.assumedRolesAndShareCount = assumedRoles; + } + + public Map getAssumedRolesToShareCount() { + return this.assumedRolesAndShareCount; + } + + public Person(String name) { + this.name = name; + this.assumedRolesAndShareCount = new HashMap<>(); + this.assumedRolesAndProceeds = new HashMap<>(); + } + + public Double getTotalPayout() { + Double total = 0.0; + for (Role role : this.assumedRolesAndProceeds.keySet()) { + total += assumedRolesAndProceeds.get(role); + } + return Math.round(total * 100) / 100.0; + } +} diff --git a/src/main/java/interviewQuestions/distributeProceeds/Role.java b/src/main/java/interviewQuestions/distributeProceeds/Role.java new file mode 100644 index 0000000..7dc17f6 --- /dev/null +++ b/src/main/java/interviewQuestions/distributeProceeds/Role.java @@ -0,0 +1,9 @@ +package interviewQuestions.distributeProceeds; + +public abstract class Role { + public String name; + + public String getName() { + return this.name; + } +} From 03f2fd42e13ed0cf70976b46cc063b34e7dfa980 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 14 Dec 2021 20:28:02 +0000 Subject: [PATCH 043/132] Bump log4j-api from 2.7 to 2.16.0 Bumps log4j-api from 2.7 to 2.16.0. --- updated-dependencies: - dependency-name: org.apache.logging.log4j:log4j-api dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 37d654f..e7f02a6 100644 --- a/pom.xml +++ b/pom.xml @@ -26,7 +26,7 @@ org.apache.logging.log4j log4j-api - 2.7 + 2.16.0 org.apache.logging.log4j From 5e4180925eca27fc686f0b1592697cac1ef35b27 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 14 Dec 2021 21:05:17 +0000 Subject: [PATCH 044/132] Bump log4j-core from 2.13.2 to 2.16.0 Bumps log4j-core from 2.13.2 to 2.16.0. --- updated-dependencies: - dependency-name: org.apache.logging.log4j:log4j-core dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 37d654f..138e06e 100644 --- a/pom.xml +++ b/pom.xml @@ -31,7 +31,7 @@ org.apache.logging.log4j log4j-core - 2.13.2 + 2.16.0 From c369d1b89d7ae56b9ed2e769aa5c1ee5ce4dfe61 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 18 Dec 2021 18:02:31 +0000 Subject: [PATCH 045/132] Bump log4j-api from 2.16.0 to 2.17.0 Bumps log4j-api from 2.16.0 to 2.17.0. --- updated-dependencies: - dependency-name: org.apache.logging.log4j:log4j-api dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 1673951..950f150 100644 --- a/pom.xml +++ b/pom.xml @@ -26,7 +26,7 @@ org.apache.logging.log4j log4j-api - 2.16.0 + 2.17.0 org.apache.logging.log4j From d8229a0ad525a82f000361948e49096c1ca5a7f0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 18 Dec 2021 18:03:28 +0000 Subject: [PATCH 046/132] Bump log4j-core from 2.16.0 to 2.17.0 Bumps log4j-core from 2.16.0 to 2.17.0. --- updated-dependencies: - dependency-name: org.apache.logging.log4j:log4j-core dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 1673951..6f6c9fb 100644 --- a/pom.xml +++ b/pom.xml @@ -31,7 +31,7 @@ org.apache.logging.log4j log4j-core - 2.16.0 + 2.17.0 From 60c729158ef12c6b73ac4fd56c96245b8635fd07 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 4 Jan 2022 16:30:46 +0000 Subject: [PATCH 047/132] Bump log4j-core from 2.17.0 to 2.17.1 Bumps log4j-core from 2.17.0 to 2.17.1. --- updated-dependencies: - dependency-name: org.apache.logging.log4j:log4j-core dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 683614b..d8ad7b9 100644 --- a/pom.xml +++ b/pom.xml @@ -31,7 +31,7 @@ org.apache.logging.log4j log4j-core - 2.17.0 + 2.17.1 From 1e6912a4860eccb266fd05fc3b7a4fb96cd32338 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 4 Jan 2022 16:30:56 +0000 Subject: [PATCH 048/132] Bump log4j-api from 2.17.0 to 2.17.1 Bumps log4j-api from 2.17.0 to 2.17.1. --- updated-dependencies: - dependency-name: org.apache.logging.log4j:log4j-api dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 683614b..b4fed04 100644 --- a/pom.xml +++ b/pom.xml @@ -26,7 +26,7 @@ org.apache.logging.log4j log4j-api - 2.17.0 + 2.17.1 org.apache.logging.log4j From c701d40ed8c735907b0262a8258462b60fe990ad Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 31 Mar 2022 18:34:55 +0000 Subject: [PATCH 049/132] Bump spring-webmvc from 4.1.6.RELEASE to 5.3.18 Bumps [spring-webmvc](https://github.com/spring-projects/spring-framework) from 4.1.6.RELEASE to 5.3.18. - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v4.1.6.RELEASE...v5.3.18) --- updated-dependencies: - dependency-name: org.springframework:spring-webmvc dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 41767bb..2fcdca3 100644 --- a/pom.xml +++ b/pom.xml @@ -68,7 +68,7 @@ org.springframework spring-webmvc - 4.1.6.RELEASE + 5.3.18 org.springframework @@ -170,6 +177,12 @@ 1.5.1 test + + org.testng + testng + RELEASE + test + diff --git a/src/main/java/guice/relearn_2019_09/_8_already_configured_exception/PrivateModuleTest.java b/src/main/java/guice/relearn_2019_09/_8_already_configured_exception/PrivateModuleTest.java index 4cc0551..9a69a98 100644 --- a/src/main/java/guice/relearn_2019_09/_8_already_configured_exception/PrivateModuleTest.java +++ b/src/main/java/guice/relearn_2019_09/_8_already_configured_exception/PrivateModuleTest.java @@ -1,32 +1,18 @@ package guice.relearn_2019_09._8_already_configured_exception; -import static com.google.inject.name.Names.named; - -import com.google.inject.AbstractModule; -import com.google.inject.ConfigurationException; -import com.google.inject.CreationException; -import com.google.inject.Exposed; -import com.google.inject.Guice; -import com.google.inject.Inject; -import com.google.inject.Injector; -import com.google.inject.Key; -import com.google.inject.PrivateBinder; -import com.google.inject.PrivateModule; -import com.google.inject.Provider; -import com.google.inject.Provides; +import com.google.inject.*; import com.google.inject.name.Named; import com.google.inject.name.Names; -import com.google.inject.spi.Dependency; import com.google.inject.spi.ExposedBinding; -import com.google.inject.spi.PrivateElements; import com.google.inject.util.Types; - import junit.framework.TestCase; import java.util.ArrayList; import java.util.Collection; import java.util.List; +import static com.google.inject.name.Names.named; + public class PrivateModuleTest extends TestCase { public void testBasicUsage() { diff --git a/src/test/b2SdkExamples/B2JsonTest.java b/src/test/b2SdkExamples/B2JsonTest.java index b8e645b..3181255 100644 --- a/src/test/b2SdkExamples/B2JsonTest.java +++ b/src/test/b2SdkExamples/B2JsonTest.java @@ -5,7 +5,7 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; import org.json.JSONException; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.skyscreamer.jsonassert.JSONAssert; import java.math.BigDecimal; @@ -13,8 +13,8 @@ import java.time.LocalDateTime; import java.util.*; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThrows; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; /** * Reference: https://github.com/Backblaze/b2-sdk-java/blob/0ecd68df94691cbba5a6af363246b7193aead234/core/src/test/java/com/backblaze/b2/json/B2JsonTest.java From 61a75bac35f33704eb96ede7cc41fbf8b1419f1c Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Sat, 3 Jun 2023 15:23:48 -0700 Subject: [PATCH 078/132] add more junit 5 tests --- pom.xml | 9 +++- src/test/junit5/Junit5Test.java | 77 +++++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+), 2 deletions(-) create mode 100644 src/test/junit5/Junit5Test.java diff --git a/pom.xml b/pom.xml index d4c8467..fab1182 100644 --- a/pom.xml +++ b/pom.xml @@ -50,8 +50,13 @@ org.junit.jupiter junit-jupiter-engine - 5.9.1 - test + 5.9.2 + + + + org.junit.jupiter + junit-jupiter-params + 5.9.0 diff --git a/src/test/junit5/Junit5Test.java b/src/test/junit5/Junit5Test.java new file mode 100644 index 0000000..ff12e84 --- /dev/null +++ b/src/test/junit5/Junit5Test.java @@ -0,0 +1,77 @@ +package junit5; + +import org.apache.logging.log4j.util.Strings; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.stream.Stream; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +public class Junit5Test { + @BeforeAll + static void setup() { + System.out.println("@BeforeAll - executes once before all test methods in this class"); + } + + @BeforeEach + void init() { + System.out.println("@BeforeEach - executes before each test method in this class"); + } + + @DisplayName("Single test successful") + @Test + void testSingleSuccessTest() { + System.out.println("Success"); + assertEquals(5 + 2, 7); + } + + @Test + void shouldThrowException() { + Throwable exception = assertThrows(UnsupportedOperationException.class, () -> { + throw new UnsupportedOperationException("Not supported"); + }); + assertEquals("Not supported", exception.getMessage()); + } + + @Test + void assertThrowsException() { + String str = null; + assertThrows(IllegalArgumentException.class, () -> { + Integer.valueOf(str); + }); + } + + @ParameterizedTest + @MethodSource("data") + public void parameterizedTest(String input, boolean expected) { + assertEquals(expected, Strings.isBlank(input)); + } + + private static Stream data() { + return Stream.of( + Arguments.of(null, true), + Arguments.of("", true), + Arguments.of(" ", true), + Arguments.of("not blank", false) + ); + } + + @AfterEach + void tearDown() { + System.out.println("@AfterEach - executed after each test method."); + } + + @AfterAll + static void done() { + System.out.println("@AfterAll - executed after all test methods."); + } +} From f90ad28aed39556f560a4fa45aa7df85e66a5d6a Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Sun, 4 Jun 2023 09:31:25 -0700 Subject: [PATCH 079/132] add more print out to help understand --- src/test/junit5/Junit5Test.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/test/junit5/Junit5Test.java b/src/test/junit5/Junit5Test.java index ff12e84..e8e5bea 100644 --- a/src/test/junit5/Junit5Test.java +++ b/src/test/junit5/Junit5Test.java @@ -30,12 +30,13 @@ void init() { @DisplayName("Single test successful") @Test void testSingleSuccessTest() { - System.out.println("Success"); + System.out.println("in testSingleSuccessTest"); assertEquals(5 + 2, 7); } @Test void shouldThrowException() { + System.out.println("in shouldThrowException"); Throwable exception = assertThrows(UnsupportedOperationException.class, () -> { throw new UnsupportedOperationException("Not supported"); }); @@ -44,6 +45,7 @@ void shouldThrowException() { @Test void assertThrowsException() { + System.out.println("in assertThrowsException"); String str = null; assertThrows(IllegalArgumentException.class, () -> { Integer.valueOf(str); @@ -53,6 +55,7 @@ void assertThrowsException() { @ParameterizedTest @MethodSource("data") public void parameterizedTest(String input, boolean expected) { + System.out.println("input is: " + input + ", expected is: " + expected); assertEquals(expected, Strings.isBlank(input)); } From 5a2420cc5310c8e7bfd537afce5e58d014a68789 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Sat, 29 Jul 2023 13:37:47 -0700 Subject: [PATCH 080/132] use try to create B2StorageClient --- src/main/java/b2SdkExamples/B2SdkExamples.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/b2SdkExamples/B2SdkExamples.java b/src/main/java/b2SdkExamples/B2SdkExamples.java index 25f51af..de7df71 100644 --- a/src/main/java/b2SdkExamples/B2SdkExamples.java +++ b/src/main/java/b2SdkExamples/B2SdkExamples.java @@ -19,8 +19,10 @@ public static void main(String... args) throws B2Exception { // B2StorageClient client = B2StorageClientFactory.createDefaultFactory().create(USER_AGENT); //set up B2 CLI //and then use b2 get-account-info to get applicationKeyId and applicationKey to fill in here and run - B2StorageClient client = B2StorageClientFactory.createDefaultFactory().create(APPLICATION_KEY_ID, APPLICATION_KEY, USER_AGENT); - B2ListBucketsResponse b2ListBucketsResponse = client.listBuckets(); + B2ListBucketsResponse b2ListBucketsResponse; + try (B2StorageClient client = B2StorageClientFactory.createDefaultFactory().create(APPLICATION_KEY_ID, APPLICATION_KEY, USER_AGENT)) { + b2ListBucketsResponse = client.listBuckets(); + } List buckets = b2ListBucketsResponse.getBuckets(); System.out.println("buckets.size() is: " + buckets.size()); for (B2Bucket b2Bucket : buckets) { From 25b6b82469da997ee9a352d19d69c41e2b30e20f Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Sun, 30 Jul 2023 16:21:34 -0700 Subject: [PATCH 081/132] call to get Backblaze Account ID --- .../java/b2SdkExamples/B2SdkExamples.java | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/main/java/b2SdkExamples/B2SdkExamples.java b/src/main/java/b2SdkExamples/B2SdkExamples.java index de7df71..b2c69a7 100644 --- a/src/main/java/b2SdkExamples/B2SdkExamples.java +++ b/src/main/java/b2SdkExamples/B2SdkExamples.java @@ -9,9 +9,9 @@ import java.util.List; public class B2SdkExamples { - private static final String APPLICATION_KEY_ID = "xxx"; private static final String APPLICATION_KEY = "yyy"; + private static final String USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36"; public static void main(String... args) throws B2Exception { @@ -20,14 +20,16 @@ public static void main(String... args) throws B2Exception { //set up B2 CLI //and then use b2 get-account-info to get applicationKeyId and applicationKey to fill in here and run B2ListBucketsResponse b2ListBucketsResponse; - try (B2StorageClient client = B2StorageClientFactory.createDefaultFactory().create(APPLICATION_KEY_ID, APPLICATION_KEY, USER_AGENT)) { - b2ListBucketsResponse = client.listBuckets(); - } - List buckets = b2ListBucketsResponse.getBuckets(); - System.out.println("buckets.size() is: " + buckets.size()); - for (B2Bucket b2Bucket : buckets) { - System.out.println("this bucket info is: " + b2Bucket.getBucketInfo()); - System.out.println("this bucket getBucketName is: " + b2Bucket.getBucketName()); + try (B2StorageClient b2StorageClient = B2StorageClientFactory.createDefaultFactory().create(APPLICATION_KEY_ID, APPLICATION_KEY, USER_AGENT)) { + b2ListBucketsResponse = b2StorageClient.listBuckets(); + List buckets = b2ListBucketsResponse.getBuckets(); + System.out.println("buckets.size() is: " + buckets.size()); + for (B2Bucket b2Bucket : buckets) { + System.out.println("this bucket info is: " + b2Bucket.getBucketInfo()); + System.out.println("this bucket getBucketName is: " + b2Bucket.getBucketName()); + } + String b2AccountId = b2StorageClient.getAccountId(); + System.out.println("b2AccountId is: " + b2AccountId); } System.out.println("Finished running in main method."); } From cbfb342a3397e508f7f1f63927f3e82d82e00de4 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Sun, 6 Aug 2023 16:51:56 -0700 Subject: [PATCH 082/132] add String.Format example --- .../java/javaSDKExamples/StringFormatAPI.java | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 src/main/java/javaSDKExamples/StringFormatAPI.java diff --git a/src/main/java/javaSDKExamples/StringFormatAPI.java b/src/main/java/javaSDKExamples/StringFormatAPI.java new file mode 100644 index 0000000..1eaee91 --- /dev/null +++ b/src/main/java/javaSDKExamples/StringFormatAPI.java @@ -0,0 +1,28 @@ +package javaSDKExamples; + +public class StringFormatAPI { + + public static void main(String... args) { + /**https://www.javatpoint.com/java-string-format + * %d decimal integer + * %x hex string, %06x means padding up to 6 leading zeroes to make it 6 digits + * %s string value + * + * */ + final String actual = String.format( + "coolString%d%c%02d%02d%02d%02d%06x%012x%s%s", + 1, + 'a', + 17, + 3, + 9, + 3, + 1234, + 1234567890, + "4_abc_12", + "" + ); + System.out.println("actual is: " + actual); + } + +} From e785cce43c2b0506d759f89c3b7eafac24fd51b2 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Fri, 18 Aug 2023 18:37:13 -0700 Subject: [PATCH 083/132] remove type in declaration --- .../java_async_method_example/async/method/SyncClientImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/java_async_method_example/async/method/SyncClientImpl.java b/src/main/java/java_async_method_example/async/method/SyncClientImpl.java index 2dd400f..bf1e722 100644 --- a/src/main/java/java_async_method_example/async/method/SyncClientImpl.java +++ b/src/main/java/java_async_method_example/async/method/SyncClientImpl.java @@ -14,7 +14,7 @@ public class SyncClientImpl implements SyncClient { @Override public void executeSynchronous(String userId) { - List> list = new ArrayList>(); + List> list = new ArrayList<>(); Callable callable = new Task(userId); From 5a7cc87e57231ad71857b699e978e462d76c88e8 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Sat, 19 Aug 2023 20:22:47 -0700 Subject: [PATCH 084/132] clean up old code --- .../async/method/AsyncClient.java | 8 ----- .../async/method/AsyncClientImpl.java | 36 ------------------- .../async/method/MainApp.java | 16 ++------- .../async/method/SyncClient.java | 6 ---- .../async/method/SyncClientImpl.java | 36 ------------------- .../async/method/Task.java | 19 ---------- .../future/MainApp.java | 4 +-- 7 files changed, 5 insertions(+), 120 deletions(-) delete mode 100644 src/main/java/java_async_method_example/async/method/AsyncClient.java delete mode 100644 src/main/java/java_async_method_example/async/method/AsyncClientImpl.java delete mode 100644 src/main/java/java_async_method_example/async/method/SyncClient.java delete mode 100644 src/main/java/java_async_method_example/async/method/SyncClientImpl.java delete mode 100644 src/main/java/java_async_method_example/async/method/Task.java diff --git a/src/main/java/java_async_method_example/async/method/AsyncClient.java b/src/main/java/java_async_method_example/async/method/AsyncClient.java deleted file mode 100644 index 6e1fe8f..0000000 --- a/src/main/java/java_async_method_example/async/method/AsyncClient.java +++ /dev/null @@ -1,8 +0,0 @@ -package java_async_method_example.async.method; - -public interface AsyncClient { - - // for asynchronous - public void executeAsynchronous(final String userId); - -} diff --git a/src/main/java/java_async_method_example/async/method/AsyncClientImpl.java b/src/main/java/java_async_method_example/async/method/AsyncClientImpl.java deleted file mode 100644 index a466d99..0000000 --- a/src/main/java/java_async_method_example/async/method/AsyncClientImpl.java +++ /dev/null @@ -1,36 +0,0 @@ -package java_async_method_example.async.method; - -import java.util.ArrayList; -import java.util.Date; -import java.util.List; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; - -public class AsyncClientImpl implements AsyncClient { - ExecutorService executor = Executors.newFixedThreadPool(3); - - @Override - public void executeAsynchronous(String userId) { - List> list = new ArrayList>(); - - Callable callable = new Task(userId); - - for(int i = 0; i < 10; i++) { - Future future = executor.submit(callable); - list.add(future); - } - - for(Future future : list){ - try { - System.out.println(new Date() + " " + future.get()); - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); - } - } - System.out.println("That's the end of the executeAsynchronous method!"); - executor.shutdown(); - } -} diff --git a/src/main/java/java_async_method_example/async/method/MainApp.java b/src/main/java/java_async_method_example/async/method/MainApp.java index f8ad438..a470ae1 100644 --- a/src/main/java/java_async_method_example/async/method/MainApp.java +++ b/src/main/java/java_async_method_example/async/method/MainApp.java @@ -1,18 +1,8 @@ package java_async_method_example.async.method; -/**This package was used to demo the difference between sync and async methods, but right now, there's really no difference between the impl of SyncClientImpl and AsyncClientImpl classes, - * I need to rewrite them to deepen my understanding!*/ public class MainApp { - public static void main(String... args) { - SyncClient syncClient = new SyncClientImpl(); - - syncClient.executeSynchronous("this is executing synchronous method!"); - - AsyncClient asyncClient = new AsyncClientImpl(); - asyncClient - .executeAsynchronous("this is executing Asynchronous method!"); - - System.out.println("That's the end of MainApp!"); - } + public static void main(String... args) { + System.out.println("That's the end of MainApp!"); + } } diff --git a/src/main/java/java_async_method_example/async/method/SyncClient.java b/src/main/java/java_async_method_example/async/method/SyncClient.java deleted file mode 100644 index 97418ad..0000000 --- a/src/main/java/java_async_method_example/async/method/SyncClient.java +++ /dev/null @@ -1,6 +0,0 @@ -package java_async_method_example.async.method; - -public interface SyncClient { - // for synchronous - void executeSynchronous(final String userId); -} diff --git a/src/main/java/java_async_method_example/async/method/SyncClientImpl.java b/src/main/java/java_async_method_example/async/method/SyncClientImpl.java deleted file mode 100644 index bf1e722..0000000 --- a/src/main/java/java_async_method_example/async/method/SyncClientImpl.java +++ /dev/null @@ -1,36 +0,0 @@ -package java_async_method_example.async.method; - -import java.util.ArrayList; -import java.util.Date; -import java.util.List; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; - -public class SyncClientImpl implements SyncClient { - ExecutorService executor = Executors.newFixedThreadPool(3); - - @Override - public void executeSynchronous(String userId) { - List> list = new ArrayList<>(); - - Callable callable = new Task(userId); - - for(int i = 0; i < 10; i++) { - Future future = executor.submit(callable); - list.add(future); - } - - for(Future future : list){ - try { - System.out.println(new Date() + " " + future.get()); - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); - } - } - executor.shutdown(); - System.out.println("That's the end of the executeSynchronous method!"); - } -} diff --git a/src/main/java/java_async_method_example/async/method/Task.java b/src/main/java/java_async_method_example/async/method/Task.java deleted file mode 100644 index 9517d41..0000000 --- a/src/main/java/java_async_method_example/async/method/Task.java +++ /dev/null @@ -1,19 +0,0 @@ -package java_async_method_example.async.method; - -import java.util.concurrent.Callable; - -public class Task implements Callable { - - private final String userId; - - public Task(String userId) { - this.userId = userId; - } - - @Override - public String call() throws Exception { - Thread.sleep(1500); - return Thread.currentThread().getName() + " " + userId; - } - -} diff --git a/src/main/java/java_async_method_example/future/MainApp.java b/src/main/java/java_async_method_example/future/MainApp.java index cd94c55..c4e2692 100644 --- a/src/main/java/java_async_method_example/future/MainApp.java +++ b/src/main/java/java_async_method_example/future/MainApp.java @@ -17,10 +17,10 @@ public static void main(String... args) { // Executors.newSingleThreadExecutor() // Executors.newCachedThreadPool() Executors.newScheduledThreadPool(15); - /**thread pool account could be a bottleneck when it's smaller than 10 which is the max in the below for loop. + /**thread pool count could be a bottleneck when it's smaller than 10 which is the max in the below for loop. * so when I changed the ThreadPool size to 15, then ALL Future objects got returned at the same time! Cool!*/ - List> list = new ArrayList>(); + List> list = new ArrayList<>(); Callable callable = new MyCallable(); From 0a5b06a3cd6c1017ffd2b76a740d718a30c480ed Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Sun, 20 Aug 2023 14:31:58 -0700 Subject: [PATCH 085/132] add multithreading example in Java --- .../MultiThreadedApp.java | 62 +++++++++++++++++++ .../SingleThreadedApp.java | 31 ++++++++++ 2 files changed, 93 insertions(+) create mode 100644 src/main/java/multithread/singlevsmultiplethreads/MultiThreadedApp.java create mode 100644 src/main/java/multithread/singlevsmultiplethreads/SingleThreadedApp.java diff --git a/src/main/java/multithread/singlevsmultiplethreads/MultiThreadedApp.java b/src/main/java/multithread/singlevsmultiplethreads/MultiThreadedApp.java new file mode 100644 index 0000000..981f314 --- /dev/null +++ b/src/main/java/multithread/singlevsmultiplethreads/MultiThreadedApp.java @@ -0,0 +1,62 @@ +package multithread.singlevsmultiplethreads; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; + +/** + * This folder has two classes which is a good illustration to show the power of multithreading: + * it dramatically improves throughput and speeds up workload! + */ +public class MultiThreadedApp { + private static final int THREAD_POOL_SIZE = 5; + private static final int TOTAL_TASKS = 10; + private static final int MILLISECONDS_TO_FINISH_A_TASK = 1000; + + public static void main(String[] args) throws ExecutionException, InterruptedException { + + long start = System.currentTimeMillis(); + ExecutorService executorService = Executors.newFixedThreadPool(THREAD_POOL_SIZE); + List futures = new ArrayList<>(); + for (int i = 0; i < TOTAL_TASKS; i++) { + Runnable worker = new Worker("Worker" + i); + Future future = executorService.submit(worker); + futures.add(future); + } + executorService.shutdown(); + while (!executorService.isTerminated()) { + } + long end = System.currentTimeMillis(); + System.out.println("Multi-threaded app finished, it took " + (end - start) / 1000 + + " seconds for a thread pool of size " + THREAD_POOL_SIZE + " to finish " + + TOTAL_TASKS + " tasks, with each task takes " + MILLISECONDS_TO_FINISH_A_TASK / 1000 + " seconds."); + executorService.shutdown(); + } + + static class Worker implements Runnable { + private String workerName; + + public Worker(String workerName) { + this.workerName = workerName; + } + + @Override + public void run() { + System.out.println(Thread.currentThread().getName() + " starting worker: " + workerName); + doWork(); + System.out.println(Thread.currentThread().getName() + " ended for worker: " + workerName); + } + + private void doWork() { + try { + Thread.sleep(MILLISECONDS_TO_FINISH_A_TASK); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + } + +} diff --git a/src/main/java/multithread/singlevsmultiplethreads/SingleThreadedApp.java b/src/main/java/multithread/singlevsmultiplethreads/SingleThreadedApp.java new file mode 100644 index 0000000..189f575 --- /dev/null +++ b/src/main/java/multithread/singlevsmultiplethreads/SingleThreadedApp.java @@ -0,0 +1,31 @@ +package multithread.singlevsmultiplethreads; + +public class SingleThreadedApp { + + private static final int TOTAL_TASKS = 10; + private static final int MILLISECONDS_TO_FINISH_A_TASK = 1000; + + public static void main(String[] args) throws InterruptedException { + long start = System.currentTimeMillis(); + work(TOTAL_TASKS); + long end = System.currentTimeMillis(); + System.out.println("Single-threaded app took " + (end - start) / 1000 + + " seconds to finish a total of " + TOTAL_TASKS + + " tasks, with each task takes " + MILLISECONDS_TO_FINISH_A_TASK / 1000 + " seconds."); + } + + private static void work(int n) { + for (int i = 0; i < n; i++) { + doWork(i); + } + } + + private static void doWork(int workNumber) { + System.out.println("Task " + workNumber + " is being worked on."); + try { + Thread.sleep(MILLISECONDS_TO_FINISH_A_TASK); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } +} From 8658182c25260edd74752dfd2efa621f79c96a83 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Sun, 20 Aug 2023 18:10:47 -0700 Subject: [PATCH 086/132] a simple demo for CompletableFuture class --- .../CompletableFutureDemo.java | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 src/main/java/multithread/completablefutureexamples/CompletableFutureDemo.java diff --git a/src/main/java/multithread/completablefutureexamples/CompletableFutureDemo.java b/src/main/java/multithread/completablefutureexamples/CompletableFutureDemo.java new file mode 100644 index 0000000..f5b05af --- /dev/null +++ b/src/main/java/multithread/completablefutureexamples/CompletableFutureDemo.java @@ -0,0 +1,61 @@ +package multithread.completablefutureexamples; + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; + +import static org.junit.Assert.assertEquals; + +public class CompletableFutureDemo { + private static final int MILLISECONDS_TO_FINISH_A_TASK = 1000; + + + public static void main(String... args) throws Exception { + System.out.println("Program started."); + runApp(); + System.out.println("Program ended."); + } + + private static void runApp() throws InterruptedException, ExecutionException { + Future completableFuture = calculateAsync(); + String result = completableFuture.get(); + assertEquals("Hello", result); + } + + private static Future calculateAsync() { + CompletableFuture completableFuture = new CompletableFuture<>(); + + Executors.newCachedThreadPool().submit(() -> { + Thread.sleep(1000); + System.out.println("Doing some work in the thread now.."); + completableFuture.complete("Hello"); + return null; + }); + + return completableFuture; + } + + static class Worker implements Runnable { + private String workerName; + + public Worker(String workerName) { + this.workerName = workerName; + } + + @Override + public void run() { + System.out.println(Thread.currentThread().getName() + " starting worker: " + workerName); + doWork(); + System.out.println(Thread.currentThread().getName() + " ended for worker: " + workerName); + } + + private void doWork() { + try { + Thread.sleep(MILLISECONDS_TO_FINISH_A_TASK); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + } +} From 3e3882a948337b218ef381b63211615e2e4faa19 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Sun, 20 Aug 2023 18:18:18 -0700 Subject: [PATCH 087/132] another simple demo for CompletableFuture class --- .../CompletableFutureDemo2.java | 71 +++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 src/main/java/multithread/completablefutureexamples/CompletableFutureDemo2.java diff --git a/src/main/java/multithread/completablefutureexamples/CompletableFutureDemo2.java b/src/main/java/multithread/completablefutureexamples/CompletableFutureDemo2.java new file mode 100644 index 0000000..7acd9e3 --- /dev/null +++ b/src/main/java/multithread/completablefutureexamples/CompletableFutureDemo2.java @@ -0,0 +1,71 @@ +package multithread.completablefutureexamples; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; + +import static multithread.completablefutureexamples.CompletableFutureDemo2.WorkerPool.TIME_FOR_A_COMPUTATION_JOB_IN_MS; + +public class CompletableFutureDemo2 { + + private static final int POOL_SIZE = 10; + private static final int NUMBER_OF_COMPUTATION_JOBS = 20; + + public static void main(String... args) throws ExecutionException, InterruptedException { + System.out.println("Program started."); + long start = System.currentTimeMillis(); + WorkerPool workerPool = new WorkerPool(POOL_SIZE); + int finalResult = 0; + List> futureList = new ArrayList<>(); + for (int i = 1; i <= NUMBER_OF_COMPUTATION_JOBS; i++) { + Future completableFuture = workerPool.executeAsync(i); + futureList.add(completableFuture); + } + for (Future future : futureList) { + String result = future.get(); + finalResult += Integer.parseInt(result); + } + long end = System.currentTimeMillis(); + System.out.println("It took " + (end - start) / 1000 + + " seconds to complete computation, final result: " + finalResult + + ", a total of " + NUMBER_OF_COMPUTATION_JOBS + " computation jobs " + + "have been completed, total pool worker size is: " + POOL_SIZE + + ", and each job took " + TIME_FOR_A_COMPUTATION_JOB_IN_MS / 1000 + " second(s)." + ); + System.out.println("Program ended."); + } + + static class WorkerPool { + static final long TIME_FOR_A_COMPUTATION_JOB_IN_MS = 1000l; + int poolSize; + ExecutorService executorService; + + public WorkerPool(int poolSize) { + this.poolSize = poolSize; + this.executorService = Executors.newFixedThreadPool(poolSize); + } + + public Future executeAsync(int input) { + final CompletableFuture completableFuture = new CompletableFuture<>(); + this.executorService.submit(() -> doWork(completableFuture, input)); + return completableFuture; + } + + private void doWork(CompletableFuture completableFuture, int input) { + int result = 0; + try { + System.out.println(Thread.currentThread().getName() + " is doing some real work now that'll take 1 second to complete."); + Thread.sleep(TIME_FOR_A_COMPUTATION_JOB_IN_MS); + result += input * 2; + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + completableFuture.complete("" + result); + } + } + +} From d4ab0c2e9e70eefdcb2afa7669c95fafa3c5dcb0 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Sun, 20 Aug 2023 20:58:26 -0700 Subject: [PATCH 088/132] Function interface examples --- .../FunctionalInterfacesDemo.java | 79 +++++++++++++++++-- 1 file changed, 73 insertions(+), 6 deletions(-) diff --git a/src/main/java/java8tutorials/functionalInterfaces/FunctionalInterfacesDemo.java b/src/main/java/java8tutorials/functionalInterfaces/FunctionalInterfacesDemo.java index 311083d..c335cc5 100644 --- a/src/main/java/java8tutorials/functionalInterfaces/FunctionalInterfacesDemo.java +++ b/src/main/java/java8tutorials/functionalInterfaces/FunctionalInterfacesDemo.java @@ -1,10 +1,10 @@ package java8tutorials.functionalInterfaces; -/** - * Created by stevesun on 4/16/17. - */ +import java.util.function.Function; + public class FunctionalInterfacesDemo { - /**How does lambda expressions fit into Javas type system? + /** + * How does lambda expressions fit into Javas type system? * Each lambda corresponds to a given type, specified by an interface. * A so called functional interface must contain exactly one abstract method declaration. * Each lambda expression of that type will be matched to this abstract method. @@ -13,9 +13,10 @@ public class FunctionalInterfacesDemo { * To ensure that your interface meet the requirements, * you should add the @FunctionalInterface annotation. * The compiler is aware of this annotation and throws a compiler error as soon as you try to add a second abstract method declaration to - * the interface.*/ + * the interface. + */ - public static void main(String ... args) { + public static void main(String... args) { Converter converter = (from -> Integer.valueOf(from)); Integer converted = converter.convert("123"); System.out.println(converted); @@ -25,6 +26,72 @@ public static void main(String ... args) { converter = Integer::valueOf; converted = converter.convert("321"); System.out.println(converted); + + runAnotherFunctionInterfaceExample(); + } + + private static void runAnotherFunctionInterfaceExample() { + /**Function interface has a few methods that are often used: + * apply() + * andThen() + * compose() + * identity() + * */ + Function addFunction = a -> a + 3; + System.out.println(addFunction.apply(1)); + + Function multipleFunction = (a) -> a * 3; + System.out.println(multipleFunction.apply(1)); + + //a.compose(b) means b will be executed first and then a will execute + Function compositeFunction = addFunction.compose(multipleFunction); + System.out.println(compositeFunction.apply(1)); + + //a.andThen(b) means a will be executed first, and then function b executes. + Function andThenFunction = addFunction.andThen(multipleFunction); + System.out.println(andThenFunction.apply(1)); + + //Function.identity() is a static method of Function interface that returns a Function that always returns its input argument. i.e. f(x) = x + understandFunctionIdentity(); + } + + private static void understandFunctionIdentity() { + // Using String as Input for Function.identity() + Function stringFunction = Function.identity(); + System.out.println(stringFunction.apply("Alive is Awesome")); + + // Using Integer as input for Function.identity() + Function integerFunctionUsingFunctionIdentity = Function.identity(); + System.out.println(integerFunctionUsingFunctionIdentity.apply(8)); + + // Using lambda expression and String as input + Function stringFunctionUsingLambda = t -> t; + System.out.println(stringFunctionUsingLambda.apply("Be in present")); + + // Using lambda expression and Integer as input + Function integerFunctionUsingLambda = t -> t; + System.out.println(integerFunctionUsingLambda.apply(4)); + + Function func1 = Function.identity(); + Function func2 = Function.identity(); + Function func3 = Function.identity(); + + Function intFunc1 = t -> t; + Function intFunc2 = t -> t; + Function intFunc3 = t -> t; + + System.out.println(func1); + System.out.println(func2); + System.out.println(func3); + + System.out.println(intFunc1); + System.out.println(intFunc2); + System.out.println(intFunc3); + /** + * From the above output, we can conclude that Function.identity() + * method will always return the same instance + * whereas each occurrence of (t -> t) or identifier -> identifier + * will not only create its own instance but even have a distinct implementation class.*/ } } From 114583695318a9fbb41ce71f223e484d21448888 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Sun, 20 Aug 2023 20:59:54 -0700 Subject: [PATCH 089/132] update comment --- .../functionalInterfaces/FunctionalInterfacesDemo.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/java8tutorials/functionalInterfaces/FunctionalInterfacesDemo.java b/src/main/java/java8tutorials/functionalInterfaces/FunctionalInterfacesDemo.java index c335cc5..b0b24ba 100644 --- a/src/main/java/java8tutorials/functionalInterfaces/FunctionalInterfacesDemo.java +++ b/src/main/java/java8tutorials/functionalInterfaces/FunctionalInterfacesDemo.java @@ -6,7 +6,7 @@ public class FunctionalInterfacesDemo { /** * How does lambda expressions fit into Javas type system? * Each lambda corresponds to a given type, specified by an interface. - * A so called functional interface must contain exactly one abstract method declaration. + * A so-called functional interface must contain exactly one abstract method declaration. * Each lambda expression of that type will be matched to this abstract method. * Since default methods are not abstract you're free to add default methods to your functional interface. * We can use arbitrary interfaces as lambda expressions as long as the interface only contains one abstract method. From a768af27830ef78a9507424bba9818753cd6d1c1 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Sun, 20 Aug 2023 21:37:35 -0700 Subject: [PATCH 090/132] add Function demo examples --- .../functionalInterfaces/FunctionDemo.java | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 src/main/java/java8tutorials/functionalInterfaces/FunctionDemo.java diff --git a/src/main/java/java8tutorials/functionalInterfaces/FunctionDemo.java b/src/main/java/java8tutorials/functionalInterfaces/FunctionDemo.java new file mode 100644 index 0000000..0c13945 --- /dev/null +++ b/src/main/java/java8tutorials/functionalInterfaces/FunctionDemo.java @@ -0,0 +1,61 @@ +package java8tutorials.functionalInterfaces; + +import java.util.concurrent.ExecutionException; +import java.util.function.Function; + +public class FunctionDemo { + + public static void main(String... args) throws ExecutionException, InterruptedException { + System.out.println("Program started."); + FunctionDemo main = new FunctionDemo(); + String originalInput = "originalInput"; + String result = main.doWorkInMultipleStepsInSequence(originalInput); + System.out.println("Program ended, result: " + result); + } + + String doWorkInMultipleStepsInSequence(String messageOne) throws InterruptedException { + return doWorkStepTwoAsync(messageOne, doWorkStepTwoFunction); + } + + String doWorkStepTwoAsync(String message, Function doWorkStepTwoFunction) throws InterruptedException { + Thread.sleep(1000); + StringBuilder sb = new StringBuilder(message); + System.out.println("Spent 1 second doing work in Step Two Async function."); + sb.append(",aboutToCallDoWorkStepTwoFunction"); + String intermediateResult = doWorkStepTwoFunction.apply(sb.toString()); + return doWorkStepThreeAsync(intermediateResult, doWorkStepThreeFunction); + } + + String doWorkStepThreeAsync(String message, Function doWorkStepThreeFunction) throws InterruptedException { + Thread.sleep(1000); + StringBuilder sb = new StringBuilder(message); + System.out.println("Spent 1 second doing work in Step Three Async function."); + sb.append(",aboutToCallDoWorkStepThreeFunction"); + return doWorkStepThreeFunction.apply(sb.toString()); + } + + Function doWorkStepTwoFunction = s -> { + StringBuilder sb = new StringBuilder(s); + try { + Thread.sleep(1000); + System.out.println("Spent 1 second doing work in Step Two."); + sb.append(",stepTwoDone"); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + return sb.toString(); + }; + + Function doWorkStepThreeFunction = s -> { + StringBuilder sb = new StringBuilder(s); + try { + Thread.sleep(1000); + System.out.println("Spent 1 second doing work in Step Three."); + sb.append(",stepThreeDone"); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + return sb.toString(); + }; + +} From 3461c73ae962fb791535eef0fc05e213a3d0a00f Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Fri, 25 Aug 2023 07:22:20 -0700 Subject: [PATCH 091/132] print out start and end times --- .../completablefutureexamples/CompletableFutureDemo2.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/multithread/completablefutureexamples/CompletableFutureDemo2.java b/src/main/java/multithread/completablefutureexamples/CompletableFutureDemo2.java index 7acd9e3..0efe944 100644 --- a/src/main/java/multithread/completablefutureexamples/CompletableFutureDemo2.java +++ b/src/main/java/multithread/completablefutureexamples/CompletableFutureDemo2.java @@ -30,6 +30,8 @@ public static void main(String... args) throws ExecutionException, InterruptedEx finalResult += Integer.parseInt(result); } long end = System.currentTimeMillis(); + System.out.println("end: " + end); + System.out.println("start: " + start); System.out.println("It took " + (end - start) / 1000 + " seconds to complete computation, final result: " + finalResult + ", a total of " + NUMBER_OF_COMPUTATION_JOBS + " computation jobs " From 5f01f66864d87fe7ca22790401ce0427583e5d1a Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Sun, 27 Aug 2023 16:02:58 -0700 Subject: [PATCH 092/132] update org.apache.maven.plugins to 16 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index fab1182..ac85fbd 100644 --- a/pom.xml +++ b/pom.xml @@ -8,8 +8,8 @@ org.apache.maven.plugins maven-compiler-plugin - 9 - 9 + 16 + 16 From e06b0a9bb86aa18a804c9cb905b26834267f6095 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Tue, 12 Sep 2023 09:06:41 -0700 Subject: [PATCH 093/132] rename profiler class --- src/main/java/profiler/{Main.java => SimpleProfiler.java} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename src/main/java/profiler/{Main.java => SimpleProfiler.java} (96%) diff --git a/src/main/java/profiler/Main.java b/src/main/java/profiler/SimpleProfiler.java similarity index 96% rename from src/main/java/profiler/Main.java rename to src/main/java/profiler/SimpleProfiler.java index 3884b74..f165b6a 100644 --- a/src/main/java/profiler/Main.java +++ b/src/main/java/profiler/SimpleProfiler.java @@ -1,6 +1,6 @@ package profiler; -public class Main { +public class SimpleProfiler { /** * From this post: https://stackoverflow.com/a/9415368/4117496 * To run this: go to terminal and use this command: From 0f6eb54b12c6a9b8ea5f643ba3c7f17e64e5dbdd Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Tue, 12 Sep 2023 09:12:46 -0700 Subject: [PATCH 094/132] add Intellij profiler example --- src/main/java/profiler/IntellijProfiler.java | 49 ++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 src/main/java/profiler/IntellijProfiler.java diff --git a/src/main/java/profiler/IntellijProfiler.java b/src/main/java/profiler/IntellijProfiler.java new file mode 100644 index 0000000..4e2f1b6 --- /dev/null +++ b/src/main/java/profiler/IntellijProfiler.java @@ -0,0 +1,49 @@ +package profiler; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayDeque; +import java.util.Arrays; +import java.util.Deque; +import java.util.concurrent.TimeUnit; + +public class IntellijProfiler { + /**Source: https://github.com/flounder4130/profiler-example/tree/master*/ + public static int update(Deque events, long nanos, long interval) { + events.add(nanos); + events.removeIf(aTime -> aTime < nanos - interval); + /* + //noinspection ConstantConditions + while (events.peekFirst() < nanos - interval) { + events.removeFirst(); + } + */ + return events.size(); + } + + public static void main(String[] args) throws IOException { + long start = System.nanoTime(); + int total = 100_000; + long interval = TimeUnit.MILLISECONDS.toNanos(100); + int[] count = new int[total]; + + Deque collection = new ArrayDeque<>(); + for (int counter = 0; counter < count.length; counter++) { + count[counter] = update(collection, System.nanoTime(), interval); + Path p = Paths.get("./a/b"); + Files.createDirectories(p); + /* + if (!Files.exists(p)) { + Files.createDirectories(p); + } + */ + } + long spent = System.nanoTime() - start; + + //noinspection OptionalGetWithoutIsPresent + System.out.println("Average count: " + (int) (Arrays.stream(count).average().getAsDouble()) + " op"); + System.out.println("Spent time: " + TimeUnit.NANOSECONDS.toMillis(spent) + " ms"); + } +} From 6961dabaf97f1fd36f4080e4161b588bb3dfca22 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Tue, 12 Sep 2023 15:18:11 -0700 Subject: [PATCH 095/132] rename profile class --- .../{IntellijProfiler.java => IntellijProfilerExample.java} | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) rename src/main/java/profiler/{IntellijProfiler.java => IntellijProfilerExample.java} (92%) diff --git a/src/main/java/profiler/IntellijProfiler.java b/src/main/java/profiler/IntellijProfilerExample.java similarity index 92% rename from src/main/java/profiler/IntellijProfiler.java rename to src/main/java/profiler/IntellijProfilerExample.java index 4e2f1b6..1077a30 100644 --- a/src/main/java/profiler/IntellijProfiler.java +++ b/src/main/java/profiler/IntellijProfilerExample.java @@ -9,7 +9,7 @@ import java.util.Deque; import java.util.concurrent.TimeUnit; -public class IntellijProfiler { +public class IntellijProfilerExample { /**Source: https://github.com/flounder4130/profiler-example/tree/master*/ public static int update(Deque events, long nanos, long interval) { events.add(nanos); @@ -24,6 +24,7 @@ public static int update(Deque events, long nanos, long interval) { } public static void main(String[] args) throws IOException { + System.out.println("Program started."); long start = System.nanoTime(); int total = 100_000; long interval = TimeUnit.MILLISECONDS.toNanos(100); @@ -45,5 +46,6 @@ public static void main(String[] args) throws IOException { //noinspection OptionalGetWithoutIsPresent System.out.println("Average count: " + (int) (Arrays.stream(count).average().getAsDouble()) + " op"); System.out.println("Spent time: " + TimeUnit.NANOSECONDS.toMillis(spent) + " ms"); + System.out.println("\nProgram finished."); } } From 4c45fad3b3299a108c80f7b35961865797cbb24c Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Sun, 15 Oct 2023 08:36:09 -0700 Subject: [PATCH 096/132] [WIP] add a simple and incomplete volatile example --- src/main/java/java_volatile/TaskRunner.java | 26 +++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 src/main/java/java_volatile/TaskRunner.java diff --git a/src/main/java/java_volatile/TaskRunner.java b/src/main/java/java_volatile/TaskRunner.java new file mode 100644 index 0000000..086614a --- /dev/null +++ b/src/main/java/java_volatile/TaskRunner.java @@ -0,0 +1,26 @@ +package java_volatile; + +public class TaskRunner { + private static int number; + private static boolean ready; + + private static class Reader extends Thread { + @Override + public void run() { + System.out.println("ready is: " + ready); + while (!ready) { + System.out.println("It's yielding now.."); + Thread.yield(); + } + System.out.println("number is: " + number); + } + } + + public static void main(String[] args) { + System.out.println("Program started."); + new Reader().start(); + number = 42; + ready = true; + System.out.println("Program finished."); + } +} From 8bcf0e84da5b84b0c66a763ead149d95d2f60b92 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Mon, 16 Oct 2023 17:01:12 -0700 Subject: [PATCH 097/132] add comment for TaskRunner --- src/main/java/java_volatile/TaskRunner.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/java_volatile/TaskRunner.java b/src/main/java/java_volatile/TaskRunner.java index 086614a..272ce6a 100644 --- a/src/main/java/java_volatile/TaskRunner.java +++ b/src/main/java/java_volatile/TaskRunner.java @@ -1,6 +1,9 @@ package java_volatile; public class TaskRunner { + /** + * This is following the examples from https://www.baeldung.com/java-volatile + */ private static int number; private static boolean ready; From 4867daee354af6079a9fa9e55274bf3458fc7776 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Fri, 17 Nov 2023 21:15:00 -0800 Subject: [PATCH 098/132] add code to get uploadPartUrl --- .../java/b2SdkExamples/B2SdkExamples.java | 43 ++++++++++++++++--- 1 file changed, 38 insertions(+), 5 deletions(-) diff --git a/src/main/java/b2SdkExamples/B2SdkExamples.java b/src/main/java/b2SdkExamples/B2SdkExamples.java index b2c69a7..8155436 100644 --- a/src/main/java/b2SdkExamples/B2SdkExamples.java +++ b/src/main/java/b2SdkExamples/B2SdkExamples.java @@ -2,34 +2,67 @@ import com.backblaze.b2.client.B2StorageClient; import com.backblaze.b2.client.B2StorageClientFactory; +import com.backblaze.b2.client.contentSources.B2ByteArrayContentSource; +import com.backblaze.b2.client.contentSources.B2ContentTypes; import com.backblaze.b2.client.exceptions.B2Exception; -import com.backblaze.b2.client.structures.B2Bucket; -import com.backblaze.b2.client.structures.B2ListBucketsResponse; +import com.backblaze.b2.client.structures.*; import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; public class B2SdkExamples { private static final String APPLICATION_KEY_ID = "xxx"; private static final String APPLICATION_KEY = "yyy"; + + private static final String USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36"; + private static final int minimumPartSize = 5000000; + private static final byte[] large_file_in_bytes = new byte[minimumPartSize + 1]; + public static void main(String... args) throws B2Exception { System.out.println("Hello world from B2SdkExamples.."); // B2StorageClient client = B2StorageClientFactory.createDefaultFactory().create(USER_AGENT); //set up B2 CLI //and then use b2 get-account-info to get applicationKeyId and applicationKey to fill in here and run B2ListBucketsResponse b2ListBucketsResponse; - try (B2StorageClient b2StorageClient = B2StorageClientFactory.createDefaultFactory().create(APPLICATION_KEY_ID, APPLICATION_KEY, USER_AGENT)) { - b2ListBucketsResponse = b2StorageClient.listBuckets(); + try (B2StorageClient b2Client = B2StorageClientFactory.createDefaultFactory().create(APPLICATION_KEY_ID, APPLICATION_KEY, USER_AGENT)) { + b2ListBucketsResponse = b2Client.listBuckets(); List buckets = b2ListBucketsResponse.getBuckets(); System.out.println("buckets.size() is: " + buckets.size()); + B2Bucket bucketOne = null; for (B2Bucket b2Bucket : buckets) { System.out.println("this bucket info is: " + b2Bucket.getBucketInfo()); System.out.println("this bucket getBucketName is: " + b2Bucket.getBucketName()); + bucketOne = b2Bucket; + break; } - String b2AccountId = b2StorageClient.getAccountId(); + String b2AccountId = b2Client.getAccountId(); System.out.println("b2AccountId is: " + b2AccountId); + + B2FileVersion largeFile = b2Client.startLargeFile( + B2StartLargeFileRequest + .builder(bucketOne.getBucketId(), "this_is_a_large_test_file_jsun", "text/plain") + .build() + ); + B2UploadPartUrlResponse uploadPartUrl = b2Client.getUploadPartUrl(B2GetUploadPartUrlRequest.builder(largeFile.getFileId()).build()); + System.out.println("uploadPartUrl.getFileId() is: " + uploadPartUrl.getFileId()); + System.out.println("uploadPartUrl.getUploadUrl() is: " + uploadPartUrl.getUploadUrl()); +// example output: +// uploadPartUrl.getFileId() is: 4_zc0c2ee6e6dccd2d788960d17_f231f3059ce9d1672_d20231118_m042524_c004_v0402007_t0004_u01700281524855 +// uploadPartUrl.getUploadUrl() is: https://pod-040-2007-12.backblaze.com/b2api/v2/b2_upload_part/4_zc0c2ee6e6dccd2d788960d17_f231f3059ce9d1672_d20231118_m042524_c004_v0402007_t0004_u01700281524855/0014 + + final B2UploadFileRequest request = B2UploadFileRequest.builder( + bucketOne.getBucketId(), + "largeFile", + B2ContentTypes.TEXT_PLAIN, + B2ByteArrayContentSource.build(large_file_in_bytes) + ).build(); + ExecutorService executor = Executors.newScheduledThreadPool(15); + B2FileVersion uploaded = b2Client.uploadLargeFile(request, executor); + System.out.println("uploaded.getLargeFileSha1OrNull(): " + uploaded.getLargeFileSha1OrNull()); } System.out.println("Finished running in main method."); } From 571f0cfba00f9cf2efe0a0c34cfeba3f0522c869 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Fri, 17 Nov 2023 21:17:31 -0800 Subject: [PATCH 099/132] add TODO comments --- src/main/java/b2SdkExamples/B2SdkExamples.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/b2SdkExamples/B2SdkExamples.java b/src/main/java/b2SdkExamples/B2SdkExamples.java index 8155436..0c3166d 100644 --- a/src/main/java/b2SdkExamples/B2SdkExamples.java +++ b/src/main/java/b2SdkExamples/B2SdkExamples.java @@ -16,10 +16,10 @@ public class B2SdkExamples { private static final String APPLICATION_KEY = "yyy"; - private static final String USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36"; private static final int minimumPartSize = 5000000; +// TODO: read in a big file or generate a random file to fill into below byte array private static final byte[] large_file_in_bytes = new byte[minimumPartSize + 1]; public static void main(String... args) throws B2Exception { @@ -54,6 +54,7 @@ public static void main(String... args) throws B2Exception { // uploadPartUrl.getFileId() is: 4_zc0c2ee6e6dccd2d788960d17_f231f3059ce9d1672_d20231118_m042524_c004_v0402007_t0004_u01700281524855 // uploadPartUrl.getUploadUrl() is: https://pod-040-2007-12.backblaze.com/b2api/v2/b2_upload_part/4_zc0c2ee6e6dccd2d788960d17_f231f3059ce9d1672_d20231118_m042524_c004_v0402007_t0004_u01700281524855/0014 +// TODO: figure out how to make below API call work elegantly final B2UploadFileRequest request = B2UploadFileRequest.builder( bucketOne.getBucketId(), "largeFile", From c664f91c85c130d89e9d8dcab635e7e0c167cb57 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Tue, 23 Jan 2024 11:24:57 -0800 Subject: [PATCH 100/132] add a simple program under java_playground --- src/main/java/java_playground/MainApp.java | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 src/main/java/java_playground/MainApp.java diff --git a/src/main/java/java_playground/MainApp.java b/src/main/java/java_playground/MainApp.java new file mode 100644 index 0000000..0bc44e6 --- /dev/null +++ b/src/main/java/java_playground/MainApp.java @@ -0,0 +1,8 @@ +package java_playground; + +public class MainApp { + public static void main(String... args) { + System.out.println("Hello world."); + System.out.println("Program finished."); + } +} From 126bee220daea87e5b06ddd39d9aa0ee6048efe1 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Fri, 26 Jan 2024 16:06:16 -0800 Subject: [PATCH 101/132] add a simple Java File IO example --- .../java/IO_example/JavaFileIOExample.java | 29 +++++++++++++++++++ src/test/resources/sample_input.txt | 1 + 2 files changed, 30 insertions(+) create mode 100644 src/main/java/IO_example/JavaFileIOExample.java create mode 100644 src/test/resources/sample_input.txt diff --git a/src/main/java/IO_example/JavaFileIOExample.java b/src/main/java/IO_example/JavaFileIOExample.java new file mode 100644 index 0000000..29cfd75 --- /dev/null +++ b/src/main/java/IO_example/JavaFileIOExample.java @@ -0,0 +1,29 @@ +package IO_example; + +import java.io.File; +import java.io.IOException; +import java.util.Scanner; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class JavaFileIOExample { + + public static void main(String... args) throws IOException { + System.out.println("Program started."); + readFileOnDisk(); + System.out.println("Program finished."); + } + + private static void readFileOnDisk() throws IOException { + String file = "src/test/resources/sample_input.txt"; + Scanner scanner = new Scanner(new File(file)); + scanner.useDelimiter(" "); + + assertTrue(scanner.hasNext()); + while (scanner.hasNext()) { + System.out.println(scanner.next()); + } + + scanner.close(); + } +} diff --git a/src/test/resources/sample_input.txt b/src/test/resources/sample_input.txt new file mode 100644 index 0000000..10a9d37 --- /dev/null +++ b/src/test/resources/sample_input.txt @@ -0,0 +1 @@ +cool test it is \ No newline at end of file From 9831290d31cc61445722d4c192262b825b92173c Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Mon, 29 Jan 2024 18:22:10 -0800 Subject: [PATCH 102/132] add a method to read in csv file and count --- .../java/IO_example/JavaFileIOExample.java | 21 +++++++++++++++++++ src/test/resources/city_names.csv | 1 + 2 files changed, 22 insertions(+) create mode 100644 src/test/resources/city_names.csv diff --git a/src/main/java/IO_example/JavaFileIOExample.java b/src/main/java/IO_example/JavaFileIOExample.java index 29cfd75..e967514 100644 --- a/src/main/java/IO_example/JavaFileIOExample.java +++ b/src/main/java/IO_example/JavaFileIOExample.java @@ -2,6 +2,8 @@ import java.io.File; import java.io.IOException; +import java.util.HashMap; +import java.util.Map; import java.util.Scanner; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -11,6 +13,7 @@ public class JavaFileIOExample { public static void main(String... args) throws IOException { System.out.println("Program started."); readFileOnDisk(); + findUniqueCityNames(); System.out.println("Program finished."); } @@ -26,4 +29,22 @@ private static void readFileOnDisk() throws IOException { scanner.close(); } + + private static void findUniqueCityNames() throws IOException { + String file = "src/test/resources/city_names.csv"; + Scanner scanner = new Scanner(new File(file)); + scanner.useDelimiter(","); + Map map = new HashMap<>(); + while (scanner.hasNext()) { + String city = scanner.next(); + map.put(city, map.getOrDefault(city, 0) + 1); + } + scanner.close(); + System.out.println("Unique city names are: "); + for (String city : map.keySet()) { + if (map.get(city) == 1) { + System.out.println(city); + } + } + } } diff --git a/src/test/resources/city_names.csv b/src/test/resources/city_names.csv new file mode 100644 index 0000000..2ee71fd --- /dev/null +++ b/src/test/resources/city_names.csv @@ -0,0 +1 @@ +NYC,NYC,NYC,Cedar Park,NYC,NYC,NYC,NYC,San Jose,San Jose,San Jose,San Jose,McKinney,San Jose,SF,LA,LA,LA,LA,LA,San Diego,San Diego,San Diego,Seattle,Portland,Portland,Portland,Boston,D.C,D.C,D.C,Miami,Dallas,Cedar Park,McKinney,Melissa,Sacramento,Sacramento \ No newline at end of file From b8a0c679f5894d30e91e11178cb26d2e8c5c4e9f Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Sat, 3 Feb 2024 11:03:24 -0800 Subject: [PATCH 103/132] add Java8 stream example --- .../lamdaExpressions/LamdaDemo.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/main/java/java8tutorials/lamdaExpressions/LamdaDemo.java b/src/main/java/java8tutorials/lamdaExpressions/LamdaDemo.java index e4c54c5..88b2e31 100644 --- a/src/main/java/java8tutorials/lamdaExpressions/LamdaDemo.java +++ b/src/main/java/java8tutorials/lamdaExpressions/LamdaDemo.java @@ -1,9 +1,12 @@ package java8tutorials.lamdaExpressions; +import lombok.Getter; + import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.List; +import java.util.stream.Collectors; /** * Created by stevesun on 4/16/17. @@ -68,16 +71,30 @@ public static void sortInJava8_use_lamda_expressions_shorter_even() { print(names, "After sorting: "); } + public static void sortInJava8_use_lamda_expressions_and_stream() { + List names = Arrays.asList(new Person("Sophie", 27), new Person("Ada", 1), + new Person("Steve", 28), new Person("Eason", 26), new Person("Jenny", 31)); + + System.out.println("In sortInJava8_use_lamda_expressions_using_stream method."); + print(names, "Prior to sort: "); + + List sorted = names.stream().sorted(Comparator.comparing(Person::getAge)).collect(Collectors.toList()); + + print(sorted, "After sorting: "); + } + public static void main(String...args) { sortInPreJava8(); sortInJava8_use_lamda_expressions(); sortInJava8_use_lamda_expressions_shorter(); sortInJava8_use_lamda_expressions_shorter_even(); + sortInJava8_use_lamda_expressions_and_stream(); } } class Person { String name; + @Getter int age; public Person (String name, int age) { this.name = name; From 65d57ae2d293407dfa29b2dbef49babb7211db98 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Sat, 3 Feb 2024 11:23:49 -0800 Subject: [PATCH 104/132] update comments --- .../completablefutureexamples/CompletableFutureDemo.java | 6 +++++- .../completablefutureexamples/CompletableFutureDemo2.java | 5 +++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/main/java/multithread/completablefutureexamples/CompletableFutureDemo.java b/src/main/java/multithread/completablefutureexamples/CompletableFutureDemo.java index f5b05af..e1a49a5 100644 --- a/src/main/java/multithread/completablefutureexamples/CompletableFutureDemo.java +++ b/src/main/java/multithread/completablefutureexamples/CompletableFutureDemo.java @@ -19,7 +19,10 @@ public static void main(String... args) throws Exception { private static void runApp() throws InterruptedException, ExecutionException { Future completableFuture = calculateAsync(); + System.out.println("got completableFuture: " + completableFuture); + System.out.println("got completableFuture.isDone(): " + completableFuture.isDone()); String result = completableFuture.get(); + System.out.println("got completableFuture.isDone(): " + completableFuture.isDone()); assertEquals("Hello", result); } @@ -27,8 +30,9 @@ private static Future calculateAsync() { CompletableFuture completableFuture = new CompletableFuture<>(); Executors.newCachedThreadPool().submit(() -> { - Thread.sleep(1000); System.out.println("Doing some work in the thread now.."); + Thread.sleep(1000); + System.out.println("Almost done working in the thread now.."); completableFuture.complete("Hello"); return null; }); diff --git a/src/main/java/multithread/completablefutureexamples/CompletableFutureDemo2.java b/src/main/java/multithread/completablefutureexamples/CompletableFutureDemo2.java index 0efe944..88135b0 100644 --- a/src/main/java/multithread/completablefutureexamples/CompletableFutureDemo2.java +++ b/src/main/java/multithread/completablefutureexamples/CompletableFutureDemo2.java @@ -23,6 +23,7 @@ public static void main(String... args) throws ExecutionException, InterruptedEx List> futureList = new ArrayList<>(); for (int i = 1; i <= NUMBER_OF_COMPUTATION_JOBS; i++) { Future completableFuture = workerPool.executeAsync(i); + System.out.println("i = " + i + " and completableFuture.isDone() is: " + completableFuture.isDone()); futureList.add(completableFuture); } for (Future future : futureList) { @@ -30,8 +31,8 @@ public static void main(String... args) throws ExecutionException, InterruptedEx finalResult += Integer.parseInt(result); } long end = System.currentTimeMillis(); - System.out.println("end: " + end); - System.out.println("start: " + start); + System.out.println("end time in millis: " + end); + System.out.println("start time in millis: " + start); System.out.println("It took " + (end - start) / 1000 + " seconds to complete computation, final result: " + finalResult + ", a total of " + NUMBER_OF_COMPUTATION_JOBS + " computation jobs " From 4d9dbe7a99cde9a040cc1428a4602652e6502351 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Sat, 3 Feb 2024 11:58:38 -0800 Subject: [PATCH 105/132] add CompletionService demo --- .../multithread/CompletionServiceDemo.java | 87 +++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 src/main/java/multithread/CompletionServiceDemo.java diff --git a/src/main/java/multithread/CompletionServiceDemo.java b/src/main/java/multithread/CompletionServiceDemo.java new file mode 100644 index 0000000..58cca21 --- /dev/null +++ b/src/main/java/multithread/CompletionServiceDemo.java @@ -0,0 +1,87 @@ +package multithread; + +import java.util.concurrent.*; + +public class CompletionServiceDemo { + /** + * credit: https://stackoverflow.com/a/5580058/4117496 + */ + class CalcResult { + long result; + + CalcResult(long l) { + result = l; + } + } + + class CallableTask implements Callable { + String taskName; + long input1; + int input2; + + CallableTask(String name, long v1, int v2) { + taskName = name; + input1 = v1; + input2 = v2; + } + + public CalcResult call() { + System.out.println("Task " + taskName + " started -----"); + for (int i = 0; i < input2; i++) { + try { + Thread.sleep(200); + } catch (InterruptedException e) { + System.out.println("Task " + taskName + " interrupted !! "); + e.printStackTrace(); + } + input1 += i; + } + System.out.println("Task " + taskName + " completed."); + return new CalcResult(input1); + } + + } + + public void test() { + ExecutorService executorService = Executors.newFixedThreadPool(3); + CompletionService completionService = new ExecutorCompletionService<>(executorService); + + int submittedTasks = 5; + for (int i = 0; i < submittedTasks; i++) { + completionService.submit(new CallableTask( + String.valueOf(i), + (i * 10), + ((i * 10) + 10) + )); + System.out.println("Task " + i + " submitted"); + } + for (int tasksHandled = 0; tasksHandled < submittedTasks; tasksHandled++) { + try { + System.out.println("trying to take from Completion service"); + Future result = completionService.take(); + System.out.println("result for a task available in queue. Trying to get() now"); + // above call blocks till atleast one task is completed and results availble for it + // but we don't have to worry which one + + // process the result here by doing result.get() + CalcResult l = result.get(); + System.out.println("Task " + tasksHandled + " completed - results obtained : " + l.result); + + } catch (InterruptedException e) { + // Something went wrong with a task submitted + System.out.println("Error Interrupted exception"); + e.printStackTrace(); + } catch (ExecutionException e) { + // Something went wrong with the result + e.printStackTrace(); + System.out.println("Error get() threw exception"); + } + } + } + + public static void main(String... args) { + CompletionServiceDemo demo = new CompletionServiceDemo(); + demo.test(); + System.out.println("\n\nProgram finished.\n"); + } +} From 12cd5578b55cf1f2a9c17ce032a7686e1209d571 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Sun, 4 Feb 2024 11:06:16 -0800 Subject: [PATCH 106/132] add equality examples --- .../java/string/UnderstandStringInJava.java | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 src/main/java/string/UnderstandStringInJava.java diff --git a/src/main/java/string/UnderstandStringInJava.java b/src/main/java/string/UnderstandStringInJava.java new file mode 100644 index 0000000..f431629 --- /dev/null +++ b/src/main/java/string/UnderstandStringInJava.java @@ -0,0 +1,29 @@ +package string; + +public class UnderstandStringInJava { + public static void main(String... args) { + UnderstandStringInJava understandStringInJava = new UnderstandStringInJava(); + understandStringInJava.checkStringEquality(); + System.out.println("Program finished."); + } + + public void checkStringEquality() { + String a = "abc"; + String b = "abc"; + + /** + * One can use == operators for reference comparison (address comparison) and the .equals() method for content comparison. + * Both s1 and s2 refer to different objects. + * When one uses == operator for the s1 and s2 comparison then the result is false as both have different addresses in memory. + * Using equals, the result is true because it’s only comparing the values given in s1 and s2.*/ + System.out.println(a == b); + System.out.println(a.equals(b)); + + String c = new String(new char[]{'a', 'b', 'c', 'd'}); + String d = new String(new char[]{'a', 'b', 'c', 'd'}); + System.out.println("c is: " + c); + System.out.println("d is: " + d); + System.out.println(c == d); + System.out.println(c.equals(d)); + } +} From 69675da2f0a3c13e561e5bacb98bd7329e35c1a0 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Sun, 4 Feb 2024 13:21:51 -0800 Subject: [PATCH 107/132] format MergeSort --- src/main/java/sorting/MergeSort.java | 126 +++++++++++++-------------- 1 file changed, 63 insertions(+), 63 deletions(-) diff --git a/src/main/java/sorting/MergeSort.java b/src/main/java/sorting/MergeSort.java index 18adafb..b39b5ad 100644 --- a/src/main/java/sorting/MergeSort.java +++ b/src/main/java/sorting/MergeSort.java @@ -1,69 +1,69 @@ package sorting; public class MergeSort { - public static void main(String...strings){ - int a[] = new int[] { 9, 3, 8, 6, 2, 1, 5, 4}; - int b[] = new int[a.length]; + public static void main(String... strings) { + int a[] = new int[]{9, 3, 8, 6, 2, 1, 5, 4}; + int b[] = new int[a.length]; - System.out.println("List before sorting\n"); - for (int i = 0; i < a.length; i++) System.out.print(a[i] + " "); - - MergeSort test = new MergeSort(); - test.sort(a, 0, a.length-1); - - System.out.println("\nList after sorting\n"); - for (int i = 0; i < a.length; i++) System.out.print(a[i] + " "); - } - - public void sort(int[] arr, int l, int r){ - if(l < r){ - int m = (l+r)/2; - sort(arr, l, m); - sort(arr, m+1, r); - merge(arr, l, m, r); - } - } + System.out.println("List before sorting\n"); + for (int i = 0; i < a.length; i++) System.out.print(a[i] + " "); - private void merge(int[] arr, int l, int m, int r) { - //find sizes of two subarrays that are to be merged - int size1 = m-l+1; - int size2 = r-m; - - //copy the two subarrays into two temp arrays - int[] tempL = new int[size1]; - int[] tempR = new int[size2]; - for(int i = 0; i < size1; i++){ - tempL[i] = arr[l+i]; - } - for(int i = 0; i < size2; i++){ - tempR[i] = arr[m+i+1]; - } - - //now we merge the two subarrays - - //initial indices of the two subarrays - int i = 0, j = 0; - - //initial index of the merged subarray array - int k = l; - - while(i < size1 && j < size2){ - if(tempL[i] <= tempR[j]){ - arr[k] = tempL[i]; - i++; - } else { - arr[k] = tempR[j]; - j++; - } - k++; - } - - //copy remaining list into arr if any - while(i < size1){ - arr[k++] = tempL[i++]; - } - while(j < size2){ - arr[k++] = tempR[j++]; - } - } + MergeSort test = new MergeSort(); + test.sort(a, 0, a.length - 1); + + System.out.println("\nList after sorting\n"); + for (int i = 0; i < a.length; i++) System.out.print(a[i] + " "); + } + + public void sort(int[] arr, int l, int r) { + if (l < r) { + int m = (l + r) / 2; + sort(arr, l, m); + sort(arr, m + 1, r); + merge(arr, l, m, r); + } + } + + private void merge(int[] arr, int l, int m, int r) { + //find sizes of two subarrays that are to be merged + int size1 = m - l + 1; + int size2 = r - m; + + //copy the two subarrays into two temp arrays + int[] tempL = new int[size1]; + int[] tempR = new int[size2]; + for (int i = 0; i < size1; i++) { + tempL[i] = arr[l + i]; + } + for (int i = 0; i < size2; i++) { + tempR[i] = arr[m + i + 1]; + } + + //now we merge the two subarrays + + //initial indices of the two subarrays + int i = 0, j = 0; + + //initial index of the merged subarray array + int k = l; + + while (i < size1 && j < size2) { + if (tempL[i] <= tempR[j]) { + arr[k] = tempL[i]; + i++; + } else { + arr[k] = tempR[j]; + j++; + } + k++; + } + + //copy remaining list into arr if any + while (i < size1) { + arr[k++] = tempL[i++]; + } + while (j < size2) { + arr[k++] = tempR[j++]; + } + } } From 36bfaf742f66f7c44661301e9a9714b82e7a3886 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Sun, 4 Feb 2024 16:00:46 -0800 Subject: [PATCH 108/132] update ThreadIsCool class --- src/main/java/multithread/ThreadIsCool.java | 93 ++++++++++++--------- 1 file changed, 52 insertions(+), 41 deletions(-) diff --git a/src/main/java/multithread/ThreadIsCool.java b/src/main/java/multithread/ThreadIsCool.java index f062404..a7ae96b 100644 --- a/src/main/java/multithread/ThreadIsCool.java +++ b/src/main/java/multithread/ThreadIsCool.java @@ -1,59 +1,70 @@ package multithread; -/** This is a cool and small program to show that threads don't run in the order that you can control, it's all scheduled by the thing called - * Thread Scheduler.*/ - -public class ThreadIsCool implements Runnable{ - - public static void main(String [] args){ - ThreadIsCool threadIsCool = new ThreadIsCool(); - Thread thread1 = new Thread(threadIsCool); - Thread thread2 = new Thread(threadIsCool); - Thread thread3 = new Thread(threadIsCool); - thread1.setName("Thread Andrew"); - thread2.setName("Thread James"); - thread3.setName("Thread Steve"); - System.out.println("Now the three threads kick off:"); - - thread1.start(); - try { - /* Wait for this thread to die before other invocations*/ +/** + * This is a cool and small program to show that threads run order could be controlled by using Thread.join() method. + */ + +public class ThreadIsCool implements Runnable { + + public static void main(String[] args) { + ThreadIsCool threadIsCool = new ThreadIsCool(); + Thread thread1 = new Thread(threadIsCool); + Thread thread2 = new Thread(threadIsCool); + Thread thread3 = new Thread(threadIsCool); + Thread thread4 = new Thread(threadIsCool); + thread1.setName("Thread 1"); + thread2.setName("Thread 2"); + thread3.setName("Thread 3"); + thread4.setName("Thread 4"); + System.out.println("Now all the threads are about to kick off:"); + + thread1.start(); + try { + /* Wait for this thread to die before other invocations*/ thread1.join(); } catch (InterruptedException e) { e.printStackTrace(); } - - thread2.start(); - try { - /* Wait for this thread to die before other invocations*/ + + thread2.start(); + try { + /* Wait for this thread to die before other invocations*/ thread2.join(); } catch (InterruptedException e) { e.printStackTrace(); } - - thread3.start(); - try { - /* Wait for this thread to die before other invocations*/ + + thread3.start(); + try { + /* Wait for this thread to die before other invocations*/ thread3.join(); } catch (InterruptedException e) { e.printStackTrace(); } - System.out.println("Now the Program ended."); - } - - @Override - public void run(){ - for(int i = 0; i < 10; i++){ - String threadName = Thread.currentThread().getName(); - System.out.println(threadName + " is running!"); - } - System.out.println(Thread.currentThread().getName() + " is sleeping for 3 seconds"); - try { - Thread.sleep(3000); + + thread4.start(); + try { + /* Wait for this thread to die before other invocations*/ + thread4.join(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + System.out.println("Now the Program ended."); + } + + @Override + public void run() { + for (int i = 0; i < 10; i++) { + String threadName = Thread.currentThread().getName(); + System.out.println(threadName + " is running!"); + } + System.out.println(Thread.currentThread().getName() + " is sleeping for 1 second"); + try { + Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } - System.out.println(Thread.currentThread().getName() + " run finished."); - } - + System.out.println(Thread.currentThread().getName() + " run finished."); + } + } From b77e3c3b15566edc77f246a51051680cf00f46da Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Sun, 4 Feb 2024 16:12:33 -0800 Subject: [PATCH 109/132] update TestThread class --- .../withSynchronization/TestThread.java | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/src/main/java/multithread/synchronization/withSynchronization/TestThread.java b/src/main/java/multithread/synchronization/withSynchronization/TestThread.java index 819269c..e027730 100644 --- a/src/main/java/multithread/synchronization/withSynchronization/TestThread.java +++ b/src/main/java/multithread/synchronization/withSynchronization/TestThread.java @@ -12,8 +12,8 @@ * When we start two or more threads within a program, there may be a situation * when multiple threads try to access the same resource and finally they can * produce unforeseen result due to concurrency issue. For example if multiple - * threads try to write within a same file then they may corrupt the data - * because one of the threads can overrite data or while one thread is opening + * threads try to write within the same file then they may corrupt the data + * because one of the threads can overwrite data or while one thread is opening * the same file at the same time another thread might be closing the same file. * * So there is a need to synchronize the action of multiple threads and make @@ -27,11 +27,11 @@ * resources within this block. Following is the general form of the * synchronized statement: * - * synchronized(objectidentifier) { + * synchronized(objectIdentifier) { * // Access shared variables and other shared resources * } * - * Here, the objectidentifier is a reference to an object whose lock associates + * Here, the objectIdentifier is a reference to an object whose lock associates * with the monitor that the synchronized statement represents. Now we are going * to see two examples where we will print a counter using two different * threads. When threads are not synchronized, they print counter value which is @@ -40,19 +40,18 @@ */ public class TestThread { public static void main(String args[]) { + PrintDemo printDemo = new PrintDemo(); - PrintDemo PD = new PrintDemo(); + ThreadDemo threadOne = new ThreadDemo("Thread - 1 ", printDemo); + ThreadDemo threadTwo = new ThreadDemo("Thread - 2 ", printDemo); - ThreadDemo T1 = new ThreadDemo("Thread - 1 ", PD); - ThreadDemo T2 = new ThreadDemo("Thread - 2 ", PD); - - T1.start(); - T2.start(); + threadOne.start(); + threadTwo.start(); // wait for threads to end try { - T1.join(); - T2.join(); + threadOne.join(); + threadTwo.join(); } catch (Exception e) { System.out.println("Interrupted"); } @@ -62,29 +61,30 @@ public static void main(String args[]) { class PrintDemo { public void printCount() { try { + System.out.println(Thread.currentThread().getName() + " is working now.."); for (int i = 5; i > 0; i--) { - System.out.println("Counter --- " + i); + System.out.println("Counter --- " + i + " from thread: " + Thread.currentThread().getName()); } } catch (Exception e) { System.out.println("Thread interrupted."); } } - } class ThreadDemo extends Thread { private Thread t; private String threadName; - PrintDemo PD; + PrintDemo printDemo; ThreadDemo(String name, PrintDemo pd) { threadName = name; - PD = pd; + printDemo = pd; } public void run() { - synchronized (PD) {//Here's all the difference between the two examples! It uses this synchronized keyword to identify the resources that need to be synchronized! - PD.printCount(); + //Here's all the difference between the two examples! It uses this synchronized keyword to identify the resources that need to be synchronized! + synchronized (printDemo) { + printDemo.printCount(); } System.out.println("Thread " + threadName + " exiting."); } From 916b49f3d0daf135222831d16f428135e29a4d94 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Sun, 4 Feb 2024 16:55:35 -0800 Subject: [PATCH 110/132] add a distinct method using Java8 --- .../java8tutorials/lamdaExpressions/LamdaDemo.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/main/java/java8tutorials/lamdaExpressions/LamdaDemo.java b/src/main/java/java8tutorials/lamdaExpressions/LamdaDemo.java index 88b2e31..30798bd 100644 --- a/src/main/java/java8tutorials/lamdaExpressions/LamdaDemo.java +++ b/src/main/java/java8tutorials/lamdaExpressions/LamdaDemo.java @@ -83,12 +83,23 @@ public static void sortInJava8_use_lamda_expressions_and_stream() { print(sorted, "After sorting: "); } + public static void sortInJava8_use_lamda_expressions_and_stream_and_filter() { + List names = Arrays.asList(new Person("Sophie", 27), new Person("Ada", 1), + new Person("Steve", 28), new Person("Eason", 26), new Person("Jenny", 31)); + + System.out.println("In sortInJava8_use_lamda_expressions_and_stream_and_filter method."); + + names.stream().distinct().forEach(System.out::println); + names.stream().map(person -> person.name.charAt(0)).distinct().forEach(System.out::println); + } + public static void main(String...args) { sortInPreJava8(); sortInJava8_use_lamda_expressions(); sortInJava8_use_lamda_expressions_shorter(); sortInJava8_use_lamda_expressions_shorter_even(); sortInJava8_use_lamda_expressions_and_stream(); + sortInJava8_use_lamda_expressions_and_stream_and_filter(); } } From 9ad20f89422fd7631eef2118e16facdc1d9d0e00 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Sun, 4 Feb 2024 20:40:17 -0800 Subject: [PATCH 111/132] update TaskRunner --- src/main/java/java_volatile/TaskRunner.java | 22 ++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/main/java/java_volatile/TaskRunner.java b/src/main/java/java_volatile/TaskRunner.java index 272ce6a..c5cf879 100644 --- a/src/main/java/java_volatile/TaskRunner.java +++ b/src/main/java/java_volatile/TaskRunner.java @@ -3,27 +3,35 @@ public class TaskRunner { /** * This is following the examples from https://www.baeldung.com/java-volatile + * + * Volatile keyword is to deal with Java Memory Model cache coherent challenges: + * To ensure that updates to variables propagate predictably to other threads, we should apply the volatile modifier to those variables. + * This way, we can communicate with runtime and processor to not reorder any instruction involving the volatile variable. + * Also, processors understand that they should immediately flush any updates to these variables so that other threads could read the shared variables most up-to-date values. */ private static int number; - private static boolean ready; + private volatile static boolean ready; private static class Reader extends Thread { @Override public void run() { - System.out.println("ready is: " + ready); + System.out.println(Thread.currentThread().getName() + " thread says, ready = " + ready); while (!ready) { - System.out.println("It's yielding now.."); + System.out.println(Thread.currentThread().getName() + " is yielding now.."); Thread.yield(); } - System.out.println("number is: " + number); + System.out.println(Thread.currentThread().getName() + " thread says, number = " + number); } } - public static void main(String[] args) { - System.out.println("Program started."); + public static void main(String[] args) throws InterruptedException { + System.out.println(Thread.currentThread().getName() + " thread started now..."); new Reader().start(); + System.out.println(Thread.currentThread().getName() + " thread is running now..."); number = 42; + Thread.sleep(6); + System.out.println(Thread.currentThread().getName() + " thread finishes sleeping."); ready = true; - System.out.println("Program finished."); + System.out.println(Thread.currentThread().getName() + " thread finished."); } } From 833230478d2b54c3a44231c8474ecb681f828ca4 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Sun, 4 Feb 2024 20:40:33 -0800 Subject: [PATCH 112/132] update format of ConnectionLimiter --- .../java/semaphore/ConnectionLimiter.java | 103 +++++++++--------- 1 file changed, 51 insertions(+), 52 deletions(-) diff --git a/src/main/java/semaphore/ConnectionLimiter.java b/src/main/java/semaphore/ConnectionLimiter.java index d3b8c6e..751154e 100644 --- a/src/main/java/semaphore/ConnectionLimiter.java +++ b/src/main/java/semaphore/ConnectionLimiter.java @@ -5,67 +5,66 @@ /** * This is a small program to demo how semaphore can create trouble for us. * One rule of thumb is: - * Always release what you acquire! - * Copied from online. - * + * Always release what you acquire! + * Copied from the Internet. */ //this is a bad public class name, it doesn't apply to //what this class really do, it's a name from a different class that I copied earlier. public class ConnectionLimiter { - private static class DoubleResourceGrabber implements Runnable{ - - private Semaphore first; - private Semaphore second; - - public DoubleResourceGrabber(Semaphore s1, Semaphore s2){ - first = s1; - second = s2; - } - - @Override - public void run() { - Thread t = Thread.currentThread(); - - try { - first.acquire(); - System.out.println(t.getName() + " acquired " + first); - + private static class DoubleResourceGrabber implements Runnable { + + private Semaphore first; + private Semaphore second; + + public DoubleResourceGrabber(Semaphore s1, Semaphore s2) { + first = s1; + second = s2; + } + + @Override + public void run() { + Thread t = Thread.currentThread(); + + try { + first.acquire(); + System.out.println(t.getName() + " acquired " + first); + // Thread.sleep(20);//to demo a deadlock - + // second.acquire(); // System.out.println(t.getName() + " acquired " + second); - + // second.release(); // System.out.println(t.getName() + " released " + second); - - first.release(); - System.out.println(t.getName() + " released " + first); - - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - } - - /** - * @param args - * @throws InterruptedException - */ - public static void main(String[] args) throws InterruptedException { - Semaphore s1 = new Semaphore(1);//give it only 1 permit - Semaphore s2 = new Semaphore(1);//give it only 1 permit as well - Thread t1 = new Thread(new DoubleResourceGrabber(s1, s2)); - //now reverse them, here comes the trouble - Thread t2 = new Thread(new DoubleResourceGrabber(s2, s1)); - - t1.start(); - t2.start(); - - t1.join(); - t2.join(); - System.out.println("We got lucky!"); - - } + + first.release(); + System.out.println(t.getName() + " released " + first); + + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + + /** + * @param args + * @throws InterruptedException + */ + public static void main(String[] args) throws InterruptedException { + Semaphore s1 = new Semaphore(1);//give it only 1 permit + Semaphore s2 = new Semaphore(1);//give it only 1 permit as well + Thread t1 = new Thread(new DoubleResourceGrabber(s1, s2)); + //now reverse them, here comes the trouble + Thread t2 = new Thread(new DoubleResourceGrabber(s2, s1)); + + t1.start(); + t2.start(); + + t1.join(); + t2.join(); + System.out.println("We got lucky!"); + + } } From 252bae4dcc992d2d09193858a39d045611c8cf5f Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Mon, 5 Feb 2024 08:30:06 -0800 Subject: [PATCH 113/132] add a HashMap example --- src/main/java/hashmap/MainApp.java | 38 ++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 src/main/java/hashmap/MainApp.java diff --git a/src/main/java/hashmap/MainApp.java b/src/main/java/hashmap/MainApp.java new file mode 100644 index 0000000..0b19870 --- /dev/null +++ b/src/main/java/hashmap/MainApp.java @@ -0,0 +1,38 @@ +package hashmap; + +import java.util.HashMap; +import java.util.Map; + +public class MainApp { + private static final int NUMBER_OF_MAP_ENTRIES = 2; + + public static void main(String... args) { + System.out.println("Program started."); + MainApp mainApp = new MainApp(); + mainApp.understandHashMapInternalWorkings(); + System.out.println("Program finished."); + } + + private void understandHashMapInternalWorkings() { + /**This arcitle says it pretty well: https://levelup.gitconnected.com/internal-working-of-hashmap-in-java-latest-updated-4c2708f76d2c + * 1. HashMap uses its static inner class Node for storing map entries. That means each entry in hashMap is a Node. + * 2. Internally HashMap uses a hashCode of the key Object and this hashCode is further used by the hash function to find the index of the bucket where the new entry can be added. + * 3. HashMap uses multiple buckets and each bucket points to a Singly Linked List where the entries (nodes) are stored. + * 4. Once the bucket is identified by the hash function using hashcode, then hashCode is used to check if there is already a key with the same hashCode or not in the bucket (I mean corresponding singly linked list). + * If there already exists a key with the same hashCode, then the equals() method is used on the keys. + * If the equals method returns true, that means there is already a node with the same key and hence the value against that key is overwritten in the entry (node), + * otherwise, a new node is created and added to this Singly Linked List of that bucket. + * If there is no key with the same hashCode in the bucket found by the hash function then the new Node is added to the bucket found. + * 5. There's a threshold after which is reached, HashMap will change from using singly linked list to use a self-balancing BST, static final int TREEIFY_THRESHOLD = 8; + * the motive for this change is that it could take O(n) worst case for look up with linked list, however, with a self-balancing BST, e.g. red-black tree, we could get O(logn) lookup time; + * + * To have a high-performance hashMap we need good implementation of hashCode() and equals() method along with hash function. + * */ + Map map = new HashMap<>(); + for (int i = 0; i < NUMBER_OF_MAP_ENTRIES; i++) { + map.put("key" + i, "value" + i); + } + map.put("key1", "value_new"); + System.out.println("this method finishes."); + } +} From f95987aff72bf6d0d53cf434c060173bc448ebb2 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Mon, 5 Feb 2024 08:31:17 -0800 Subject: [PATCH 114/132] remove package to be java_collections --- src/main/java/{hashmap => java_collections}/MainApp.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename src/main/java/{hashmap => java_collections}/MainApp.java (99%) diff --git a/src/main/java/hashmap/MainApp.java b/src/main/java/java_collections/MainApp.java similarity index 99% rename from src/main/java/hashmap/MainApp.java rename to src/main/java/java_collections/MainApp.java index 0b19870..882af2a 100644 --- a/src/main/java/hashmap/MainApp.java +++ b/src/main/java/java_collections/MainApp.java @@ -1,4 +1,4 @@ -package hashmap; +package java_collections; import java.util.HashMap; import java.util.Map; From 86d96bafd7efb21780725ed1cfe84b63c65967c4 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Mon, 5 Feb 2024 08:32:38 -0800 Subject: [PATCH 115/132] rename class to be self-explanatory --- .../java/java_collections/{MainApp.java => HashMap.java} | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) rename src/main/java/java_collections/{MainApp.java => HashMap.java} (92%) diff --git a/src/main/java/java_collections/MainApp.java b/src/main/java/java_collections/HashMap.java similarity index 92% rename from src/main/java/java_collections/MainApp.java rename to src/main/java/java_collections/HashMap.java index 882af2a..3aa0ef1 100644 --- a/src/main/java/java_collections/MainApp.java +++ b/src/main/java/java_collections/HashMap.java @@ -1,15 +1,14 @@ package java_collections; -import java.util.HashMap; import java.util.Map; -public class MainApp { +public class HashMap { private static final int NUMBER_OF_MAP_ENTRIES = 2; public static void main(String... args) { System.out.println("Program started."); - MainApp mainApp = new MainApp(); - mainApp.understandHashMapInternalWorkings(); + HashMap hashMap = new HashMap(); + hashMap.understandHashMapInternalWorkings(); System.out.println("Program finished."); } @@ -28,7 +27,7 @@ private void understandHashMapInternalWorkings() { * * To have a high-performance hashMap we need good implementation of hashCode() and equals() method along with hash function. * */ - Map map = new HashMap<>(); + Map map = new java.util.HashMap<>(); for (int i = 0; i < NUMBER_OF_MAP_ENTRIES; i++) { map.put("key" + i, "value" + i); } From 3c615de6c4f678f4a9bea6f9b0f9c090c019d1f3 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Mon, 5 Feb 2024 08:35:14 -0800 Subject: [PATCH 116/132] add Demo suffix to avoid naming conflict --- .../java_collections/{HashMap.java => HashMapDemo.java} | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) rename src/main/java/java_collections/{HashMap.java => HashMapDemo.java} (94%) diff --git a/src/main/java/java_collections/HashMap.java b/src/main/java/java_collections/HashMapDemo.java similarity index 94% rename from src/main/java/java_collections/HashMap.java rename to src/main/java/java_collections/HashMapDemo.java index 3aa0ef1..bd84588 100644 --- a/src/main/java/java_collections/HashMap.java +++ b/src/main/java/java_collections/HashMapDemo.java @@ -2,13 +2,13 @@ import java.util.Map; -public class HashMap { +public class HashMapDemo { private static final int NUMBER_OF_MAP_ENTRIES = 2; public static void main(String... args) { System.out.println("Program started."); - HashMap hashMap = new HashMap(); - hashMap.understandHashMapInternalWorkings(); + HashMapDemo hashMapDemo = new HashMapDemo(); + hashMapDemo.understandHashMapInternalWorkings(); System.out.println("Program finished."); } From 75ac9050a1555691306df2679f3910695f9e715f Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Mon, 5 Feb 2024 08:41:28 -0800 Subject: [PATCH 117/132] add a demo for HashSet --- .../java/java_collections/HashSetDemo.java | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 src/main/java/java_collections/HashSetDemo.java diff --git a/src/main/java/java_collections/HashSetDemo.java b/src/main/java/java_collections/HashSetDemo.java new file mode 100644 index 0000000..cd98ee1 --- /dev/null +++ b/src/main/java/java_collections/HashSetDemo.java @@ -0,0 +1,32 @@ +package java_collections; + +import java.util.HashSet; +import java.util.Set; + +public class HashSetDemo { + + private static final int NUMBER_OF_SET_ENTRIES = 2; + + public static void main(String... args) { + System.out.println("Program started."); + HashSetDemo hashSetDemo = new HashSetDemo(); + hashSetDemo.understandHashSetInternalWorkings(); + System.out.println("Program finished."); + } + + private void understandHashSetInternalWorkings() { + /** + * 1. Internally, Java uses a HashMap to implement HashSet, it just inserts a dummy object as value into the map: private static final Object PRESENT = new Object(); + * you can step into the java.util.HashSet library to see this: + * public boolean add(E e) { + * return map.put(e, PRESENT)==null; + * } + * 2. https://medium.com/javarevisited/internal-working-of-hashset-in-java-interview-question-129bdd31fc60 for more references/ + * */ + Set set = new HashSet<>(); + for (int i = 0; i < NUMBER_OF_SET_ENTRIES; i++) { + set.add(i + ""); + } + System.out.println("Method finishes."); + } +} From a38ef41c0f7ea516a10956801b59dbf492a69e3c Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Mon, 5 Feb 2024 08:59:33 -0800 Subject: [PATCH 118/132] add a stream example --- .../java/java_streams/StreamsExample.java | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 src/main/java/java_streams/StreamsExample.java diff --git a/src/main/java/java_streams/StreamsExample.java b/src/main/java/java_streams/StreamsExample.java new file mode 100644 index 0000000..82af461 --- /dev/null +++ b/src/main/java/java_streams/StreamsExample.java @@ -0,0 +1,43 @@ +package java_streams; + +import java.util.Arrays; +import java.util.List; + +public class StreamsExample { + public static void main(String... args) { + /**reference: https://www.baeldung.com/java-when-to-use-parallel-stream*/ + System.out.println("Program started."); + sequentialStreams(); + parallelStreams(); + System.out.println("Program ended."); + } + + private static void sequentialStreams() { + /**By default, any stream operation in Java is processed sequentially, unless explicitly specified as parallel. + Sequential streams use a single thread to process the pipeline like below: + */ + List listOfNumbers = Arrays.asList(1, 2, 3, 4); + listOfNumbers.stream().forEach(number -> + System.out.println(number + " from this thread: " + Thread.currentThread().getName()) + ); + } + + private static void parallelStreams() { + /** + * Any stream in Java can easily be transformed from sequential to parallel. + * We can achieve this by adding the parallel method to a sequential stream or by creating a stream using the parallelStream method of a collection: + * */ + List listOfNumbers = Arrays.asList(5, 6, 7, 8); + listOfNumbers.parallelStream().forEach(number -> + System.out.println(number + " from this thread: " + Thread.currentThread().getName()) + ); + /** + * Parallel streams enable us to execute code in parallel on separate cores. + * The final result is the combination of each individual outcome. + * However, the order of execution is out of our control.*/ + + /** + * Parallel streams make use of the fork-join framework and its common pool of worker threads. + * The fork-join framework was added to java.util.concurrent in Java 7 to handle task management between multiple threads.*/ + } +} From 0022483f0218d6cb9ef08f9928568a0f35c6ea9d Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Sat, 24 Feb 2024 13:33:25 -0800 Subject: [PATCH 119/132] add a simple one thread example --- src/main/java/multithread/OneThreadDemo.java | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 src/main/java/multithread/OneThreadDemo.java diff --git a/src/main/java/multithread/OneThreadDemo.java b/src/main/java/multithread/OneThreadDemo.java new file mode 100644 index 0000000..df978f8 --- /dev/null +++ b/src/main/java/multithread/OneThreadDemo.java @@ -0,0 +1,20 @@ +package multithread; + +public class OneThreadDemo { + static class MeaninglessClass { + public void meaninglessMethod() { + System.out.println("In meaninglessMethod method now, current thread name is: " + Thread.currentThread().getName()); + } + } + + public static void main(String... args) { + /**This is to show that this program will guarantee to run in just one thread: main, there's no multi-threading here.*/ + MeaninglessClass meaninglessClass = new MeaninglessClass(); + meaninglessClass.meaninglessMethod(); + meaninglessClass.meaninglessMethod(); + meaninglessClass.meaninglessMethod(); + meaninglessClass.meaninglessMethod(); + meaninglessClass.meaninglessMethod(); + System.out.println("Program finished."); + } +} From 21195c232051a5f6a806e937cdf21b6e0ff23d85 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Thu, 20 Jun 2024 21:14:28 -0700 Subject: [PATCH 120/132] add Java Consumer examples --- .../ConsumerInterfaceExample.java | 42 +++++++++++++++++++ .../MainApp.java | 10 +++++ 2 files changed, 52 insertions(+) create mode 100644 src/main/java/javaConsumerInterfaceExamples/ConsumerInterfaceExample.java create mode 100644 src/main/java/javaConsumerInterfaceExamples/MainApp.java diff --git a/src/main/java/javaConsumerInterfaceExamples/ConsumerInterfaceExample.java b/src/main/java/javaConsumerInterfaceExamples/ConsumerInterfaceExample.java new file mode 100644 index 0000000..a0cf1b9 --- /dev/null +++ b/src/main/java/javaConsumerInterfaceExamples/ConsumerInterfaceExample.java @@ -0,0 +1,42 @@ +package javaConsumerInterfaceExamples; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; + +public class ConsumerInterfaceExample { + static void printMessage(String name) { + System.out.println("Hello " + name); + } + + static void printValue(int val) { + System.out.println(val); + } + + static void addList(List list) { + // Return sum of list values + int result = list.stream() + .mapToInt(Integer::intValue) + .sum(); + System.out.println("Sum of list values: " + result); + } + + public static void main(String[] args) { + // Referring method to String type Consumer interface + Consumer consumer1 = ConsumerInterfaceExample::printMessage; + consumer1.accept("John"); // Calling Consumer method + // Referring method to Integer type Consumer interface + Consumer consumer2 = ConsumerInterfaceExample::printValue; + consumer2.accept(12); // Calling Consumer method + + // Creating a list and adding values + List list = new ArrayList<>(); + list.add(10); + list.add(20); + list.add(30); + list.add(40); + // Referring method to String type Consumer interface + Consumer> consumer = ConsumerInterfaceExample::addList; + consumer.accept(list); // Calling Consumer method + } +} diff --git a/src/main/java/javaConsumerInterfaceExamples/MainApp.java b/src/main/java/javaConsumerInterfaceExamples/MainApp.java new file mode 100644 index 0000000..f6baf1f --- /dev/null +++ b/src/main/java/javaConsumerInterfaceExamples/MainApp.java @@ -0,0 +1,10 @@ +package javaConsumerInterfaceExamples; + +import java.util.function.Consumer; + +public class MainApp { + public static void main(String... args) { + Consumer print = x -> System.out.println(x); + print.accept("java 8 consumer interface"); // java + } +} From e29bbac5b4de19498fb6e5bb08ccc6fb6ba5251e Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Thu, 4 Jul 2024 12:06:22 -0700 Subject: [PATCH 121/132] add enum example --- src/main/java/randomExamples/EnumExamples.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 src/main/java/randomExamples/EnumExamples.java diff --git a/src/main/java/randomExamples/EnumExamples.java b/src/main/java/randomExamples/EnumExamples.java new file mode 100644 index 0000000..3204205 --- /dev/null +++ b/src/main/java/randomExamples/EnumExamples.java @@ -0,0 +1,17 @@ +package randomExamples; + +public class EnumExamples { + public static void main(String... args) { + System.out.println(RequestType.GET); + System.out.println(RequestType.GET == RequestType.GET); + System.out.println(RequestType.GET.name()); + } +} + +enum RequestType { + GET, + PUT, + POST, + PATCH, + DELETE +} From 6dcc77516f4007b8f3232b078c875da01807ab1b Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Sun, 7 Jul 2024 10:22:05 -0700 Subject: [PATCH 122/132] add encryption and description example --- .../java/encryption/EncryptionDecryption.java | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 src/main/java/encryption/EncryptionDecryption.java diff --git a/src/main/java/encryption/EncryptionDecryption.java b/src/main/java/encryption/EncryptionDecryption.java new file mode 100644 index 0000000..e975f96 --- /dev/null +++ b/src/main/java/encryption/EncryptionDecryption.java @@ -0,0 +1,80 @@ +package encryption; + +import javax.crypto.*; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.PBEKeySpec; +import javax.crypto.spec.SecretKeySpec; +import javax.xml.bind.DatatypeConverter; +import java.security.AlgorithmParameters; +import java.security.SecureRandom; + +public class EncryptionDecryption { + /** + * This is a small program that uses Java native library to do encryption and description, + * credit: StackOverflow + */ + + private static String salt; + private static int iterations = 65536; + private static int keySize = 256; + private static byte[] ivBytes; + + private static SecretKey secretKey; + + public static void main(String[] args) throws Exception { + System.out.println("Program started."); + salt = getSalt(); + System.out.println("salt is: " + salt); + char[] message = "PasswordToEncrypt".toCharArray(); + System.out.println("Message: " + String.valueOf(message)); + System.out.println("Encrypted: " + encrypt(message)); + System.out.println("Decrypted: " + decrypt(encrypt(message).toCharArray())); + System.out.println("Program ended."); + } + + public static String encrypt(char[] plaintext) throws Exception { + byte[] saltBytes = salt.getBytes(); + + SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); + PBEKeySpec spec = new PBEKeySpec(plaintext, saltBytes, iterations, keySize); + secretKey = secretKeyFactory.generateSecret(spec); + SecretKeySpec secretSpec = new SecretKeySpec(secretKey.getEncoded(), "AES"); + + Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); + cipher.init(Cipher.ENCRYPT_MODE, secretSpec); + AlgorithmParameters algorithmParameters = cipher.getParameters(); + ivBytes = algorithmParameters.getParameterSpec(IvParameterSpec.class).getIV(); + byte[] encryptedTextBytes = cipher.doFinal(String.valueOf(plaintext).getBytes("UTF-8")); + + return DatatypeConverter.printBase64Binary(encryptedTextBytes); + } + + public static String decrypt(char[] encryptedText) throws Exception { + byte[] encryptedTextBytes = DatatypeConverter.parseBase64Binary(new String(encryptedText)); + SecretKeySpec secretSpec = new SecretKeySpec(secretKey.getEncoded(), "AES"); + + Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); + cipher.init(Cipher.DECRYPT_MODE, secretSpec, new IvParameterSpec(ivBytes)); + + byte[] decryptedTextBytes = null; + + try { + decryptedTextBytes = cipher.doFinal(encryptedTextBytes); + } catch (IllegalBlockSizeException e) { + e.printStackTrace(); + } catch (BadPaddingException e) { + e.printStackTrace(); + } + + return new String(decryptedTextBytes); + + } + + public static String getSalt() throws Exception { + //https://docs.oracle.com/en/java/javase/22/docs/specs/security/standard-names.html + SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");//this is the default algorithm, so can be omitted + byte[] salt = new byte[20]; + secureRandom.nextBytes(salt); + return new String(salt); + } +} From d2b859a3829a56ac62d0c35f4ef321e5bff3865f Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Sun, 7 Jul 2024 12:13:43 -0700 Subject: [PATCH 123/132] add encryption and description in Spring example --- pom.xml | 6 +++++ .../SpringSecurityCryptoModule.java | 23 +++++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 src/main/java/encryption/SpringSecurityCryptoModule.java diff --git a/pom.xml b/pom.xml index ac85fbd..9072849 100644 --- a/pom.xml +++ b/pom.xml @@ -189,6 +189,12 @@ test + + org.springframework.security + spring-security-crypto + 6.3.1 + + diff --git a/src/main/java/encryption/SpringSecurityCryptoModule.java b/src/main/java/encryption/SpringSecurityCryptoModule.java new file mode 100644 index 0000000..71ba681 --- /dev/null +++ b/src/main/java/encryption/SpringSecurityCryptoModule.java @@ -0,0 +1,23 @@ +package encryption; + +import org.springframework.security.crypto.keygen.BytesKeyGenerator; +import org.springframework.security.crypto.keygen.KeyGenerators; + +public class SpringSecurityCryptoModule { + /** + * Reference: https://docs.spring.io/spring-security/site/docs/3.1.x/reference/crypto.html + */ + public static void main(String... args) { +// BytesEncryptor encryptor = Encryptors.standard("password", "salt"); + + String salt = KeyGenerators.string().generateKey(); // generates a random 8-byte salt that is then hex-encoded + System.out.println("salt is: " + salt); + +// TextEncryptor textEncryptor = Encryptors.text("password", "salt"); + + BytesKeyGenerator generator = KeyGenerators.secureRandom(); + byte[] key = generator.generateKey(); + System.out.println("key is: " + key); + + } +} From 7bc9a32a4c016a7b308e9d77e56e5470ca9a17a0 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Mon, 9 Sep 2024 08:24:46 -0700 Subject: [PATCH 124/132] [RandomJava-101] update modifier for Java method --- src/main/java/IO_example/JavaFileIOExample.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/IO_example/JavaFileIOExample.java b/src/main/java/IO_example/JavaFileIOExample.java index e967514..1bb3f50 100644 --- a/src/main/java/IO_example/JavaFileIOExample.java +++ b/src/main/java/IO_example/JavaFileIOExample.java @@ -17,7 +17,7 @@ public static void main(String... args) throws IOException { System.out.println("Program finished."); } - private static void readFileOnDisk() throws IOException { + public static void readFileOnDisk() throws IOException { String file = "src/test/resources/sample_input.txt"; Scanner scanner = new Scanner(new File(file)); scanner.useDelimiter(" "); From 993bcbeae2b506966e9f177d267b12543f4c2ba6 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Mon, 9 Sep 2024 08:48:51 -0700 Subject: [PATCH 125/132] [RandomJava-101] update file IO method --- src/main/java/IO_example/JavaFileIOExample.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/main/java/IO_example/JavaFileIOExample.java b/src/main/java/IO_example/JavaFileIOExample.java index 1bb3f50..e307e17 100644 --- a/src/main/java/IO_example/JavaFileIOExample.java +++ b/src/main/java/IO_example/JavaFileIOExample.java @@ -12,14 +12,13 @@ public class JavaFileIOExample { public static void main(String... args) throws IOException { System.out.println("Program started."); - readFileOnDisk(); + readFileOnDisk("src/test/resources/sample_input.txt"); findUniqueCityNames(); System.out.println("Program finished."); } - public static void readFileOnDisk() throws IOException { - String file = "src/test/resources/sample_input.txt"; - Scanner scanner = new Scanner(new File(file)); + public static void readFileOnDisk(String filePath) throws IOException { + Scanner scanner = new Scanner(new File(filePath)); scanner.useDelimiter(" "); assertTrue(scanner.hasNext()); From 5d53c4cbbbd815a853f0157e198fe14984b5a216 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Mon, 9 Sep 2024 15:18:50 -0700 Subject: [PATCH 126/132] [RandomJava-101] add a Utility class to process file --- .../IO_example/ExtractFieldsFromFile.java | 93 +++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 src/main/java/IO_example/ExtractFieldsFromFile.java diff --git a/src/main/java/IO_example/ExtractFieldsFromFile.java b/src/main/java/IO_example/ExtractFieldsFromFile.java new file mode 100644 index 0000000..1d96efc --- /dev/null +++ b/src/main/java/IO_example/ExtractFieldsFromFile.java @@ -0,0 +1,93 @@ +package IO_example; + +import java.io.*; +import java.util.HashSet; +import java.util.Scanner; +import java.util.Set; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class ExtractFieldsFromFile { + private static final String BASE_FILE = "/Users/Downloads/base_file"; + private static final String UPDATE_FILE = "/Users/Downloads/update_file"; + + public static void main(String... args) throws IOException { + System.out.println("Program started."); + readAllFieldNames(""); + Set baseSet = readAllFieldNames(BASE_FILE); + Set updateFileSet = readAllFieldNames(UPDATE_FILE); + Set baseSetCopy = new HashSet<>(baseSet); + baseSetCopy.removeAll(updateFileSet); + System.out.println("baseSetCopy size after removing updateFileSet is: " + baseSetCopy.size()); + + Set linesOnlyExistInBaseSet = readLinesMatchingSet(BASE_FILE, baseSetCopy); +// linesOnlyExistInBaseSet.forEach(System.out::println); + System.out.println("Found a total of " + linesOnlyExistInBaseSet.size() + " matches."); + + appendLinesToFile(UPDATE_FILE, linesOnlyExistInBaseSet); + + System.out.println("Program finished."); + } + + private static void appendLinesToFile(String updateFile, Set linesToBeAppended) throws IOException { + BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(updateFile, true)); + bufferedWriter.append("\n\n\n"); + bufferedWriter.append("#Added below fields from base file ---------\n"); + for (String str : linesToBeAppended) { + bufferedWriter.append(str); + bufferedWriter.append("\n"); + } + bufferedWriter.close(); + } + + private static Set readLinesMatchingSet(String filePath, Set set) throws FileNotFoundException { + if (filePath.isEmpty()) { + System.out.println("No file to read, exit."); + return null; + } + Scanner scanner = new Scanner(new File(filePath)); + scanner.useDelimiter("\n"); + Set lines = new HashSet<>(); + int i = 0; + while (scanner.hasNext()) { + String line = scanner.next(); + i++; + if (!line.isEmpty() && Character.isAlphabetic(line.charAt(0))) { + String[] parts = line.split("="); + if (set.contains(parts[0])) { + lines.add(line); + } + } + } + scanner.close(); + System.out.println("A total of " + i + " lines were gone through, and found a total of " + lines.size() + " matches."); + return lines; + } + + public static Set readAllFieldNames(String filePath) throws IOException { + if (filePath.isEmpty()) { + System.out.println("No file to read, exit."); + return null; + } + Scanner scanner = new Scanner(new File(filePath)); + scanner.useDelimiter("\n"); + + assertTrue(scanner.hasNext()); + int i = 0; + int nonEmptyLines = 0; + Set fields = new HashSet<>(); + while (scanner.hasNext()) { + String line = scanner.next(); + i++; + if (!line.isEmpty() && Character.isAlphabetic(line.charAt(0))) { + String[] parts = line.split("="); + fields.add(parts[0]); + nonEmptyLines++; + } + } + System.out.println("For this file: " + filePath + ": A total of " + i + " lines, in which " + nonEmptyLines + " are non empty."); + + scanner.close(); + return fields; + } +} From a1cbc7fde7da1dc012473dd6cefa3ff723c57a43 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Sat, 12 Oct 2024 15:13:58 -0700 Subject: [PATCH 127/132] [RandomJava-101] upgrade Java version to 17 along with Lombok version upgrade --- pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 9072849..3722b83 100644 --- a/pom.xml +++ b/pom.xml @@ -8,8 +8,8 @@ org.apache.maven.plugins maven-compiler-plugin - 16 - 16 + 17 + 17 @@ -37,7 +37,7 @@ org.projectlombok lombok - 1.18.2 + 1.18.20 provided From bd5486acd709e40e1ef4100b85f755e507f257c4 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Sat, 12 Oct 2024 15:17:19 -0700 Subject: [PATCH 128/132] [RandomJava-101] separate out Parameterized tests --- src/test/junit5/Junit5Test.java | 22 --------------- .../junit5/ParameterizedTestExampleTest.java | 28 +++++++++++++++++++ 2 files changed, 28 insertions(+), 22 deletions(-) create mode 100644 src/test/junit5/ParameterizedTestExampleTest.java diff --git a/src/test/junit5/Junit5Test.java b/src/test/junit5/Junit5Test.java index e8e5bea..d6352a5 100644 --- a/src/test/junit5/Junit5Test.java +++ b/src/test/junit5/Junit5Test.java @@ -1,17 +1,11 @@ package junit5; -import org.apache.logging.log4j.util.Strings; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; - -import java.util.stream.Stream; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -52,22 +46,6 @@ void assertThrowsException() { }); } - @ParameterizedTest - @MethodSource("data") - public void parameterizedTest(String input, boolean expected) { - System.out.println("input is: " + input + ", expected is: " + expected); - assertEquals(expected, Strings.isBlank(input)); - } - - private static Stream data() { - return Stream.of( - Arguments.of(null, true), - Arguments.of("", true), - Arguments.of(" ", true), - Arguments.of("not blank", false) - ); - } - @AfterEach void tearDown() { System.out.println("@AfterEach - executed after each test method."); diff --git a/src/test/junit5/ParameterizedTestExampleTest.java b/src/test/junit5/ParameterizedTestExampleTest.java new file mode 100644 index 0000000..e856e13 --- /dev/null +++ b/src/test/junit5/ParameterizedTestExampleTest.java @@ -0,0 +1,28 @@ +package junit5; + +import org.apache.logging.log4j.util.Strings; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.stream.Stream; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class ParameterizedTestExampleTest { + @ParameterizedTest + @MethodSource("data") + public void parameterizedTest(String input, boolean expected) { + System.out.println("input is: " + input + ", expected is: " + expected); + assertEquals(expected, Strings.isBlank(input)); + } + + private static Stream data() { + return Stream.of( + Arguments.of(null, true), + Arguments.of("", true), + Arguments.of(" ", true), + Arguments.of("not blank", false) + ); + } +} From 66629b68acef10abe23e4e098acc86cdc9f83fec Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Fri, 18 Oct 2024 11:56:29 -0700 Subject: [PATCH 129/132] [RandomJava-101] add two parameterized test classes --- src/test/junit5/BaseTest.java | 6 ++++++ src/test/junit5/ChildTest.java | 22 ++++++++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 src/test/junit5/BaseTest.java create mode 100644 src/test/junit5/ChildTest.java diff --git a/src/test/junit5/BaseTest.java b/src/test/junit5/BaseTest.java new file mode 100644 index 0000000..073f751 --- /dev/null +++ b/src/test/junit5/BaseTest.java @@ -0,0 +1,6 @@ +package junit5; + +public class BaseTest { + protected String field1; + protected Integer field2; +} diff --git a/src/test/junit5/ChildTest.java b/src/test/junit5/ChildTest.java new file mode 100644 index 0000000..aff3b9f --- /dev/null +++ b/src/test/junit5/ChildTest.java @@ -0,0 +1,22 @@ +package junit5; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.stream.Stream; + +import static org.junit.jupiter.api.Assertions.assertNull; + +public class ChildTest extends BaseTest { + + private static Stream data() { + return Stream.of(Arguments.of("string1")); + } + + @ParameterizedTest + @MethodSource("data") + public void test1() { + assertNull(this.field2); + } +} From d75ef5a51eb67ed1327dff1b118c37049a60e3f9 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Sun, 20 Oct 2024 09:51:25 -0700 Subject: [PATCH 130/132] [RandomJava-101] add parallel unit tests examples --- src/test/junit5/FirstParallelUnitTest.java | 19 +++++++++++++++++++ src/test/junit5/SecondParallelUnitTest.java | 19 +++++++++++++++++++ src/test/resources/junit-platform.properties | 3 +++ 3 files changed, 41 insertions(+) create mode 100644 src/test/junit5/FirstParallelUnitTest.java create mode 100644 src/test/junit5/SecondParallelUnitTest.java create mode 100644 src/test/resources/junit-platform.properties diff --git a/src/test/junit5/FirstParallelUnitTest.java b/src/test/junit5/FirstParallelUnitTest.java new file mode 100644 index 0000000..a82734d --- /dev/null +++ b/src/test/junit5/FirstParallelUnitTest.java @@ -0,0 +1,19 @@ +package junit5; + +import org.junit.jupiter.api.Test; + +public class FirstParallelUnitTest { + @Test + public void first() throws Exception { + System.out.println("FirstParallelUnitTest first() start => " + Thread.currentThread().getName()); + Thread.sleep(500); + System.out.println("FirstParallelUnitTest first() end => " + Thread.currentThread().getName()); + } + + @Test + public void second() throws Exception { + System.out.println("FirstParallelUnitTest second() start => " + Thread.currentThread().getName()); + Thread.sleep(500); + System.out.println("FirstParallelUnitTest second() end => " + Thread.currentThread().getName()); + } +} diff --git a/src/test/junit5/SecondParallelUnitTest.java b/src/test/junit5/SecondParallelUnitTest.java new file mode 100644 index 0000000..5daf074 --- /dev/null +++ b/src/test/junit5/SecondParallelUnitTest.java @@ -0,0 +1,19 @@ +package junit5; + +import org.junit.jupiter.api.Test; + +public class SecondParallelUnitTest { + @Test + public void first() throws Exception { + System.out.println("SecondParallelUnitTest first() start => " + Thread.currentThread().getName()); + Thread.sleep(500); + System.out.println("SecondParallelUnitTest first() end => " + Thread.currentThread().getName()); + } + + @Test + public void second() throws Exception { + System.out.println("SecondParallelUnitTest second() start => " + Thread.currentThread().getName()); + Thread.sleep(500); + System.out.println("SecondParallelUnitTest second() end => " + Thread.currentThread().getName()); + } +} diff --git a/src/test/resources/junit-platform.properties b/src/test/resources/junit-platform.properties new file mode 100644 index 0000000..ad19ea8 --- /dev/null +++ b/src/test/resources/junit-platform.properties @@ -0,0 +1,3 @@ +junit.jupiter.execution.parallel.enabled = true +junit.jupiter.execution.parallel.mode.default = concurrent +junit.jupiter.execution.parallel.mode.classes.default = concurrent \ No newline at end of file From 492e550465c9758a024c56fcba18f88cfb8599e4 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Thu, 19 Dec 2024 19:27:42 -0800 Subject: [PATCH 131/132] [RandomJava-101] add OpenCSV example --- pom.xml | 5 +++ .../java/randomExamples/OpenCSVExample.java | 31 +++++++++++++++++++ .../resources/values_with_comma_inside.csv | 6 ++++ 3 files changed, 42 insertions(+) create mode 100644 src/main/java/randomExamples/OpenCSVExample.java create mode 100644 src/test/resources/values_with_comma_inside.csv diff --git a/pom.xml b/pom.xml index 3722b83..ee65683 100644 --- a/pom.xml +++ b/pom.xml @@ -22,6 +22,11 @@ 1.0-SNAPSHOT + + com.opencsv + opencsv + 5.9 + org.apache.logging.log4j diff --git a/src/main/java/randomExamples/OpenCSVExample.java b/src/main/java/randomExamples/OpenCSVExample.java new file mode 100644 index 0000000..6879c1f --- /dev/null +++ b/src/main/java/randomExamples/OpenCSVExample.java @@ -0,0 +1,31 @@ +package randomExamples; + +import com.opencsv.CSVReader; +import com.opencsv.exceptions.CsvValidationException; + +import java.io.FileReader; +import java.io.IOException; + +public class OpenCSVExample { + /** + * This is a good example to show that this popular CSV library that can handle fields that contain comma in CSV files well. + * Look at this file: values_with_comma_inside.csv, some fields have comma in them, which are enclosed with double quotes, + * if you use string.split(","), that field will be broken into parts which is wrong, + * whereas using this library will help take care of this case very well. + */ + public static void main(String[] args) throws CsvValidationException { + String file = "src/test/resources/values_with_comma_inside.csv"; + try (CSVReader reader = new CSVReader(new FileReader(file))) { + String[] nextLine; + while ((nextLine = reader.readNext()) != null) { + System.out.println("nextLine.length is: " + nextLine.length); + for (int i = 0; i < nextLine.length; i++) { + System.out.println("nextLine[" + i + "] is: " + nextLine[i]); + } + System.out.println(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/src/test/resources/values_with_comma_inside.csv b/src/test/resources/values_with_comma_inside.csv new file mode 100644 index 0000000..977ea75 --- /dev/null +++ b/src/test/resources/values_with_comma_inside.csv @@ -0,0 +1,6 @@ +9130348058430616,FixIT LLC +1376819470,"JACKSON ABC, LLC. " +1313034490,Campers Cove LLC +123145734316537,"Nice Corp, LLC" +9130347434882146,FORCE COLLIDE LLC +539967725,"Watson Group, LLC. " \ No newline at end of file From 24895517ae852d992a0587af45bce635e4c61602 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Thu, 19 Dec 2024 19:28:59 -0800 Subject: [PATCH 132/132] [RandomJava-101] update csv file --- src/test/resources/values_with_comma_inside.csv | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/test/resources/values_with_comma_inside.csv b/src/test/resources/values_with_comma_inside.csv index 977ea75..32d8d9c 100644 --- a/src/test/resources/values_with_comma_inside.csv +++ b/src/test/resources/values_with_comma_inside.csv @@ -1,6 +1,5 @@ -9130348058430616,FixIT LLC -1376819470,"JACKSON ABC, LLC. " -1313034490,Campers Cove LLC -123145734316537,"Nice Corp, LLC" -9130347434882146,FORCE COLLIDE LLC -539967725,"Watson Group, LLC. " \ No newline at end of file +fjdosibv,FixIT LLC +98cdsjoin,"JACKSON ABC, LLC. " +1234,Campers Nice LLC +abc123,"Nice Corp, LLC" +9876,"Watson Group, LLC. " \ No newline at end of file