From 201780e3d611eee7d5adef37e25af85c40c69cfb Mon Sep 17 00:00:00 2001
From: Steve Sun <stevesun@coupang.com>
Date: Sun, 18 Dec 2016 18:02:09 -0800
Subject: [PATCH 001/185] correct package names

---
 .../MaximumSizeSubarraySumEqualsOrSmallerThanK.java             | 2 +-
 src/interviewQuestions/MinFloors.java                           | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/interviewQuestions/MaximumSizeSubarraySumEqualsOrSmallerThanK.java b/src/interviewQuestions/MaximumSizeSubarraySumEqualsOrSmallerThanK.java
index 6f2cc67..33df3a1 100644
--- a/src/interviewQuestions/MaximumSizeSubarraySumEqualsOrSmallerThanK.java
+++ b/src/interviewQuestions/MaximumSizeSubarraySumEqualsOrSmallerThanK.java
@@ -1,4 +1,4 @@
-package interviewQuestions;
+package InterviewQuestions;
 
 import java.util.HashMap;
 import java.util.Map;
diff --git a/src/interviewQuestions/MinFloors.java b/src/interviewQuestions/MinFloors.java
index a20e895..3a3fe6d 100644
--- a/src/interviewQuestions/MinFloors.java
+++ b/src/interviewQuestions/MinFloors.java
@@ -1,4 +1,4 @@
-package interviewQuestions;
+package InterviewQuestions;
 
 import java.util.Arrays;
 import java.util.HashMap;

From 7a51cc961e1a1f35cedb966ca717504218abe73f Mon Sep 17 00:00:00 2001
From: Steve Sun <stevesun@coupang.com>
Date: Mon, 19 Dec 2016 08:46:29 -0800
Subject: [PATCH 002/185] sorting algorithms

---
 src/sporadic/sorting/HeapSort.java      |   7 +
 src/sporadic/sorting/InsertionSort.java |  66 +++++++++
 src/sporadic/sorting/MergeSort.java     |  69 +++++++++
 src/sporadic/sorting/QuickSort.java     | 187 ++++++++++++++++++++++++
 4 files changed, 329 insertions(+)
 create mode 100644 src/sporadic/sorting/HeapSort.java
 create mode 100644 src/sporadic/sorting/InsertionSort.java
 create mode 100644 src/sporadic/sorting/MergeSort.java
 create mode 100644 src/sporadic/sorting/QuickSort.java

diff --git a/src/sporadic/sorting/HeapSort.java b/src/sporadic/sorting/HeapSort.java
new file mode 100644
index 0000000..c8e62f0
--- /dev/null
+++ b/src/sporadic/sorting/HeapSort.java
@@ -0,0 +1,7 @@
+package sorting;
+
+public class HeapSort {
+	public static void main(String...strings){
+		System.out.println("Hello World!");
+	}
+}
diff --git a/src/sporadic/sorting/InsertionSort.java b/src/sporadic/sorting/InsertionSort.java
new file mode 100644
index 0000000..90041ea
--- /dev/null
+++ b/src/sporadic/sorting/InsertionSort.java
@@ -0,0 +1,66 @@
+package sorting;
+
+import java.util.Random;
+
+public class InsertionSort {
+	
+	public static int[] generateRandomArray(int len) {
+		int[] nums = new int[len];
+		for(int i = 0; i < len; i++){
+			nums[i] = (new Random()).nextInt(200);
+		}
+		return nums;
+	}
+
+	public int[] insertionSort(int[] nums){
+		long lStartTime = System.currentTimeMillis();
+		for(int i = 1; i < nums.length; i++){
+			int j = i-1;
+			if(nums[i] > nums[j]) continue;
+			while(j >= 0 && nums[j] > nums[i]){
+				swap(nums, j, i);
+				j--;
+				i--;
+			}
+		}
+		long lEndTime = System.currentTimeMillis();
+		System.out.println("Elapsed milliseconds: " + (lEndTime - lStartTime));
+		return nums;
+	}
+
+	private void swap(int[] nums, int j, int i) {
+		int temp = nums[i];
+		nums[i] = nums[j];
+		nums[j] = temp;
+	}
+	
+	public static void print(int[] nums){
+		for(int i : nums) System.out.print( i + ", ");
+		System.out.println();
+	}
+	
+	public static void main(String... args){
+//		System.out.println(2 >> 4);
+//		System.out.println(Integer.toBinaryString(32));
+		int[] nums = generateRandomArray(10);
+		InsertionSort test = new InsertionSort();
+		test.print(nums);
+//		test.swap(nums, 2, 0);
+//		test.print(nums);
+		test.print(test.insertionSortAgain(nums));
+//		test.print(test.insertionSort(nums));
+	}
+	
+	public int[] insertionSortAgain(int[] nums){
+		for(int i = 1; i < nums.length; i++){
+			for(int j = i-1; j >= 0; j--){
+				if(nums[j+1] <= nums[j]){
+					int temp = nums[j+1];
+					nums[j+1] = nums[j];
+					nums[j] = temp;
+				}
+			}
+		}
+		return nums;
+	}
+}
diff --git a/src/sporadic/sorting/MergeSort.java b/src/sporadic/sorting/MergeSort.java
new file mode 100644
index 0000000..18adafb
--- /dev/null
+++ b/src/sporadic/sorting/MergeSort.java
@@ -0,0 +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];
+
+		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);
+		}
+	}
+
+	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++];
+		}
+	}
+}
diff --git a/src/sporadic/sorting/QuickSort.java b/src/sporadic/sorting/QuickSort.java
new file mode 100644
index 0000000..4e8c314
--- /dev/null
+++ b/src/sporadic/sorting/QuickSort.java
@@ -0,0 +1,187 @@
+package sorting;
+
+public class QuickSort {
+	public int[] quickSort(int[] nums){
+		quickSort(nums, 0, nums.length-1);
+		return nums;
+	}
+
+	private void quickSort(int[] nums, int low, int high) {
+		if(low < high){
+			System.out.println("low = " + low + " high = " + high);
+			InsertionSort.print(nums);
+			int pi = partition_last(nums, low, high);
+			System.out.println("pi = " + pi);
+			InsertionSort.print(nums);
+			quickSort(nums, low, pi-1);
+			System.out.println("from " + low + " to " + (pi - 1) + " is already sorted, we'll start to sort the right half from " + (pi+1) + " to " + high);
+			InsertionSort.print(nums);
+			quickSort(nums, pi+1, high);
+			System.out.println("Final sorted list is: ");
+			InsertionSort.print(nums);
+		}
+		
+	}
+	
+	private int partition_last(int[] nums, int low, int high) {
+		int pivot = nums[high];
+		int i = (low-1);
+		for(int j = low; j <= high-1; j++){
+			if(nums[j] <= pivot){
+				i++;
+				//swap nums[i] and nums[j]
+				int temp = nums[i];
+				nums[i] = nums[j];
+				nums[j] = temp;
+			}
+		}
+		
+		//swap nums[i+1] and nums[high]
+		int temp = nums[i+1];
+		nums[i+1] = nums[high];
+		nums[high] = temp;
+		
+		return i+1;
+	}
+	
+	// this method find the pivot and do the sorting
+		private int partition_first(int[] list, int first, int last) {
+			int pivot = list[first];
+			int low = first + 1; // searching forward from pivot'next element
+			int high = last;// searching from the end for backward
+			while (low < high) {
+				// forward searching
+				while (low <= high && list[low] < pivot)
+					low++;
+				// backward searching
+				while (low <= high && list[high] >= pivot)
+					high--;
+				// swap two elements in the list when list[high]<pivot
+				if (high > low) {
+					int temp = list[high];
+					list[high] = list[low];
+					list[low] = temp;
+				}
+			}
+
+			while (high > first && list[high] >= pivot)
+				high--;
+			// swap pivot
+			if (pivot > list[high]) {
+				list[first] = list[high];
+				list[high] = pivot;
+				return high;
+			} else {
+				return first;
+			}
+		}
+	
+	public static void main(String... args){
+		int[] nums = InsertionSort.generateRandomArray(17);
+//		int[] nums = new int[]{10, 7, 8, 9, 1, 5};
+		InsertionSort.print(nums);
+//		test.swap(nums, 2, 0);
+//		test.print(nums);
+		QuickSort test = new QuickSort();
+//		InsertionSort.print(test.quickSort(nums));
+//		InsertionSort.print(test.quickSort_20160628(nums));
+//		InsertionSort.print(test.quickSort_pivot_first_20160628(nums));
+		InsertionSort.print(test.quickSort_pivot_median_20160628(nums));
+		
+		
+	}
+	
+	int[] quickSort_20160628(int[] nums){
+		quickSort_20160628(nums, 0, nums.length-1);
+		return nums;
+	}
+
+	void quickSort_20160628(int[] nums, int low, int high) {
+		if(low < high){
+			int pi = partition_20160628(nums, low, high);
+			quickSort_20160628(nums, low, pi-1);
+			quickSort_20160628(nums, pi+1, high);
+		}
+	}
+
+	int partition_20160628(int[] nums, int low, int high) {
+		int pivot = nums[high];
+		int i = low-1;
+		for(int j = low; j <= high-1; j++){
+			if(nums[j] <= pivot){
+				i++;
+				
+				int temp = nums[i];
+				nums[i] = nums[j];
+				nums[j] = temp;
+			}
+		}
+		
+		int temp = nums[i+1];
+		nums[i+1] = nums[high];
+		nums[high] = temp;
+		return i+1;
+	}
+	
+	//This below method is also accepted on http://www.practice.geeksforgeeks.org/problem-page.php?pid=700151
+	int[] quickSort_pivot_first_20160628(int[] nums){
+		quickSort_pivot_first_20160628(nums, 0, nums.length-1);
+		return nums;
+	}
+
+	private void quickSort_pivot_first_20160628(int[] nums, int low, int high) {
+		if (low < high) {
+			int pi = partition_pivot_first_20160628(nums, low, high);
+			quickSort_pivot_first_20160628(nums, low, pi - 1);
+			quickSort_pivot_first_20160628(nums, pi + 1, high);
+		}
+	}
+
+	private int partition_pivot_first_20160628(int[] nums, int low, int high) {
+		int pivot = nums[low];
+		int i = high+1;
+		for(int j = high; j > low; j--){
+			if(nums[j] > pivot){
+				i--;
+				
+				int temp = nums[j];
+				nums[j] = nums[i];
+				nums[i] = temp;
+			}
+		}
+		
+		int temp = nums[low];
+		nums[low] = nums[i-1];
+		nums[i-1] = temp;
+		
+		return i-1;
+	}
+	
+	int[] quickSort_pivot_median_20160628(int[] nums){
+		quickSort_pivot_median_20160628(nums, 0, nums.length-1);
+		return nums;
+	}
+
+	void quickSort_pivot_median_20160628(int[] nums, int low, int high) {
+		if(nums == null || nums.length == 0) return ;
+		if(low >= high) return;
+		
+		int i = low, j = high, mid = (low+high)/2, pivot = nums[mid];
+		
+		while(i <= j){
+			while(nums[i] < pivot) i++;
+			while(nums[j] > pivot) j--;
+			if(i <= j){
+				int temp = nums[i];
+				nums[i] = nums[j];
+				nums[j] = temp;
+				i++;
+				j--;
+			}
+		}
+		
+		if(low < j) quickSort_pivot_median_20160628(nums, low, j);
+		if(i < high) quickSort_pivot_median_20160628(nums, i, high);
+	}
+
+}

From 56eec86eafc742ac3b7122c1a18ddeded9c8812e Mon Sep 17 00:00:00 2001
From: Steve Sun <stevesun@coupang.com>
Date: Tue, 20 Dec 2016 22:15:05 -0800
Subject: [PATCH 003/185] change package

---
 src/sporadic/sorting/HeapSort.java      | 3 ++-
 src/sporadic/sorting/InsertionSort.java | 2 +-
 src/sporadic/sorting/MergeSort.java     | 2 +-
 src/sporadic/sorting/QuickSort.java     | 2 +-
 4 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/src/sporadic/sorting/HeapSort.java b/src/sporadic/sorting/HeapSort.java
index c8e62f0..7c5e873 100644
--- a/src/sporadic/sorting/HeapSort.java
+++ b/src/sporadic/sorting/HeapSort.java
@@ -1,6 +1,7 @@
-package sorting;
+package sporadic.sorting;
 
 public class HeapSort {
+	//TODO: implement it here.
 	public static void main(String...strings){
 		System.out.println("Hello World!");
 	}
diff --git a/src/sporadic/sorting/InsertionSort.java b/src/sporadic/sorting/InsertionSort.java
index 90041ea..80aaa83 100644
--- a/src/sporadic/sorting/InsertionSort.java
+++ b/src/sporadic/sorting/InsertionSort.java
@@ -1,4 +1,4 @@
-package sorting;
+package sporadic.sorting;
 
 import java.util.Random;
 
diff --git a/src/sporadic/sorting/MergeSort.java b/src/sporadic/sorting/MergeSort.java
index 18adafb..ea22303 100644
--- a/src/sporadic/sorting/MergeSort.java
+++ b/src/sporadic/sorting/MergeSort.java
@@ -1,4 +1,4 @@
-package sorting;
+package sporadic.sorting;
 
 public class MergeSort {
 	public static void main(String...strings){
diff --git a/src/sporadic/sorting/QuickSort.java b/src/sporadic/sorting/QuickSort.java
index 4e8c314..53b7591 100644
--- a/src/sporadic/sorting/QuickSort.java
+++ b/src/sporadic/sorting/QuickSort.java
@@ -1,4 +1,4 @@
-package sorting;
+package sporadic.sorting;
 
 public class QuickSort {
 	public int[] quickSort(int[] nums){

From d667df4c75ee81be47930d6402742fdcff51f592 Mon Sep 17 00:00:00 2001
From: Steve Sun <stevesun@coupang.com>
Date: Mon, 26 Dec 2016 21:20:21 -0800
Subject: [PATCH 004/185] use explicit getters and setters to avoid lombok not
 working cases

---
 .../chapter_3_decorator_pattern/Beverage.java |  9 +--
 .../Employee.java                             | 53 ++++++++++++----
 src/sporadic/jsonExample/JsonDemoClass.java   | 60 ++++++++++++++-----
 3 files changed, 90 insertions(+), 32 deletions(-)

diff --git a/src/designPatterns/chapter_3_decorator_pattern/Beverage.java b/src/designPatterns/chapter_3_decorator_pattern/Beverage.java
index 8585a7f..6202fef 100644
--- a/src/designPatterns/chapter_3_decorator_pattern/Beverage.java
+++ b/src/designPatterns/chapter_3_decorator_pattern/Beverage.java
@@ -1,10 +1,11 @@
 package designPatterns.chapter_3_decorator_pattern;
 
-import lombok.Getter;
-
 public abstract class Beverage {
-	@Getter
 	String description = "Unknown beverage";
-	
+
+	public String getDescription() {
+		return description;
+	}
+
 	public abstract double cost();
 }
diff --git a/src/learnHeadFirstJava/another_serialization_example/Employee.java b/src/learnHeadFirstJava/another_serialization_example/Employee.java
index f841037..c4992bd 100644
--- a/src/learnHeadFirstJava/another_serialization_example/Employee.java
+++ b/src/learnHeadFirstJava/another_serialization_example/Employee.java
@@ -6,9 +6,7 @@
 import org.springframework.stereotype.Repository;
 import org.springframework.stereotype.Service;
 
-import lombok.Getter;
 import lombok.RequiredArgsConstructor;
-import lombok.Setter;
 
 //Any one of the following three annotations: @Service, @Repository and @Component will work fine here since I'm doing a component-scan.
 //@Component
@@ -16,20 +14,51 @@
 @Service
 @RequiredArgsConstructor
 public class Employee implements Serializable {
-	@Setter
-	@Getter
 	private String address;
-	@Setter
-	@Getter
+
+	public String getAddress() {
+		return address;
+	}
+
+	public void setAddress(String address) {
+		this.address = address;
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	public void setName(String name) {
+		this.name = name;
+	}
+
+	public int getAge() {
+		return age;
+	}
+
+	public void setAge(int age) {
+		this.age = age;
+	}
+
+	public double getSalary() {
+		return salary;
+	}
+
+	public void setSalary(double salary) {
+		this.salary = salary;
+	}
+
+	public int getSSN() {
+		return SSN;
+	}
+
+	public void setSSN(int SSN) {
+		this.SSN = SSN;
+	}
+
 	private String name;
-	@Setter
-	@Getter
 	private int age;
-	@Setter
-	@Getter
 	private double salary;
-	@Setter
-	@Getter
 	private transient int SSN;// any field that cannot be serialized needs to be
 								// marked as transient, for demo purpose, we
 								// just set SSN as a non-serializable field, it
diff --git a/src/sporadic/jsonExample/JsonDemoClass.java b/src/sporadic/jsonExample/JsonDemoClass.java
index 8f8154c..f536c43 100644
--- a/src/sporadic/jsonExample/JsonDemoClass.java
+++ b/src/sporadic/jsonExample/JsonDemoClass.java
@@ -6,9 +6,7 @@
 import org.springframework.stereotype.Repository;
 import org.springframework.stereotype.Service;
 
-import lombok.Getter;
 import lombok.NoArgsConstructor;
-import lombok.Setter;
 import lombok.ToString;
 
 /**This package is to demo how @JsonIgnore and @JsonIgnorProperties and @JsonProperty work:
@@ -22,27 +20,57 @@
 @ToString
 @JsonIgnoreProperties({"noInterestingMember", "forgetThisField"})
 public class JsonDemoClass {
-	@Getter
-	@Setter
+	public long getId() {
+		return id;
+	}
+
+	public void setId(long id) {
+		this.id = id;
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	public void setName(String name) {
+		this.name = name;
+	}
+
+	public String getNoInterestingMember() {
+		return noInterestingMember;
+	}
+
+	public void setNoInterestingMember(String noInterestingMember) {
+		this.noInterestingMember = noInterestingMember;
+	}
+
+	public int getAnotherMember() {
+		return anotherMember;
+	}
+
+	public void setAnotherMember(int anotherMember) {
+		this.anotherMember = anotherMember;
+	}
+
+	public double getForgetThisField() {
+		return forgetThisField;
+	}
+
+	public void setForgetThisField(double forgetThisField) {
+		this.forgetThisField = forgetThisField;
+	}
+
 	@JsonProperty("ID")
 	public long id;
-	
-	@Getter
-	@Setter
+
 	@JsonProperty("NAME")
 	public String name;
-	
-	@Getter
-	@Setter
+
 	public String noInterestingMember;
-	
-	@Getter
-	@Setter
+
 	@JsonIgnore
 	@JsonProperty("ANOTHER-MEMEBR")
 	public int anotherMember;
-	
-	@Getter
-	@Setter
+
 	public double forgetThisField;
 }
\ No newline at end of file

From a9679b11d220da2d1fa16166fe4473c3211fba1f Mon Sep 17 00:00:00 2001
From: Steve Sun <stevesun@coupang.com>
Date: Mon, 26 Dec 2016 21:21:38 -0800
Subject: [PATCH 005/185] change package name

---
 src/interviewQuestions/ConcatenatedWordsII.java | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/interviewQuestions/ConcatenatedWordsII.java b/src/interviewQuestions/ConcatenatedWordsII.java
index 1f17d27..9d964d0 100644
--- a/src/interviewQuestions/ConcatenatedWordsII.java
+++ b/src/interviewQuestions/ConcatenatedWordsII.java
@@ -1,4 +1,4 @@
-package interviewQuestions;
+package InterviewQuestions;
 
 import java.io.BufferedReader;
 import java.io.BufferedWriter;

From 7979805f115fe5a1b2ee05aaff20455e7849650a Mon Sep 17 00:00:00 2001
From: Steve Sun <stevesun@coupang.com>
Date: Thu, 29 Dec 2016 16:32:20 -0800
Subject: [PATCH 006/185] understand Java reference

---
 src/sporadic/UnderstandingJavaReference.java | 25 ++++++++++++++++++++
 1 file changed, 25 insertions(+)
 create mode 100644 src/sporadic/UnderstandingJavaReference.java

diff --git a/src/sporadic/UnderstandingJavaReference.java b/src/sporadic/UnderstandingJavaReference.java
new file mode 100644
index 0000000..03a42c3
--- /dev/null
+++ b/src/sporadic/UnderstandingJavaReference.java
@@ -0,0 +1,25 @@
+package sporadic;
+
+/**
+ * Created by stevesun on 12/29/16.
+ */
+public class UnderstandingJavaReference {
+    /**This is a good example to understand how references work in Java.*/
+    public static void main(String[] args) {
+        /**String.replace() method has a return value, this method actually creates a new string
+         * to return, these four lines of code assign the newly created string to this reference 'a',
+         * that's why a got changed the second time I print it out.*/
+        String a = "ABCabc";
+        System.out.println(a);
+        a = a.replace('A', 'a');
+        System.out.println(a);
+
+        /**Here, we didn't assign the newly created string to ss, that's why ss didn't change when
+         * I print it out the second time.
+         * I can find more details if I open up String.replace() method.*/
+        String ss = "123456";
+        System.out.println(ss);
+        ss.replace('1', '0');
+        System.out.println(ss);
+    }
+}

From b435b8cface334e3f5641631d93edaad54136429 Mon Sep 17 00:00:00 2001
From: Steve Sun <stevesun@coupang.com>
Date: Thu, 29 Dec 2016 16:41:48 -0800
Subject: [PATCH 007/185] heap sort

---
 src/sporadic/sorting/HeapSort.java      | 70 ++++++++++++++++++++++++-
 src/sporadic/sorting/HeapSortAgain.java | 58 ++++++++++++++++++++
 2 files changed, 126 insertions(+), 2 deletions(-)
 create mode 100644 src/sporadic/sorting/HeapSortAgain.java

diff --git a/src/sporadic/sorting/HeapSort.java b/src/sporadic/sorting/HeapSort.java
index 7c5e873..a394cc2 100644
--- a/src/sporadic/sorting/HeapSort.java
+++ b/src/sporadic/sorting/HeapSort.java
@@ -1,8 +1,74 @@
 package sporadic.sorting;
 
 public class HeapSort {
-	//TODO: implement it here.
+	private static int N;
+
+	public static void sort(int[] nums) {
+		heapify(nums);// put the initial array into a heap
+		for (int i = N; i > 0; i--) {
+			swap(nums, 0, i);// the number at index zero is always the largest
+			// in
+			// the current UN-sorted array, so we always swap it with the
+			// current
+			// last one which is i
+			N = N - 1;// then we decrement N by 1 so that in the following
+			// maxheap() function we only need to work on elements
+			// from index zero to N (this N is decremented by 1 each
+			// time)
+			maxheap(nums, 0);// this is the maintain the heap property after
+			// placing its previous largest number into the
+			// correct place and get ready for next round of
+			// swap: take the max (root) out from the heap.
+		}
+	}
+
+	//this function is used to maintain the heap, always re-position the number at index i to its correct place
+	private static void maxheap(int[] nums, int i) {
+		int left = 2*i;
+		int right = left+1;
+		int max = i;
+		if(left <= N && nums[left] > nums[i]){
+			max = left;
+		}
+		if(right <= N && nums[right] > nums[max]){
+			max = right;
+		}
+
+		if(max != i){
+			swap(nums, i, max);
+			maxheap(nums, max);
+		}
+	}
+
+	private static void heapify(int[] nums) {
+		N = nums.length-1;
+		for(int i = N/2; i >= 0; i--){
+			maxheap(nums, i);
+		}
+	}
+
+	private static void swap(int[] nums, int i, int j) {
+		int temp = nums[i];
+		nums[i] = nums[j];
+		nums[j] = temp;
+	}
+
 	public static void main(String...strings){
-		System.out.println("Hello World!");
+		int[] nums = new int[]{6,5,3,1,8,7,2,4};
+		//		int[] nums = new int[]{1,2,3,4,5,6};
+		//		int[] nums = new int[]{6,5,4,3,2,1};
+//		int[] nums = new int[]{488, 667, 634, 380, 944, 594, 783, 584, 550, 665, 721, 819, 285, 344, 503, 807, 491, 623, 845, 300};
+		print("BEFORE printing, nums are: ", nums);
+		sort(nums);
+		print("AFTER printing, nums are: ", nums);
+		System.out.println();
+	}
+
+	private static void print(String msg, int[] nums) {
+		System.out.println(msg);
+		for(int i : nums){
+			System.out.print(i + ", ");
+		}
+		System.out.println();
 	}
 }
diff --git a/src/sporadic/sorting/HeapSortAgain.java b/src/sporadic/sorting/HeapSortAgain.java
new file mode 100644
index 0000000..88c3c29
--- /dev/null
+++ b/src/sporadic/sorting/HeapSortAgain.java
@@ -0,0 +1,58 @@
+package sporadic.sorting;
+
+/**After completing understanding this algorithm, I implemented myself, so this class is called HeapSortAgain.*/
+public class HeapSortAgain {
+    private static int N;
+    public static void sort(int[] nums){
+        heapify(nums);
+        for(int i = N; i > 0; i--){//i doesn't need to be equal to zero, because we don't need to swap zero-indexed number with itself
+            swap(nums, i, 0);//we always swap the first element in the array which means it's at the root of the heap with the number at index i which is the largest index in the UN-sorted array
+            N -= 1;//don't remember to decrement N by 1, because we only need to worry about one number fewer each time
+            maxheap(nums, 0);//then we always update the heap for the number at index zero
+        }
+    }
+    private static void heapify(int[] nums) {
+        N = nums.length-1;
+        for(int i = N/2; i >= 0; i--){//here we need i to be equal to zero because we need to do maxheap() on its first element as well
+            maxheap(nums, i);
+        }
+    }
+    private static void maxheap(int[] nums, int i) {
+        int leftChildIndex = 2*i;
+        int rightChildIndex = leftChildIndex+1;
+        int max = i;
+        if(leftChildIndex <= N && nums[leftChildIndex] > nums[i]){
+            max = leftChildIndex;
+        }
+        if(rightChildIndex <= N && nums[rightChildIndex] > nums[max]){
+            max = rightChildIndex;
+        }
+        if(i != max){
+            swap(nums, i, max);
+            maxheap(nums, max);
+        }
+    }
+    private static void swap(int[] nums, int i, int j) {
+        int temp = nums[i];
+        nums[i] = nums[j];
+        nums[j] = temp;
+    }
+    public static void main(String...strings){
+        int[] nums = new int[]{6,5,3,1,8,7,2,4};
+        //		int[] nums = new int[]{1,2,3,4,5,6};
+        //		int[] nums = new int[]{6,5,4,3,2,1};
+//		int[] nums = new int[]{488, 667, 634, 380, 944, 594, 783, 584, 550, 665, 721, 819, 285, 344, 503, 807, 491, 623, 845, 300};
+        print("BEFORE printing, nums are: ", nums);
+        sort(nums);
+        print("AFTER printing, nums are: ", nums);
+        System.out.println();
+    }
+
+    private static void print(String msg, int[] nums) {
+        System.out.println(msg);
+        for(int i : nums){
+            System.out.print(i + ", ");
+        }
+        System.out.println();
+    }
+}

From 13d7b332c3d682d93f3124045ecf6288fc4b66b4 Mon Sep 17 00:00:00 2001
From: Steve Sun <stevesun@coupang.com>
Date: Thu, 29 Dec 2016 17:23:44 -0800
Subject: [PATCH 008/185] Find Word From Number

---
 .../FindWordFromNumber.java                   | 302 ++++++++++++++++++
 1 file changed, 302 insertions(+)
 create mode 100644 src/InterviewQuestions/FindWordFromNumber.java

diff --git a/src/InterviewQuestions/FindWordFromNumber.java b/src/InterviewQuestions/FindWordFromNumber.java
new file mode 100644
index 0000000..558468b
--- /dev/null
+++ b/src/InterviewQuestions/FindWordFromNumber.java
@@ -0,0 +1,302 @@
+package InterviewQuestions;
+
+/**With Cracking group on 11/23/2013, a very fruitful day.
+
+ *
+ *Problem statement (Dropbox interview question):
+ *Given a defined dictionary, test if a 7-digit number can represent any
+ *valid words from this dictionary.
+ *The digit to alphabet matching relationship is exactly the same as from the cellphone keyboard.
+ */
+
+/**The idea here is that:
+ *This 7-digit number can only be separated into the following three situations:
+ *a 3-letter word followed by a 4-letter word;
+ *a 4-letter word followed by a 3-letter word;
+ *a 7-letter word.
+ *Because we assume there's no word with only one letter or two letters in our dictionary.*/
+
+
+
+/**Then we construct another three HashMaps to store all 3-letter words, all 4-letter words and
+ * all 7-letter words in the dictionary respectively. */
+import java.util.ArrayList;
+import java.util.HashMap;
+
+public class FindWordFromNumber {
+
+/**The KEY thing to bare in mind is that in HashMap,
+ *you can only get values using key, NOT the other way around!*/
+
+        public static void main(String args[]){
+
+		/**We construct our first HashMap, ATTENTION: in this HashMap, the key is the alphabet
+		 *while the value is its corresponding digit, because we want to find the digit from
+		 *the alphabet.*/
+            HashMap<Character, Integer> charToNum = new HashMap();
+            charToNum.put('a', 2);
+            charToNum.put('b', 2);
+            charToNum.put('c', 2);
+            charToNum.put('d', 3);
+            charToNum.put('e', 3);
+            charToNum.put('f', 3);
+            charToNum.put('g', 4);
+            charToNum.put('h', 4);
+            charToNum.put('i', 4);
+            charToNum.put('j', 5);
+            charToNum.put('k', 5);
+            charToNum.put('l', 5);
+            charToNum.put('m', 6);
+            charToNum.put('n', 6);
+            charToNum.put('o', 6);
+            charToNum.put('p', 7);
+            charToNum.put('q', 7);
+            charToNum.put('r', 7);
+            charToNum.put('s', 7);
+            charToNum.put('t', 8);
+            charToNum.put('u', 8);
+            charToNum.put('v', 8);
+            charToNum.put('w', 9);
+            charToNum.put('x', 9);
+            charToNum.put('y', 9);
+            charToNum.put('z', 9);
+
+		/**I should use the above HashMap to automatically put the words in the dictionary into
+		 *their corresponding HashMaps and, inside their corresponding HashMaps to their corresponding
+		 *key.*/
+
+		/**So I commented the following manual assigning methods out.*/
+
+		/**HashMap<Integer, String> threeLetterWord = new HashMap();
+		threeLetterWord.put(567, "lop");
+		threeLetterWord.put(432, "ifc");
+		threeLetterWord.put(527, "lap");
+		threeLetterWord.put(827, "tap");
+		threeLetterWord.put(567, "lmp");
+		threeLetterWord.put(438, "get");
+
+		HashMap<Integer, String> fourLetterWord = new HashMap();
+		fourLetterWord.put(5678, "jmpu");
+		fourLetterWord.put(8432, "thea");
+		fourLetterWord.put(7843, "ruif");
+		fourLetterWord.put(8432, "vida");
+
+		HashMap<Integer, String> sevenLetterWord = new HashMap();
+		sevenLetterWord.put(5678432, "kostiea");
+		sevenLetterWord.put(5678432, "kmpugec");
+		 */
+
+//		Declare an array of type String to hold the whole dictionary.
+            String dict[] = {"lop", "ifc", "lap", "tap", "lmp", "get",
+                    "jmpu", "thea", "ruif", "vida", "kostiea", "kmpugec"};
+
+
+		/**Attention: the parameters inside the HashMap: one is Integer which represents digit,
+		 * the other is ArrayList<String> which is used to store all possible valid words that this
+		 * number can represent. Because one number can represent a couple different words.*/
+            HashMap<Integer, ArrayList<String>> threeLetterWord = new HashMap();
+            HashMap<Integer, ArrayList<String>> fourLetterWord = new HashMap();
+            HashMap<Integer, ArrayList<String>> sevenLetterWord = new HashMap();
+
+            for(int i = 0; i < dict.length; i++)
+            {
+                if(dict[i].length() == 3){
+                    String num = "";
+                    for(int j = 0; j < dict[i].length(); j++){
+                        String temp = String.valueOf(charToNum.get(dict[i].charAt(j)));
+                        num = num + temp;
+                    }
+                    int _3LetterWordNum = Integer.parseInt(num);
+				/**Here we need to test if this number has already had one valid word
+				 *put in the HashMap,
+				 *
+				 *if so, we need to get whole ArrayList elements out
+				 *first, then use ArrayList.add() method to append this word at the end of
+				 *the last word that this number represents, then put it in the HashMap;
+				 *
+				 *if not, this means this word is the first word that this number
+				 *represents in the dictionary, so we just put
+				 *it in the ArrayList, then put it in the HashMap. */
+                    if(threeLetterWord.containsKey(_3LetterWordNum))
+                    {	ArrayList<String> allString = new ArrayList<String>();
+                        allString = threeLetterWord.get(_3LetterWordNum);
+                        allString.add(dict[i]);
+                        threeLetterWord.put(_3LetterWordNum, allString);
+                    }
+                    else{
+                        ArrayList<String> allString = new ArrayList<String>();
+                        allString.add(dict[i]);
+                        threeLetterWord.put(_3LetterWordNum, allString);
+                    }
+                }
+                else if (dict[i].length() == 4){
+                    String num = "";
+                    for(int j = 0; j < dict[i].length(); j++){
+                        String temp = String.valueOf(charToNum.get(dict[i].charAt(j)));
+                        num = num + temp;
+                    }
+                    int _4LetterWordNum = Integer.parseInt(num);
+                    if(fourLetterWord.containsKey(_4LetterWordNum))
+                    {
+                        ArrayList<String> allString = new ArrayList<String>();
+                        allString = fourLetterWord.get(_4LetterWordNum);
+                        allString.add(dict[i]);
+                        fourLetterWord.put(_4LetterWordNum, allString);
+                    }
+                    else{
+                        ArrayList<String> allString = new ArrayList<String>();
+                        allString.add(dict[i]);
+                        fourLetterWord.put(_4LetterWordNum, allString);
+                    }
+                }
+                else if (dict[i].length() == 7){
+                    String num = "";
+                    for(int j = 0; j < dict[i].length(); j++){
+                        String temp = String.valueOf(charToNum.get(dict[i].charAt(j)));
+                        num = num + temp;
+                    }
+                    int _7LetterWordNum = Integer.parseInt(num);
+                    if(sevenLetterWord.containsKey(_7LetterWordNum))
+                    {	ArrayList<String> allString = new ArrayList<String>();
+                        allString = sevenLetterWord.get(_7LetterWordNum);
+                        allString.add(dict[i]);
+                        sevenLetterWord.put(_7LetterWordNum, allString);
+                    }
+                    else{
+                        ArrayList<String> allString = new ArrayList<String>();
+                        allString.add(dict[i]);
+                        sevenLetterWord.put(_7LetterWordNum, allString);
+                    }
+                }
+            }
+
+		/**Use HashMap.values() method to get all the VALUES inside this HashMap.*/
+//		System.out.println(threeLetterWord.values());
+//		System.out.println(fourLetterWord.values());
+//		System.out.println(sevenLetterWord.values());
+
+		/*Use HashMap.keySet() method to get all the KEYS inside this HashMap.*/
+//		System.out.println(threeLetterWord.keySet());
+//		System.out.println(fourLetterWord.keySet());
+//		System.out.println(sevenLetterWord.keySet());
+
+            String input = "1020";
+
+            if(input.length() <= 2){
+                System.out.println("Your number has less than 3 digits," +
+                        " cannot be used to represent any valid words" +
+                        " in our dictionary, please enter a seven-digit number");
+            }
+
+            else if(input.length() == 3)/*When the input string has 3 digits.*/
+            {
+                if(threeLetterWord.containsKey(Integer.parseInt(input)))
+                {
+                    ArrayList<String> temp3word = new ArrayList<String>();
+                    temp3word = threeLetterWord.get(Integer.parseInt(input));
+                    for(String i : temp3word)
+                        System.out.println(i);
+                }
+                else
+                    System.out.print("No valid word combinations for this 3-digit number" +
+                            ", please enter another number.");
+            }
+
+            else if(input.length() == 4)/*When the input string has 4 digits.*/
+            {
+                if(fourLetterWord.containsKey(Integer.parseInt(input)))
+                {
+                    ArrayList<String> temp4word = new ArrayList<String>();
+                    temp4word = fourLetterWord.get(Integer.parseInt(input));
+                    for(String i : temp4word)
+                        System.out.println(i);
+                }
+                else
+                    System.out.println("No valid word combinations for this 4-digit number" +
+                            ", please enter another number.");
+            }
+            else if(input.length() == 5)
+                System.out.println("No valid word combinations for a 5-digit number," +
+                        " please enter another number.");
+            else if(input.length() == 6)
+                System.out.println("No valid word combinations for a 6-digit number," +
+                        " please enter another number.");
+
+            else if(input.length() == 7)/**When the input string has 7 digits, there are three possible
+		situations for this, as follows:*/
+            {
+                if(sevenLetterWord.containsKey(Integer.parseInt(input)))
+                //the following is the situation that there's only seven-letter word
+                { ArrayList<String> temp7word = new ArrayList<String>();
+                    temp7word = sevenLetterWord.get(Integer.parseInt(input));
+                    System.out.println("This 7-digit number as a whole macthes valid words in the dictonary," +
+                            " they are: ");
+                    for(String i : temp7word)
+                    {
+                        System.out.println(i);
+                    }
+                }
+
+                if(threeLetterWord.containsKey(Integer.parseInt(input.substring(0, 3)))){
+                    {
+                        //the following is the situation that there's three-letter word followed by a four-letter word
+                        ArrayList<String> temp3word = new ArrayList<String>();
+                        ArrayList<String> temp4word = new ArrayList<String>();
+                        String s1 = input.substring(0, 3);/*Pay ATTENTION to the substring method:
+					it can take char at index 0 but cannot take char at index 3, so in order to get
+					the first three chars of the String, we need to use .substring(0, 3) instead of
+					.substring(0, 2).*/
+                        //System.out.println(s1);
+                        String s2 = input.substring(3, 7);
+                        //System.out.println(s2);
+                        if(fourLetterWord.containsKey(Integer.parseInt(s2)))
+                        { System.out.println("This number can represent one 3-letter word followed by" +
+                                " a 4-letter word, they are:");
+                            temp3word = threeLetterWord.get(Integer.parseInt(s1));
+                            temp4word = fourLetterWord.get(Integer.parseInt(s2));
+                            for(String i : temp3word)
+                                for(String j : temp4word){
+                                    System.out.println(i + " + " + j);
+                                }
+                        }
+                        else
+                            System.out.println("There's valid word for the first 3 digits but no valid words" +
+                                    " for the last 4-digit number.");
+                    }
+                }
+
+                //the following is the situation that there's four-letter word followed by a three-letter word
+                if(fourLetterWord.containsKey(Integer.parseInt(input.substring(0, 4))))
+                {
+                    {
+                        String s1 = input.substring(0, 4);
+                        //System.out.println(s1);
+                        ArrayList<String> temp4word = new ArrayList<String>();
+                        ArrayList<String> temp3word = new ArrayList<String>();
+
+                        String s2 = input.substring(4, 7);
+                        //System.out.println(s2);
+                        if(threeLetterWord.containsKey(Integer.parseInt(s2)))
+                        {	System.out.println("This number can represent one 4-letter word followed by" +
+                                " a 3-letter word, they are:");
+                            temp4word = fourLetterWord.get(Integer.parseInt(s1));
+                            temp3word = threeLetterWord.get(Integer.parseInt(s2));
+                            for(String i : temp4word)
+                                for(String j : temp3word){
+                                    System.out.print(i + " + " + j);
+                                }
+                        }
+                        else
+                            System.out.println("There is valid word combinations for the first 4-digit of" +
+                                    "this number, but there's no valid word for the last 3-digit.");
+                    }
+                }
+
+                else
+                    System.out.println("This 7-digit number doesn't not match any 3-letter word, 4-letter word or" +
+                            " 7-letter word in the dictionary.");
+            }
+            else
+                System.out.println("Too long input, please enter a valid number.");
+        }
+}

From 33591fd60b19d3a7652f3fbe29bf8647b174a9d5 Mon Sep 17 00:00:00 2001
From: Fishercoder <fishercoder@gmail.com>
Date: Sun, 15 Jan 2017 12:02:50 -0800
Subject: [PATCH 009/185] test

---
 squashCommitsTest.txt | 1 +
 1 file changed, 1 insertion(+)
 create mode 100644 squashCommitsTest.txt

diff --git a/squashCommitsTest.txt b/squashCommitsTest.txt
new file mode 100644
index 0000000..2cbd40e
--- /dev/null
+++ b/squashCommitsTest.txt
@@ -0,0 +1 @@
+This is a series of test commits to really understand how to squash commits using Git.

From 3e6df21014768044add6ec2e14bf87afbbe1b22f Mon Sep 17 00:00:00 2001
From: Fishercoder <fishercoder@gmail.com>
Date: Sun, 15 Jan 2017 12:04:10 -0800
Subject: [PATCH 010/185] test

---
 squashCommitsTest.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/squashCommitsTest.txt b/squashCommitsTest.txt
index 2cbd40e..67d4bbf 100644
--- a/squashCommitsTest.txt
+++ b/squashCommitsTest.txt
@@ -1 +1,2 @@
 This is a series of test commits to really understand how to squash commits using Git.
+2nd commit.

From 80c4ddd53e3c8b70f0641d6c08b532b4bfdba985 Mon Sep 17 00:00:00 2001
From: Fishercoder <fishercoder@gmail.com>
Date: Sun, 15 Jan 2017 12:04:41 -0800
Subject: [PATCH 011/185] test

---
 squashCommitsTest.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/squashCommitsTest.txt b/squashCommitsTest.txt
index 67d4bbf..a0e104a 100644
--- a/squashCommitsTest.txt
+++ b/squashCommitsTest.txt
@@ -1,2 +1,3 @@
 This is a series of test commits to really understand how to squash commits using Git.
 2nd commit.
+3rd commit.

From 17f414c36c030058202b13d5384c15a21f16eab7 Mon Sep 17 00:00:00 2001
From: Steve Sun <stevesun@coupang.com>
Date: Thu, 29 Dec 2016 17:23:44 -0800
Subject: [PATCH 012/185] Find Word From Number

---
 .../FindWordFromNumber.java                   | 302 ++++++++++++++++++
 1 file changed, 302 insertions(+)
 create mode 100644 src/InterviewQuestions/FindWordFromNumber.java

diff --git a/src/InterviewQuestions/FindWordFromNumber.java b/src/InterviewQuestions/FindWordFromNumber.java
new file mode 100644
index 0000000..558468b
--- /dev/null
+++ b/src/InterviewQuestions/FindWordFromNumber.java
@@ -0,0 +1,302 @@
+package InterviewQuestions;
+
+/**With Cracking group on 11/23/2013, a very fruitful day.
+
+ *
+ *Problem statement (Dropbox interview question):
+ *Given a defined dictionary, test if a 7-digit number can represent any
+ *valid words from this dictionary.
+ *The digit to alphabet matching relationship is exactly the same as from the cellphone keyboard.
+ */
+
+/**The idea here is that:
+ *This 7-digit number can only be separated into the following three situations:
+ *a 3-letter word followed by a 4-letter word;
+ *a 4-letter word followed by a 3-letter word;
+ *a 7-letter word.
+ *Because we assume there's no word with only one letter or two letters in our dictionary.*/
+
+
+
+/**Then we construct another three HashMaps to store all 3-letter words, all 4-letter words and
+ * all 7-letter words in the dictionary respectively. */
+import java.util.ArrayList;
+import java.util.HashMap;
+
+public class FindWordFromNumber {
+
+/**The KEY thing to bare in mind is that in HashMap,
+ *you can only get values using key, NOT the other way around!*/
+
+        public static void main(String args[]){
+
+		/**We construct our first HashMap, ATTENTION: in this HashMap, the key is the alphabet
+		 *while the value is its corresponding digit, because we want to find the digit from
+		 *the alphabet.*/
+            HashMap<Character, Integer> charToNum = new HashMap();
+            charToNum.put('a', 2);
+            charToNum.put('b', 2);
+            charToNum.put('c', 2);
+            charToNum.put('d', 3);
+            charToNum.put('e', 3);
+            charToNum.put('f', 3);
+            charToNum.put('g', 4);
+            charToNum.put('h', 4);
+            charToNum.put('i', 4);
+            charToNum.put('j', 5);
+            charToNum.put('k', 5);
+            charToNum.put('l', 5);
+            charToNum.put('m', 6);
+            charToNum.put('n', 6);
+            charToNum.put('o', 6);
+            charToNum.put('p', 7);
+            charToNum.put('q', 7);
+            charToNum.put('r', 7);
+            charToNum.put('s', 7);
+            charToNum.put('t', 8);
+            charToNum.put('u', 8);
+            charToNum.put('v', 8);
+            charToNum.put('w', 9);
+            charToNum.put('x', 9);
+            charToNum.put('y', 9);
+            charToNum.put('z', 9);
+
+		/**I should use the above HashMap to automatically put the words in the dictionary into
+		 *their corresponding HashMaps and, inside their corresponding HashMaps to their corresponding
+		 *key.*/
+
+		/**So I commented the following manual assigning methods out.*/
+
+		/**HashMap<Integer, String> threeLetterWord = new HashMap();
+		threeLetterWord.put(567, "lop");
+		threeLetterWord.put(432, "ifc");
+		threeLetterWord.put(527, "lap");
+		threeLetterWord.put(827, "tap");
+		threeLetterWord.put(567, "lmp");
+		threeLetterWord.put(438, "get");
+
+		HashMap<Integer, String> fourLetterWord = new HashMap();
+		fourLetterWord.put(5678, "jmpu");
+		fourLetterWord.put(8432, "thea");
+		fourLetterWord.put(7843, "ruif");
+		fourLetterWord.put(8432, "vida");
+
+		HashMap<Integer, String> sevenLetterWord = new HashMap();
+		sevenLetterWord.put(5678432, "kostiea");
+		sevenLetterWord.put(5678432, "kmpugec");
+		 */
+
+//		Declare an array of type String to hold the whole dictionary.
+            String dict[] = {"lop", "ifc", "lap", "tap", "lmp", "get",
+                    "jmpu", "thea", "ruif", "vida", "kostiea", "kmpugec"};
+
+
+		/**Attention: the parameters inside the HashMap: one is Integer which represents digit,
+		 * the other is ArrayList<String> which is used to store all possible valid words that this
+		 * number can represent. Because one number can represent a couple different words.*/
+            HashMap<Integer, ArrayList<String>> threeLetterWord = new HashMap();
+            HashMap<Integer, ArrayList<String>> fourLetterWord = new HashMap();
+            HashMap<Integer, ArrayList<String>> sevenLetterWord = new HashMap();
+
+            for(int i = 0; i < dict.length; i++)
+            {
+                if(dict[i].length() == 3){
+                    String num = "";
+                    for(int j = 0; j < dict[i].length(); j++){
+                        String temp = String.valueOf(charToNum.get(dict[i].charAt(j)));
+                        num = num + temp;
+                    }
+                    int _3LetterWordNum = Integer.parseInt(num);
+				/**Here we need to test if this number has already had one valid word
+				 *put in the HashMap,
+				 *
+				 *if so, we need to get whole ArrayList elements out
+				 *first, then use ArrayList.add() method to append this word at the end of
+				 *the last word that this number represents, then put it in the HashMap;
+				 *
+				 *if not, this means this word is the first word that this number
+				 *represents in the dictionary, so we just put
+				 *it in the ArrayList, then put it in the HashMap. */
+                    if(threeLetterWord.containsKey(_3LetterWordNum))
+                    {	ArrayList<String> allString = new ArrayList<String>();
+                        allString = threeLetterWord.get(_3LetterWordNum);
+                        allString.add(dict[i]);
+                        threeLetterWord.put(_3LetterWordNum, allString);
+                    }
+                    else{
+                        ArrayList<String> allString = new ArrayList<String>();
+                        allString.add(dict[i]);
+                        threeLetterWord.put(_3LetterWordNum, allString);
+                    }
+                }
+                else if (dict[i].length() == 4){
+                    String num = "";
+                    for(int j = 0; j < dict[i].length(); j++){
+                        String temp = String.valueOf(charToNum.get(dict[i].charAt(j)));
+                        num = num + temp;
+                    }
+                    int _4LetterWordNum = Integer.parseInt(num);
+                    if(fourLetterWord.containsKey(_4LetterWordNum))
+                    {
+                        ArrayList<String> allString = new ArrayList<String>();
+                        allString = fourLetterWord.get(_4LetterWordNum);
+                        allString.add(dict[i]);
+                        fourLetterWord.put(_4LetterWordNum, allString);
+                    }
+                    else{
+                        ArrayList<String> allString = new ArrayList<String>();
+                        allString.add(dict[i]);
+                        fourLetterWord.put(_4LetterWordNum, allString);
+                    }
+                }
+                else if (dict[i].length() == 7){
+                    String num = "";
+                    for(int j = 0; j < dict[i].length(); j++){
+                        String temp = String.valueOf(charToNum.get(dict[i].charAt(j)));
+                        num = num + temp;
+                    }
+                    int _7LetterWordNum = Integer.parseInt(num);
+                    if(sevenLetterWord.containsKey(_7LetterWordNum))
+                    {	ArrayList<String> allString = new ArrayList<String>();
+                        allString = sevenLetterWord.get(_7LetterWordNum);
+                        allString.add(dict[i]);
+                        sevenLetterWord.put(_7LetterWordNum, allString);
+                    }
+                    else{
+                        ArrayList<String> allString = new ArrayList<String>();
+                        allString.add(dict[i]);
+                        sevenLetterWord.put(_7LetterWordNum, allString);
+                    }
+                }
+            }
+
+		/**Use HashMap.values() method to get all the VALUES inside this HashMap.*/
+//		System.out.println(threeLetterWord.values());
+//		System.out.println(fourLetterWord.values());
+//		System.out.println(sevenLetterWord.values());
+
+		/*Use HashMap.keySet() method to get all the KEYS inside this HashMap.*/
+//		System.out.println(threeLetterWord.keySet());
+//		System.out.println(fourLetterWord.keySet());
+//		System.out.println(sevenLetterWord.keySet());
+
+            String input = "1020";
+
+            if(input.length() <= 2){
+                System.out.println("Your number has less than 3 digits," +
+                        " cannot be used to represent any valid words" +
+                        " in our dictionary, please enter a seven-digit number");
+            }
+
+            else if(input.length() == 3)/*When the input string has 3 digits.*/
+            {
+                if(threeLetterWord.containsKey(Integer.parseInt(input)))
+                {
+                    ArrayList<String> temp3word = new ArrayList<String>();
+                    temp3word = threeLetterWord.get(Integer.parseInt(input));
+                    for(String i : temp3word)
+                        System.out.println(i);
+                }
+                else
+                    System.out.print("No valid word combinations for this 3-digit number" +
+                            ", please enter another number.");
+            }
+
+            else if(input.length() == 4)/*When the input string has 4 digits.*/
+            {
+                if(fourLetterWord.containsKey(Integer.parseInt(input)))
+                {
+                    ArrayList<String> temp4word = new ArrayList<String>();
+                    temp4word = fourLetterWord.get(Integer.parseInt(input));
+                    for(String i : temp4word)
+                        System.out.println(i);
+                }
+                else
+                    System.out.println("No valid word combinations for this 4-digit number" +
+                            ", please enter another number.");
+            }
+            else if(input.length() == 5)
+                System.out.println("No valid word combinations for a 5-digit number," +
+                        " please enter another number.");
+            else if(input.length() == 6)
+                System.out.println("No valid word combinations for a 6-digit number," +
+                        " please enter another number.");
+
+            else if(input.length() == 7)/**When the input string has 7 digits, there are three possible
+		situations for this, as follows:*/
+            {
+                if(sevenLetterWord.containsKey(Integer.parseInt(input)))
+                //the following is the situation that there's only seven-letter word
+                { ArrayList<String> temp7word = new ArrayList<String>();
+                    temp7word = sevenLetterWord.get(Integer.parseInt(input));
+                    System.out.println("This 7-digit number as a whole macthes valid words in the dictonary," +
+                            " they are: ");
+                    for(String i : temp7word)
+                    {
+                        System.out.println(i);
+                    }
+                }
+
+                if(threeLetterWord.containsKey(Integer.parseInt(input.substring(0, 3)))){
+                    {
+                        //the following is the situation that there's three-letter word followed by a four-letter word
+                        ArrayList<String> temp3word = new ArrayList<String>();
+                        ArrayList<String> temp4word = new ArrayList<String>();
+                        String s1 = input.substring(0, 3);/*Pay ATTENTION to the substring method:
+					it can take char at index 0 but cannot take char at index 3, so in order to get
+					the first three chars of the String, we need to use .substring(0, 3) instead of
+					.substring(0, 2).*/
+                        //System.out.println(s1);
+                        String s2 = input.substring(3, 7);
+                        //System.out.println(s2);
+                        if(fourLetterWord.containsKey(Integer.parseInt(s2)))
+                        { System.out.println("This number can represent one 3-letter word followed by" +
+                                " a 4-letter word, they are:");
+                            temp3word = threeLetterWord.get(Integer.parseInt(s1));
+                            temp4word = fourLetterWord.get(Integer.parseInt(s2));
+                            for(String i : temp3word)
+                                for(String j : temp4word){
+                                    System.out.println(i + " + " + j);
+                                }
+                        }
+                        else
+                            System.out.println("There's valid word for the first 3 digits but no valid words" +
+                                    " for the last 4-digit number.");
+                    }
+                }
+
+                //the following is the situation that there's four-letter word followed by a three-letter word
+                if(fourLetterWord.containsKey(Integer.parseInt(input.substring(0, 4))))
+                {
+                    {
+                        String s1 = input.substring(0, 4);
+                        //System.out.println(s1);
+                        ArrayList<String> temp4word = new ArrayList<String>();
+                        ArrayList<String> temp3word = new ArrayList<String>();
+
+                        String s2 = input.substring(4, 7);
+                        //System.out.println(s2);
+                        if(threeLetterWord.containsKey(Integer.parseInt(s2)))
+                        {	System.out.println("This number can represent one 4-letter word followed by" +
+                                " a 3-letter word, they are:");
+                            temp4word = fourLetterWord.get(Integer.parseInt(s1));
+                            temp3word = threeLetterWord.get(Integer.parseInt(s2));
+                            for(String i : temp4word)
+                                for(String j : temp3word){
+                                    System.out.print(i + " + " + j);
+                                }
+                        }
+                        else
+                            System.out.println("There is valid word combinations for the first 4-digit of" +
+                                    "this number, but there's no valid word for the last 3-digit.");
+                    }
+                }
+
+                else
+                    System.out.println("This 7-digit number doesn't not match any 3-letter word, 4-letter word or" +
+                            " 7-letter word in the dictionary.");
+            }
+            else
+                System.out.println("Too long input, please enter a valid number.");
+        }
+}

From e554e45f809b4bfa74682207f599c9c2368a7b1e Mon Sep 17 00:00:00 2001
From: Fishercoder <fishercoder@gmail.com>
Date: Sun, 15 Jan 2017 12:02:50 -0800
Subject: [PATCH 013/185] test

test

test

This is a squashed commit.
---
 squashCommitsTest.txt | 3 +++
 1 file changed, 3 insertions(+)
 create mode 100644 squashCommitsTest.txt

diff --git a/squashCommitsTest.txt b/squashCommitsTest.txt
new file mode 100644
index 0000000..a0e104a
--- /dev/null
+++ b/squashCommitsTest.txt
@@ -0,0 +1,3 @@
+This is a series of test commits to really understand how to squash commits using Git.
+2nd commit.
+3rd commit.

From 396a45d5e0bd4520ea5d99d56408f6db8494932b Mon Sep 17 00:00:00 2001
From: Fishercoder <fishercoder@gmail.com>
Date: Sun, 15 Jan 2017 12:20:20 -0800
Subject: [PATCH 014/185] 4th

---
 squashCommitsTest.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/squashCommitsTest.txt b/squashCommitsTest.txt
index a0e104a..b5348f4 100644
--- a/squashCommitsTest.txt
+++ b/squashCommitsTest.txt
@@ -1,3 +1,4 @@
 This is a series of test commits to really understand how to squash commits using Git.
 2nd commit.
 3rd commit.
+4th commit.

From 955149edbf8a9b99224ac8bb66c7c1c8a7caf1e8 Mon Sep 17 00:00:00 2001
From: Fishercoder <fishercoder@gmail.com>
Date: Sun, 15 Jan 2017 12:20:44 -0800
Subject: [PATCH 015/185] 4th

---
 squashCommitsTest.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/squashCommitsTest.txt b/squashCommitsTest.txt
index b5348f4..6b6f23a 100644
--- a/squashCommitsTest.txt
+++ b/squashCommitsTest.txt
@@ -2,3 +2,4 @@ This is a series of test commits to really understand how to squash commits usin
 2nd commit.
 3rd commit.
 4th commit.
+5th commit.

From 83f88e0f948cda90319e2b10366043a8a2a3275c Mon Sep 17 00:00:00 2001
From: Fishercoder <fishercoder@gmail.com>
Date: Sun, 15 Jan 2017 12:21:06 -0800
Subject: [PATCH 016/185] 6th commit

---
 squashCommitsTest.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/squashCommitsTest.txt b/squashCommitsTest.txt
index 6b6f23a..2bab9f6 100644
--- a/squashCommitsTest.txt
+++ b/squashCommitsTest.txt
@@ -3,3 +3,4 @@ This is a series of test commits to really understand how to squash commits usin
 3rd commit.
 4th commit.
 5th commit.
+6th commit.

From f534e41fdf617c02fb0b782ae9814b9e7505f991 Mon Sep 17 00:00:00 2001
From: Fishercoder <fishercoder@gmail.com>
Date: Sun, 15 Jan 2017 12:20:20 -0800
Subject: [PATCH 017/185] 4th

4th

6th commit

Squashed commit
---
 squashCommitsTest.txt | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/squashCommitsTest.txt b/squashCommitsTest.txt
index a0e104a..2bab9f6 100644
--- a/squashCommitsTest.txt
+++ b/squashCommitsTest.txt
@@ -1,3 +1,6 @@
 This is a series of test commits to really understand how to squash commits using Git.
 2nd commit.
 3rd commit.
+4th commit.
+5th commit.
+6th commit.

From 34e9e61f3ab8aa82050b2da867cd83993c0281c1 Mon Sep 17 00:00:00 2001
From: Steve Sun <stevesun@coupang.com>
Date: Sun, 22 Jan 2017 16:26:36 -0800
Subject: [PATCH 018/185] [JAVA-9999] remove trash

---
 squashCommitsTest.txt | 6 ------
 1 file changed, 6 deletions(-)
 delete mode 100644 squashCommitsTest.txt

diff --git a/squashCommitsTest.txt b/squashCommitsTest.txt
deleted file mode 100644
index 2bab9f6..0000000
--- a/squashCommitsTest.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-This is a series of test commits to really understand how to squash commits using Git.
-2nd commit.
-3rd commit.
-4th commit.
-5th commit.
-6th commit.

From cce4f11bed923ffd2cd693f1af853a76793f4150 Mon Sep 17 00:00:00 2001
From: Steve Sun <stevesun@coupang.com>
Date: Sun, 22 Jan 2017 16:39:09 -0800
Subject: [PATCH 019/185] [JAVA]-0000 convert into a Maven project

---
 pom.xml                                       | 118 ++++++++++++++++++
 .../InterviewQuestions}/BinarySearch.java     |   0
 .../java/InterviewQuestions}/BuildOrder.java  |   0
 .../ColorCombinations.java                    |   0
 .../ConcatenatedWords.java                    |   0
 .../ConcatenatedWordsII.java                  |   0
 .../FindLongestSuffixInTwoLists.java          |   0
 .../FindWordFromNumber.java                   |   0
 .../LongestConsecutivePathInAMatrix.java      |   0
 ...umSizeSubarraySumEqualsOrSmallerThanK.java |   0
 .../java/InterviewQuestions}/MinFloors.java   |   0
 .../SetValueInDependencyGraph.java            |   0
 .../CookBehavior.java                         |   0
 .../CookNoodlesBehavior.java                  |   0
 .../CookRiceFlour.java                        |   0
 .../LoveBehavior.java                         |   0
 .../LoveHusbandBehavior.java                  |   0
 .../chapter_1_strategy_pattern/ModelWife.java |   0
 .../chapter_1_strategy_pattern/RealWife.java  |   0
 .../StrategtyPatternTestDrive.java            |   0
 .../chapter_1_strategy_pattern/Wife.java      |   0
 .../CoreFamily.java                           |   0
 .../CoreFamilyImpl.java                       |   0
 .../ObserverPatternTestDrive.java             |   0
 .../chapter_2_observer_pattern/Relative.java  |   0
 .../RelativeImpl.java                         |   0
 .../chapter_3_decorator_pattern/Beverage.java |   0
 .../CondimentDecorator.java                   |   0
 .../DecoratorPatternTestDrive.java            |   0
 .../chapter_3_decorator_pattern/Espresso.java |   0
 .../HouseBlend.java                           |   0
 .../chapter_3_decorator_pattern/Mocha.java    |   0
 .../chapter_3_decorator_pattern/Soy.java      |   0
 .../chapter_3_decorator_pattern/Whip.java     |   0
 .../factory_pattern/Circle.java               |   0
 .../factory_pattern/MainApp.java              |   0
 .../factory_pattern/Rectangle.java            |   0
 .../designPatterns/factory_pattern/Shape.java |   0
 .../factory_pattern/ShapeFactory.java         |   0
 .../factory_pattern/Square.java               |   0
 .../visitor_pattern/Computer.java             |   0
 .../visitor_pattern/ComputerPart.java         |   0
 .../ComputerPartDisplayVisitor.java           |   0
 .../visitor_pattern/ComputerPartVisitor.java  |   0
 .../visitor_pattern/Keyboard.java             |   0
 .../visitor_pattern/Monitor.java              |   0
 .../designPatterns/visitor_pattern/Mouse.java |   0
 .../visitor_pattern/VisitorPatternDemo.java   |   0
 .../DeseriliazeDemo.java                      |   0
 .../Employee.java                             |   0
 .../MainApp.java                              |   0
 .../SerializeDemo.java                        |   0
 .../constructorChaining/Animal.java           |   0
 .../constructorChaining/Creature.java         |   0
 .../constructorChaining/Dog.java              |   0
 .../constructorChaining/MainApp.java          |   0
 .../constructorChaining/Pet.java              |   0
 .../serializationIsFun/GospelBook.java        |   0
 .../serializationIsFun/GospelSaverTest.java   |   0
 .../sporadic/IO_example/JavaFileExample.java  |   0
 .../sporadic/IO_example/JavaIOExample.java    |   0
 .../sporadic/ProgramToFindMachineInfo.java    |   0
 src/{ => main/java}/sporadic/SendEmail.java   |   0
 .../java}/sporadic/UnderstandClass.java       |   0
 .../sporadic/UnderstandingJavaReference.java  |   0
 .../AnotherSimpleTestCase.java                |   0
 .../Main.java                                 |   0
 .../MyTestRunner.java                         |   0
 .../MyTestState.java                          |   0
 .../SimpleTestCase.java                       |   0
 .../SteveSunFirstCustomAnnotation.java        |   0
 .../SteveSunException.java                    |   0
 .../UnderstandExceptionTryCatch.java          |   0
 .../async/method/AsyncClient.java             |   0
 .../async/method/AsyncClientImpl.java         |   0
 .../async/method/MainApp.java                 |   0
 .../async/method/SyncClient.java              |   0
 .../async/method/SyncClientImpl.java          |   0
 .../async/method/Task.java                    |   0
 .../future/MainApp.java                       |   0
 .../future/MyCallable.java                    |   0
 .../sporadic/java_generics/GenericClass.java  |   0
 .../java}/sporadic/java_generics/MainApp.java |   0
 .../java_generics/NonGenericClass.java        |   0
 .../sporadic/java_generics/ParentClass.java   |   0
 .../sporadic/jsonExample/JsonDemoClass.java   |   0
 .../jsonExample/JsonIgnoreAnnotationDemo.java |   0
 .../method_invoke_and_reflect/Deet.java       |   0
 .../ProducerConsumerInJava.java               |   0
 .../sporadic/semaphore/ConnectionLimiter.java |   0
 .../socket_programming/GreetingClient.java    |   0
 .../socket_programming/GreetingServer.java    |   0
 .../java}/sporadic/sorting/HeapSort.java      |   0
 .../java}/sporadic/sorting/HeapSortAgain.java |   0
 .../java}/sporadic/sorting/InsertionSort.java |   0
 .../java}/sporadic/sorting/MergeSort.java     |   0
 .../java}/sporadic/sorting/QuickSort.java     |   0
 .../sporadic/thread/HusbandAndWifeJob.java    |   0
 .../java}/sporadic/thread/ThreadIsCool.java   |   0
 .../sporadic/thread/ThreadLocalExample.java   |   0
 .../withSynchronization/TestThread.java       |   0
 .../withoutSynchronization/TestThread.java    |   0
 .../json-spring-configuration.xml             |   0
 .../serialization-spring-configuration.xml    |   0
 104 files changed, 118 insertions(+)
 create mode 100644 pom.xml
 rename src/{interviewQuestions => main/java/InterviewQuestions}/BinarySearch.java (100%)
 rename src/{interviewQuestions => main/java/InterviewQuestions}/BuildOrder.java (100%)
 rename src/{interviewQuestions => main/java/InterviewQuestions}/ColorCombinations.java (100%)
 rename src/{interviewQuestions => main/java/InterviewQuestions}/ConcatenatedWords.java (100%)
 rename src/{interviewQuestions => main/java/InterviewQuestions}/ConcatenatedWordsII.java (100%)
 rename src/{interviewQuestions => main/java/InterviewQuestions}/FindLongestSuffixInTwoLists.java (100%)
 rename src/{ => main/java}/InterviewQuestions/FindWordFromNumber.java (100%)
 rename src/{interviewQuestions => main/java/InterviewQuestions}/LongestConsecutivePathInAMatrix.java (100%)
 rename src/{interviewQuestions => main/java/InterviewQuestions}/MaximumSizeSubarraySumEqualsOrSmallerThanK.java (100%)
 rename src/{interviewQuestions => main/java/InterviewQuestions}/MinFloors.java (100%)
 rename src/{interviewQuestions => main/java/InterviewQuestions}/SetValueInDependencyGraph.java (100%)
 rename src/{ => main/java}/designPatterns/chapter_1_strategy_pattern/CookBehavior.java (100%)
 rename src/{ => main/java}/designPatterns/chapter_1_strategy_pattern/CookNoodlesBehavior.java (100%)
 rename src/{ => main/java}/designPatterns/chapter_1_strategy_pattern/CookRiceFlour.java (100%)
 rename src/{ => main/java}/designPatterns/chapter_1_strategy_pattern/LoveBehavior.java (100%)
 rename src/{ => main/java}/designPatterns/chapter_1_strategy_pattern/LoveHusbandBehavior.java (100%)
 rename src/{ => main/java}/designPatterns/chapter_1_strategy_pattern/ModelWife.java (100%)
 rename src/{ => main/java}/designPatterns/chapter_1_strategy_pattern/RealWife.java (100%)
 rename src/{ => main/java}/designPatterns/chapter_1_strategy_pattern/StrategtyPatternTestDrive.java (100%)
 rename src/{ => main/java}/designPatterns/chapter_1_strategy_pattern/Wife.java (100%)
 rename src/{ => main/java}/designPatterns/chapter_2_observer_pattern/CoreFamily.java (100%)
 rename src/{ => main/java}/designPatterns/chapter_2_observer_pattern/CoreFamilyImpl.java (100%)
 rename src/{ => main/java}/designPatterns/chapter_2_observer_pattern/ObserverPatternTestDrive.java (100%)
 rename src/{ => main/java}/designPatterns/chapter_2_observer_pattern/Relative.java (100%)
 rename src/{ => main/java}/designPatterns/chapter_2_observer_pattern/RelativeImpl.java (100%)
 rename src/{ => main/java}/designPatterns/chapter_3_decorator_pattern/Beverage.java (100%)
 rename src/{ => main/java}/designPatterns/chapter_3_decorator_pattern/CondimentDecorator.java (100%)
 rename src/{ => main/java}/designPatterns/chapter_3_decorator_pattern/DecoratorPatternTestDrive.java (100%)
 rename src/{ => main/java}/designPatterns/chapter_3_decorator_pattern/Espresso.java (100%)
 rename src/{ => main/java}/designPatterns/chapter_3_decorator_pattern/HouseBlend.java (100%)
 rename src/{ => main/java}/designPatterns/chapter_3_decorator_pattern/Mocha.java (100%)
 rename src/{ => main/java}/designPatterns/chapter_3_decorator_pattern/Soy.java (100%)
 rename src/{ => main/java}/designPatterns/chapter_3_decorator_pattern/Whip.java (100%)
 rename src/{ => main/java}/designPatterns/factory_pattern/Circle.java (100%)
 rename src/{ => main/java}/designPatterns/factory_pattern/MainApp.java (100%)
 rename src/{ => main/java}/designPatterns/factory_pattern/Rectangle.java (100%)
 rename src/{ => main/java}/designPatterns/factory_pattern/Shape.java (100%)
 rename src/{ => main/java}/designPatterns/factory_pattern/ShapeFactory.java (100%)
 rename src/{ => main/java}/designPatterns/factory_pattern/Square.java (100%)
 rename src/{ => main/java}/designPatterns/visitor_pattern/Computer.java (100%)
 rename src/{ => main/java}/designPatterns/visitor_pattern/ComputerPart.java (100%)
 rename src/{ => main/java}/designPatterns/visitor_pattern/ComputerPartDisplayVisitor.java (100%)
 rename src/{ => main/java}/designPatterns/visitor_pattern/ComputerPartVisitor.java (100%)
 rename src/{ => main/java}/designPatterns/visitor_pattern/Keyboard.java (100%)
 rename src/{ => main/java}/designPatterns/visitor_pattern/Monitor.java (100%)
 rename src/{ => main/java}/designPatterns/visitor_pattern/Mouse.java (100%)
 rename src/{ => main/java}/designPatterns/visitor_pattern/VisitorPatternDemo.java (100%)
 rename src/{ => main/java}/learnHeadFirstJava/another_serialization_example/DeseriliazeDemo.java (100%)
 rename src/{ => main/java}/learnHeadFirstJava/another_serialization_example/Employee.java (100%)
 rename src/{ => main/java}/learnHeadFirstJava/another_serialization_example/MainApp.java (100%)
 rename src/{ => main/java}/learnHeadFirstJava/another_serialization_example/SerializeDemo.java (100%)
 rename src/{ => main/java}/learnHeadFirstJava/constructorChaining/Animal.java (100%)
 rename src/{ => main/java}/learnHeadFirstJava/constructorChaining/Creature.java (100%)
 rename src/{ => main/java}/learnHeadFirstJava/constructorChaining/Dog.java (100%)
 rename src/{ => main/java}/learnHeadFirstJava/constructorChaining/MainApp.java (100%)
 rename src/{ => main/java}/learnHeadFirstJava/constructorChaining/Pet.java (100%)
 rename src/{ => main/java}/learnHeadFirstJava/serializationIsFun/GospelBook.java (100%)
 rename src/{ => main/java}/learnHeadFirstJava/serializationIsFun/GospelSaverTest.java (100%)
 rename src/{ => main/java}/sporadic/IO_example/JavaFileExample.java (100%)
 rename src/{ => main/java}/sporadic/IO_example/JavaIOExample.java (100%)
 rename src/{ => main/java}/sporadic/ProgramToFindMachineInfo.java (100%)
 rename src/{ => main/java}/sporadic/SendEmail.java (100%)
 rename src/{ => main/java}/sporadic/UnderstandClass.java (100%)
 rename src/{ => main/java}/sporadic/UnderstandingJavaReference.java (100%)
 rename src/{ => main/java}/sporadic/customize_annotations_generics_wildcards_examples/AnotherSimpleTestCase.java (100%)
 rename src/{ => main/java}/sporadic/customize_annotations_generics_wildcards_examples/Main.java (100%)
 rename src/{ => main/java}/sporadic/customize_annotations_generics_wildcards_examples/MyTestRunner.java (100%)
 rename src/{ => main/java}/sporadic/customize_annotations_generics_wildcards_examples/MyTestState.java (100%)
 rename src/{ => main/java}/sporadic/customize_annotations_generics_wildcards_examples/SimpleTestCase.java (100%)
 rename src/{ => main/java}/sporadic/customize_annotations_generics_wildcards_examples/SteveSunFirstCustomAnnotation.java (100%)
 rename src/{ => main/java}/sporadic/exceptionsCanBeSelfDefined/SteveSunException.java (100%)
 rename src/{ => main/java}/sporadic/exceptionsCanBeSelfDefined/UnderstandExceptionTryCatch.java (100%)
 rename src/{ => main/java}/sporadic/java_async_method_example/async/method/AsyncClient.java (100%)
 rename src/{ => main/java}/sporadic/java_async_method_example/async/method/AsyncClientImpl.java (100%)
 rename src/{ => main/java}/sporadic/java_async_method_example/async/method/MainApp.java (100%)
 rename src/{ => main/java}/sporadic/java_async_method_example/async/method/SyncClient.java (100%)
 rename src/{ => main/java}/sporadic/java_async_method_example/async/method/SyncClientImpl.java (100%)
 rename src/{ => main/java}/sporadic/java_async_method_example/async/method/Task.java (100%)
 rename src/{ => main/java}/sporadic/java_async_method_example/future/MainApp.java (100%)
 rename src/{ => main/java}/sporadic/java_async_method_example/future/MyCallable.java (100%)
 rename src/{ => main/java}/sporadic/java_generics/GenericClass.java (100%)
 rename src/{ => main/java}/sporadic/java_generics/MainApp.java (100%)
 rename src/{ => main/java}/sporadic/java_generics/NonGenericClass.java (100%)
 rename src/{ => main/java}/sporadic/java_generics/ParentClass.java (100%)
 rename src/{ => main/java}/sporadic/jsonExample/JsonDemoClass.java (100%)
 rename src/{ => main/java}/sporadic/jsonExample/JsonIgnoreAnnotationDemo.java (100%)
 rename src/{ => main/java}/sporadic/method_invoke_and_reflect/Deet.java (100%)
 rename src/{ => main/java}/sporadic/producer_consumer_example/ProducerConsumerInJava.java (100%)
 rename src/{ => main/java}/sporadic/semaphore/ConnectionLimiter.java (100%)
 rename src/{ => main/java}/sporadic/socket_programming/GreetingClient.java (100%)
 rename src/{ => main/java}/sporadic/socket_programming/GreetingServer.java (100%)
 rename src/{ => main/java}/sporadic/sorting/HeapSort.java (100%)
 rename src/{ => main/java}/sporadic/sorting/HeapSortAgain.java (100%)
 rename src/{ => main/java}/sporadic/sorting/InsertionSort.java (100%)
 rename src/{ => main/java}/sporadic/sorting/MergeSort.java (100%)
 rename src/{ => main/java}/sporadic/sorting/QuickSort.java (100%)
 rename src/{ => main/java}/sporadic/thread/HusbandAndWifeJob.java (100%)
 rename src/{ => main/java}/sporadic/thread/ThreadIsCool.java (100%)
 rename src/{ => main/java}/sporadic/thread/ThreadLocalExample.java (100%)
 rename src/{ => main/java}/sporadic/thread/synchronization/withSynchronization/TestThread.java (100%)
 rename src/{ => main/java}/sporadic/thread/synchronization/withoutSynchronization/TestThread.java (100%)
 rename src/{ => main/java}/spring-configuration/json-spring-configuration.xml (100%)
 rename src/{ => main/java}/spring-configuration/serialization-spring-configuration.xml (100%)

diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..849935c
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,118 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>1.8</source>
+                    <target>1.8</target>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>com.fishercoder</groupId>
+    <artifactId>RandomJava</artifactId>
+    <version>1.0-SNAPSHOT</version>
+
+    <dependencies>
+
+        <dependency>
+            <groupId>org.apache.logging.log4j</groupId>
+            <artifactId>log4j-api</artifactId>
+            <version>2.7</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.logging.log4j</groupId>
+            <artifactId>log4j-core</artifactId>
+            <version>2.7</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <version>1.16.12</version>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>4.11</version>
+        </dependency>
+
+        <!-- spring-context which provides core functionality -->
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-context</artifactId>
+            <version>4.1.6.RELEASE</version>
+        </dependency>
+
+        <!-- The spring-aop module provides an AOP Alliance-compliant aspect-oriented
+            programming implementation allowing you to define -->
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-aop</artifactId>
+            <version>4.1.6.RELEASE</version>
+        </dependency>
+
+        <!-- The spring-webmvc module (also known as the Web-Servlet module) contains
+            Spring’s model-view-controller (MVC) and REST Web Services implementation
+            for web applications -->
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-webmvc</artifactId>
+            <version>4.1.6.RELEASE</version>
+        </dependency>
+
+        <!-- The spring-web module provides basic web-oriented integration features
+            such as multipart file upload functionality and the initialization of the
+            IoC container using Servlet listeners and a web-oriented application context -->
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-web</artifactId>
+            <version>4.1.6.RELEASE</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-annotations</artifactId>
+            <version>2.6.0</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-databind</artifactId>
+            <version>2.4.1.3</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-core-asl</artifactId>
+            <version>1.9.13</version>
+            <scope>compile</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-mapper-asl</artifactId>
+            <version>1.9.13</version>
+            <scope>compile</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>javax.mail</groupId>
+            <artifactId>mail</artifactId>
+            <version>1.5.0-b01</version>
+        </dependency>
+
+    </dependencies>
+
+    
+</project>
\ No newline at end of file
diff --git a/src/interviewQuestions/BinarySearch.java b/src/main/java/InterviewQuestions/BinarySearch.java
similarity index 100%
rename from src/interviewQuestions/BinarySearch.java
rename to src/main/java/InterviewQuestions/BinarySearch.java
diff --git a/src/interviewQuestions/BuildOrder.java b/src/main/java/InterviewQuestions/BuildOrder.java
similarity index 100%
rename from src/interviewQuestions/BuildOrder.java
rename to src/main/java/InterviewQuestions/BuildOrder.java
diff --git a/src/interviewQuestions/ColorCombinations.java b/src/main/java/InterviewQuestions/ColorCombinations.java
similarity index 100%
rename from src/interviewQuestions/ColorCombinations.java
rename to src/main/java/InterviewQuestions/ColorCombinations.java
diff --git a/src/interviewQuestions/ConcatenatedWords.java b/src/main/java/InterviewQuestions/ConcatenatedWords.java
similarity index 100%
rename from src/interviewQuestions/ConcatenatedWords.java
rename to src/main/java/InterviewQuestions/ConcatenatedWords.java
diff --git a/src/interviewQuestions/ConcatenatedWordsII.java b/src/main/java/InterviewQuestions/ConcatenatedWordsII.java
similarity index 100%
rename from src/interviewQuestions/ConcatenatedWordsII.java
rename to src/main/java/InterviewQuestions/ConcatenatedWordsII.java
diff --git a/src/interviewQuestions/FindLongestSuffixInTwoLists.java b/src/main/java/InterviewQuestions/FindLongestSuffixInTwoLists.java
similarity index 100%
rename from src/interviewQuestions/FindLongestSuffixInTwoLists.java
rename to src/main/java/InterviewQuestions/FindLongestSuffixInTwoLists.java
diff --git a/src/InterviewQuestions/FindWordFromNumber.java b/src/main/java/InterviewQuestions/FindWordFromNumber.java
similarity index 100%
rename from src/InterviewQuestions/FindWordFromNumber.java
rename to src/main/java/InterviewQuestions/FindWordFromNumber.java
diff --git a/src/interviewQuestions/LongestConsecutivePathInAMatrix.java b/src/main/java/InterviewQuestions/LongestConsecutivePathInAMatrix.java
similarity index 100%
rename from src/interviewQuestions/LongestConsecutivePathInAMatrix.java
rename to src/main/java/InterviewQuestions/LongestConsecutivePathInAMatrix.java
diff --git a/src/interviewQuestions/MaximumSizeSubarraySumEqualsOrSmallerThanK.java b/src/main/java/InterviewQuestions/MaximumSizeSubarraySumEqualsOrSmallerThanK.java
similarity index 100%
rename from src/interviewQuestions/MaximumSizeSubarraySumEqualsOrSmallerThanK.java
rename to src/main/java/InterviewQuestions/MaximumSizeSubarraySumEqualsOrSmallerThanK.java
diff --git a/src/interviewQuestions/MinFloors.java b/src/main/java/InterviewQuestions/MinFloors.java
similarity index 100%
rename from src/interviewQuestions/MinFloors.java
rename to src/main/java/InterviewQuestions/MinFloors.java
diff --git a/src/interviewQuestions/SetValueInDependencyGraph.java b/src/main/java/InterviewQuestions/SetValueInDependencyGraph.java
similarity index 100%
rename from src/interviewQuestions/SetValueInDependencyGraph.java
rename to src/main/java/InterviewQuestions/SetValueInDependencyGraph.java
diff --git a/src/designPatterns/chapter_1_strategy_pattern/CookBehavior.java b/src/main/java/designPatterns/chapter_1_strategy_pattern/CookBehavior.java
similarity index 100%
rename from src/designPatterns/chapter_1_strategy_pattern/CookBehavior.java
rename to src/main/java/designPatterns/chapter_1_strategy_pattern/CookBehavior.java
diff --git a/src/designPatterns/chapter_1_strategy_pattern/CookNoodlesBehavior.java b/src/main/java/designPatterns/chapter_1_strategy_pattern/CookNoodlesBehavior.java
similarity index 100%
rename from src/designPatterns/chapter_1_strategy_pattern/CookNoodlesBehavior.java
rename to src/main/java/designPatterns/chapter_1_strategy_pattern/CookNoodlesBehavior.java
diff --git a/src/designPatterns/chapter_1_strategy_pattern/CookRiceFlour.java b/src/main/java/designPatterns/chapter_1_strategy_pattern/CookRiceFlour.java
similarity index 100%
rename from src/designPatterns/chapter_1_strategy_pattern/CookRiceFlour.java
rename to src/main/java/designPatterns/chapter_1_strategy_pattern/CookRiceFlour.java
diff --git a/src/designPatterns/chapter_1_strategy_pattern/LoveBehavior.java b/src/main/java/designPatterns/chapter_1_strategy_pattern/LoveBehavior.java
similarity index 100%
rename from src/designPatterns/chapter_1_strategy_pattern/LoveBehavior.java
rename to src/main/java/designPatterns/chapter_1_strategy_pattern/LoveBehavior.java
diff --git a/src/designPatterns/chapter_1_strategy_pattern/LoveHusbandBehavior.java b/src/main/java/designPatterns/chapter_1_strategy_pattern/LoveHusbandBehavior.java
similarity index 100%
rename from src/designPatterns/chapter_1_strategy_pattern/LoveHusbandBehavior.java
rename to src/main/java/designPatterns/chapter_1_strategy_pattern/LoveHusbandBehavior.java
diff --git a/src/designPatterns/chapter_1_strategy_pattern/ModelWife.java b/src/main/java/designPatterns/chapter_1_strategy_pattern/ModelWife.java
similarity index 100%
rename from src/designPatterns/chapter_1_strategy_pattern/ModelWife.java
rename to src/main/java/designPatterns/chapter_1_strategy_pattern/ModelWife.java
diff --git a/src/designPatterns/chapter_1_strategy_pattern/RealWife.java b/src/main/java/designPatterns/chapter_1_strategy_pattern/RealWife.java
similarity index 100%
rename from src/designPatterns/chapter_1_strategy_pattern/RealWife.java
rename to src/main/java/designPatterns/chapter_1_strategy_pattern/RealWife.java
diff --git a/src/designPatterns/chapter_1_strategy_pattern/StrategtyPatternTestDrive.java b/src/main/java/designPatterns/chapter_1_strategy_pattern/StrategtyPatternTestDrive.java
similarity index 100%
rename from src/designPatterns/chapter_1_strategy_pattern/StrategtyPatternTestDrive.java
rename to src/main/java/designPatterns/chapter_1_strategy_pattern/StrategtyPatternTestDrive.java
diff --git a/src/designPatterns/chapter_1_strategy_pattern/Wife.java b/src/main/java/designPatterns/chapter_1_strategy_pattern/Wife.java
similarity index 100%
rename from src/designPatterns/chapter_1_strategy_pattern/Wife.java
rename to src/main/java/designPatterns/chapter_1_strategy_pattern/Wife.java
diff --git a/src/designPatterns/chapter_2_observer_pattern/CoreFamily.java b/src/main/java/designPatterns/chapter_2_observer_pattern/CoreFamily.java
similarity index 100%
rename from src/designPatterns/chapter_2_observer_pattern/CoreFamily.java
rename to src/main/java/designPatterns/chapter_2_observer_pattern/CoreFamily.java
diff --git a/src/designPatterns/chapter_2_observer_pattern/CoreFamilyImpl.java b/src/main/java/designPatterns/chapter_2_observer_pattern/CoreFamilyImpl.java
similarity index 100%
rename from src/designPatterns/chapter_2_observer_pattern/CoreFamilyImpl.java
rename to src/main/java/designPatterns/chapter_2_observer_pattern/CoreFamilyImpl.java
diff --git a/src/designPatterns/chapter_2_observer_pattern/ObserverPatternTestDrive.java b/src/main/java/designPatterns/chapter_2_observer_pattern/ObserverPatternTestDrive.java
similarity index 100%
rename from src/designPatterns/chapter_2_observer_pattern/ObserverPatternTestDrive.java
rename to src/main/java/designPatterns/chapter_2_observer_pattern/ObserverPatternTestDrive.java
diff --git a/src/designPatterns/chapter_2_observer_pattern/Relative.java b/src/main/java/designPatterns/chapter_2_observer_pattern/Relative.java
similarity index 100%
rename from src/designPatterns/chapter_2_observer_pattern/Relative.java
rename to src/main/java/designPatterns/chapter_2_observer_pattern/Relative.java
diff --git a/src/designPatterns/chapter_2_observer_pattern/RelativeImpl.java b/src/main/java/designPatterns/chapter_2_observer_pattern/RelativeImpl.java
similarity index 100%
rename from src/designPatterns/chapter_2_observer_pattern/RelativeImpl.java
rename to src/main/java/designPatterns/chapter_2_observer_pattern/RelativeImpl.java
diff --git a/src/designPatterns/chapter_3_decorator_pattern/Beverage.java b/src/main/java/designPatterns/chapter_3_decorator_pattern/Beverage.java
similarity index 100%
rename from src/designPatterns/chapter_3_decorator_pattern/Beverage.java
rename to src/main/java/designPatterns/chapter_3_decorator_pattern/Beverage.java
diff --git a/src/designPatterns/chapter_3_decorator_pattern/CondimentDecorator.java b/src/main/java/designPatterns/chapter_3_decorator_pattern/CondimentDecorator.java
similarity index 100%
rename from src/designPatterns/chapter_3_decorator_pattern/CondimentDecorator.java
rename to src/main/java/designPatterns/chapter_3_decorator_pattern/CondimentDecorator.java
diff --git a/src/designPatterns/chapter_3_decorator_pattern/DecoratorPatternTestDrive.java b/src/main/java/designPatterns/chapter_3_decorator_pattern/DecoratorPatternTestDrive.java
similarity index 100%
rename from src/designPatterns/chapter_3_decorator_pattern/DecoratorPatternTestDrive.java
rename to src/main/java/designPatterns/chapter_3_decorator_pattern/DecoratorPatternTestDrive.java
diff --git a/src/designPatterns/chapter_3_decorator_pattern/Espresso.java b/src/main/java/designPatterns/chapter_3_decorator_pattern/Espresso.java
similarity index 100%
rename from src/designPatterns/chapter_3_decorator_pattern/Espresso.java
rename to src/main/java/designPatterns/chapter_3_decorator_pattern/Espresso.java
diff --git a/src/designPatterns/chapter_3_decorator_pattern/HouseBlend.java b/src/main/java/designPatterns/chapter_3_decorator_pattern/HouseBlend.java
similarity index 100%
rename from src/designPatterns/chapter_3_decorator_pattern/HouseBlend.java
rename to src/main/java/designPatterns/chapter_3_decorator_pattern/HouseBlend.java
diff --git a/src/designPatterns/chapter_3_decorator_pattern/Mocha.java b/src/main/java/designPatterns/chapter_3_decorator_pattern/Mocha.java
similarity index 100%
rename from src/designPatterns/chapter_3_decorator_pattern/Mocha.java
rename to src/main/java/designPatterns/chapter_3_decorator_pattern/Mocha.java
diff --git a/src/designPatterns/chapter_3_decorator_pattern/Soy.java b/src/main/java/designPatterns/chapter_3_decorator_pattern/Soy.java
similarity index 100%
rename from src/designPatterns/chapter_3_decorator_pattern/Soy.java
rename to src/main/java/designPatterns/chapter_3_decorator_pattern/Soy.java
diff --git a/src/designPatterns/chapter_3_decorator_pattern/Whip.java b/src/main/java/designPatterns/chapter_3_decorator_pattern/Whip.java
similarity index 100%
rename from src/designPatterns/chapter_3_decorator_pattern/Whip.java
rename to src/main/java/designPatterns/chapter_3_decorator_pattern/Whip.java
diff --git a/src/designPatterns/factory_pattern/Circle.java b/src/main/java/designPatterns/factory_pattern/Circle.java
similarity index 100%
rename from src/designPatterns/factory_pattern/Circle.java
rename to src/main/java/designPatterns/factory_pattern/Circle.java
diff --git a/src/designPatterns/factory_pattern/MainApp.java b/src/main/java/designPatterns/factory_pattern/MainApp.java
similarity index 100%
rename from src/designPatterns/factory_pattern/MainApp.java
rename to src/main/java/designPatterns/factory_pattern/MainApp.java
diff --git a/src/designPatterns/factory_pattern/Rectangle.java b/src/main/java/designPatterns/factory_pattern/Rectangle.java
similarity index 100%
rename from src/designPatterns/factory_pattern/Rectangle.java
rename to src/main/java/designPatterns/factory_pattern/Rectangle.java
diff --git a/src/designPatterns/factory_pattern/Shape.java b/src/main/java/designPatterns/factory_pattern/Shape.java
similarity index 100%
rename from src/designPatterns/factory_pattern/Shape.java
rename to src/main/java/designPatterns/factory_pattern/Shape.java
diff --git a/src/designPatterns/factory_pattern/ShapeFactory.java b/src/main/java/designPatterns/factory_pattern/ShapeFactory.java
similarity index 100%
rename from src/designPatterns/factory_pattern/ShapeFactory.java
rename to src/main/java/designPatterns/factory_pattern/ShapeFactory.java
diff --git a/src/designPatterns/factory_pattern/Square.java b/src/main/java/designPatterns/factory_pattern/Square.java
similarity index 100%
rename from src/designPatterns/factory_pattern/Square.java
rename to src/main/java/designPatterns/factory_pattern/Square.java
diff --git a/src/designPatterns/visitor_pattern/Computer.java b/src/main/java/designPatterns/visitor_pattern/Computer.java
similarity index 100%
rename from src/designPatterns/visitor_pattern/Computer.java
rename to src/main/java/designPatterns/visitor_pattern/Computer.java
diff --git a/src/designPatterns/visitor_pattern/ComputerPart.java b/src/main/java/designPatterns/visitor_pattern/ComputerPart.java
similarity index 100%
rename from src/designPatterns/visitor_pattern/ComputerPart.java
rename to src/main/java/designPatterns/visitor_pattern/ComputerPart.java
diff --git a/src/designPatterns/visitor_pattern/ComputerPartDisplayVisitor.java b/src/main/java/designPatterns/visitor_pattern/ComputerPartDisplayVisitor.java
similarity index 100%
rename from src/designPatterns/visitor_pattern/ComputerPartDisplayVisitor.java
rename to src/main/java/designPatterns/visitor_pattern/ComputerPartDisplayVisitor.java
diff --git a/src/designPatterns/visitor_pattern/ComputerPartVisitor.java b/src/main/java/designPatterns/visitor_pattern/ComputerPartVisitor.java
similarity index 100%
rename from src/designPatterns/visitor_pattern/ComputerPartVisitor.java
rename to src/main/java/designPatterns/visitor_pattern/ComputerPartVisitor.java
diff --git a/src/designPatterns/visitor_pattern/Keyboard.java b/src/main/java/designPatterns/visitor_pattern/Keyboard.java
similarity index 100%
rename from src/designPatterns/visitor_pattern/Keyboard.java
rename to src/main/java/designPatterns/visitor_pattern/Keyboard.java
diff --git a/src/designPatterns/visitor_pattern/Monitor.java b/src/main/java/designPatterns/visitor_pattern/Monitor.java
similarity index 100%
rename from src/designPatterns/visitor_pattern/Monitor.java
rename to src/main/java/designPatterns/visitor_pattern/Monitor.java
diff --git a/src/designPatterns/visitor_pattern/Mouse.java b/src/main/java/designPatterns/visitor_pattern/Mouse.java
similarity index 100%
rename from src/designPatterns/visitor_pattern/Mouse.java
rename to src/main/java/designPatterns/visitor_pattern/Mouse.java
diff --git a/src/designPatterns/visitor_pattern/VisitorPatternDemo.java b/src/main/java/designPatterns/visitor_pattern/VisitorPatternDemo.java
similarity index 100%
rename from src/designPatterns/visitor_pattern/VisitorPatternDemo.java
rename to src/main/java/designPatterns/visitor_pattern/VisitorPatternDemo.java
diff --git a/src/learnHeadFirstJava/another_serialization_example/DeseriliazeDemo.java b/src/main/java/learnHeadFirstJava/another_serialization_example/DeseriliazeDemo.java
similarity index 100%
rename from src/learnHeadFirstJava/another_serialization_example/DeseriliazeDemo.java
rename to src/main/java/learnHeadFirstJava/another_serialization_example/DeseriliazeDemo.java
diff --git a/src/learnHeadFirstJava/another_serialization_example/Employee.java b/src/main/java/learnHeadFirstJava/another_serialization_example/Employee.java
similarity index 100%
rename from src/learnHeadFirstJava/another_serialization_example/Employee.java
rename to src/main/java/learnHeadFirstJava/another_serialization_example/Employee.java
diff --git a/src/learnHeadFirstJava/another_serialization_example/MainApp.java b/src/main/java/learnHeadFirstJava/another_serialization_example/MainApp.java
similarity index 100%
rename from src/learnHeadFirstJava/another_serialization_example/MainApp.java
rename to src/main/java/learnHeadFirstJava/another_serialization_example/MainApp.java
diff --git a/src/learnHeadFirstJava/another_serialization_example/SerializeDemo.java b/src/main/java/learnHeadFirstJava/another_serialization_example/SerializeDemo.java
similarity index 100%
rename from src/learnHeadFirstJava/another_serialization_example/SerializeDemo.java
rename to src/main/java/learnHeadFirstJava/another_serialization_example/SerializeDemo.java
diff --git a/src/learnHeadFirstJava/constructorChaining/Animal.java b/src/main/java/learnHeadFirstJava/constructorChaining/Animal.java
similarity index 100%
rename from src/learnHeadFirstJava/constructorChaining/Animal.java
rename to src/main/java/learnHeadFirstJava/constructorChaining/Animal.java
diff --git a/src/learnHeadFirstJava/constructorChaining/Creature.java b/src/main/java/learnHeadFirstJava/constructorChaining/Creature.java
similarity index 100%
rename from src/learnHeadFirstJava/constructorChaining/Creature.java
rename to src/main/java/learnHeadFirstJava/constructorChaining/Creature.java
diff --git a/src/learnHeadFirstJava/constructorChaining/Dog.java b/src/main/java/learnHeadFirstJava/constructorChaining/Dog.java
similarity index 100%
rename from src/learnHeadFirstJava/constructorChaining/Dog.java
rename to src/main/java/learnHeadFirstJava/constructorChaining/Dog.java
diff --git a/src/learnHeadFirstJava/constructorChaining/MainApp.java b/src/main/java/learnHeadFirstJava/constructorChaining/MainApp.java
similarity index 100%
rename from src/learnHeadFirstJava/constructorChaining/MainApp.java
rename to src/main/java/learnHeadFirstJava/constructorChaining/MainApp.java
diff --git a/src/learnHeadFirstJava/constructorChaining/Pet.java b/src/main/java/learnHeadFirstJava/constructorChaining/Pet.java
similarity index 100%
rename from src/learnHeadFirstJava/constructorChaining/Pet.java
rename to src/main/java/learnHeadFirstJava/constructorChaining/Pet.java
diff --git a/src/learnHeadFirstJava/serializationIsFun/GospelBook.java b/src/main/java/learnHeadFirstJava/serializationIsFun/GospelBook.java
similarity index 100%
rename from src/learnHeadFirstJava/serializationIsFun/GospelBook.java
rename to src/main/java/learnHeadFirstJava/serializationIsFun/GospelBook.java
diff --git a/src/learnHeadFirstJava/serializationIsFun/GospelSaverTest.java b/src/main/java/learnHeadFirstJava/serializationIsFun/GospelSaverTest.java
similarity index 100%
rename from src/learnHeadFirstJava/serializationIsFun/GospelSaverTest.java
rename to src/main/java/learnHeadFirstJava/serializationIsFun/GospelSaverTest.java
diff --git a/src/sporadic/IO_example/JavaFileExample.java b/src/main/java/sporadic/IO_example/JavaFileExample.java
similarity index 100%
rename from src/sporadic/IO_example/JavaFileExample.java
rename to src/main/java/sporadic/IO_example/JavaFileExample.java
diff --git a/src/sporadic/IO_example/JavaIOExample.java b/src/main/java/sporadic/IO_example/JavaIOExample.java
similarity index 100%
rename from src/sporadic/IO_example/JavaIOExample.java
rename to src/main/java/sporadic/IO_example/JavaIOExample.java
diff --git a/src/sporadic/ProgramToFindMachineInfo.java b/src/main/java/sporadic/ProgramToFindMachineInfo.java
similarity index 100%
rename from src/sporadic/ProgramToFindMachineInfo.java
rename to src/main/java/sporadic/ProgramToFindMachineInfo.java
diff --git a/src/sporadic/SendEmail.java b/src/main/java/sporadic/SendEmail.java
similarity index 100%
rename from src/sporadic/SendEmail.java
rename to src/main/java/sporadic/SendEmail.java
diff --git a/src/sporadic/UnderstandClass.java b/src/main/java/sporadic/UnderstandClass.java
similarity index 100%
rename from src/sporadic/UnderstandClass.java
rename to src/main/java/sporadic/UnderstandClass.java
diff --git a/src/sporadic/UnderstandingJavaReference.java b/src/main/java/sporadic/UnderstandingJavaReference.java
similarity index 100%
rename from src/sporadic/UnderstandingJavaReference.java
rename to src/main/java/sporadic/UnderstandingJavaReference.java
diff --git a/src/sporadic/customize_annotations_generics_wildcards_examples/AnotherSimpleTestCase.java b/src/main/java/sporadic/customize_annotations_generics_wildcards_examples/AnotherSimpleTestCase.java
similarity index 100%
rename from src/sporadic/customize_annotations_generics_wildcards_examples/AnotherSimpleTestCase.java
rename to src/main/java/sporadic/customize_annotations_generics_wildcards_examples/AnotherSimpleTestCase.java
diff --git a/src/sporadic/customize_annotations_generics_wildcards_examples/Main.java b/src/main/java/sporadic/customize_annotations_generics_wildcards_examples/Main.java
similarity index 100%
rename from src/sporadic/customize_annotations_generics_wildcards_examples/Main.java
rename to src/main/java/sporadic/customize_annotations_generics_wildcards_examples/Main.java
diff --git a/src/sporadic/customize_annotations_generics_wildcards_examples/MyTestRunner.java b/src/main/java/sporadic/customize_annotations_generics_wildcards_examples/MyTestRunner.java
similarity index 100%
rename from src/sporadic/customize_annotations_generics_wildcards_examples/MyTestRunner.java
rename to src/main/java/sporadic/customize_annotations_generics_wildcards_examples/MyTestRunner.java
diff --git a/src/sporadic/customize_annotations_generics_wildcards_examples/MyTestState.java b/src/main/java/sporadic/customize_annotations_generics_wildcards_examples/MyTestState.java
similarity index 100%
rename from src/sporadic/customize_annotations_generics_wildcards_examples/MyTestState.java
rename to src/main/java/sporadic/customize_annotations_generics_wildcards_examples/MyTestState.java
diff --git a/src/sporadic/customize_annotations_generics_wildcards_examples/SimpleTestCase.java b/src/main/java/sporadic/customize_annotations_generics_wildcards_examples/SimpleTestCase.java
similarity index 100%
rename from src/sporadic/customize_annotations_generics_wildcards_examples/SimpleTestCase.java
rename to src/main/java/sporadic/customize_annotations_generics_wildcards_examples/SimpleTestCase.java
diff --git a/src/sporadic/customize_annotations_generics_wildcards_examples/SteveSunFirstCustomAnnotation.java b/src/main/java/sporadic/customize_annotations_generics_wildcards_examples/SteveSunFirstCustomAnnotation.java
similarity index 100%
rename from src/sporadic/customize_annotations_generics_wildcards_examples/SteveSunFirstCustomAnnotation.java
rename to src/main/java/sporadic/customize_annotations_generics_wildcards_examples/SteveSunFirstCustomAnnotation.java
diff --git a/src/sporadic/exceptionsCanBeSelfDefined/SteveSunException.java b/src/main/java/sporadic/exceptionsCanBeSelfDefined/SteveSunException.java
similarity index 100%
rename from src/sporadic/exceptionsCanBeSelfDefined/SteveSunException.java
rename to src/main/java/sporadic/exceptionsCanBeSelfDefined/SteveSunException.java
diff --git a/src/sporadic/exceptionsCanBeSelfDefined/UnderstandExceptionTryCatch.java b/src/main/java/sporadic/exceptionsCanBeSelfDefined/UnderstandExceptionTryCatch.java
similarity index 100%
rename from src/sporadic/exceptionsCanBeSelfDefined/UnderstandExceptionTryCatch.java
rename to src/main/java/sporadic/exceptionsCanBeSelfDefined/UnderstandExceptionTryCatch.java
diff --git a/src/sporadic/java_async_method_example/async/method/AsyncClient.java b/src/main/java/sporadic/java_async_method_example/async/method/AsyncClient.java
similarity index 100%
rename from src/sporadic/java_async_method_example/async/method/AsyncClient.java
rename to src/main/java/sporadic/java_async_method_example/async/method/AsyncClient.java
diff --git a/src/sporadic/java_async_method_example/async/method/AsyncClientImpl.java b/src/main/java/sporadic/java_async_method_example/async/method/AsyncClientImpl.java
similarity index 100%
rename from src/sporadic/java_async_method_example/async/method/AsyncClientImpl.java
rename to src/main/java/sporadic/java_async_method_example/async/method/AsyncClientImpl.java
diff --git a/src/sporadic/java_async_method_example/async/method/MainApp.java b/src/main/java/sporadic/java_async_method_example/async/method/MainApp.java
similarity index 100%
rename from src/sporadic/java_async_method_example/async/method/MainApp.java
rename to src/main/java/sporadic/java_async_method_example/async/method/MainApp.java
diff --git a/src/sporadic/java_async_method_example/async/method/SyncClient.java b/src/main/java/sporadic/java_async_method_example/async/method/SyncClient.java
similarity index 100%
rename from src/sporadic/java_async_method_example/async/method/SyncClient.java
rename to src/main/java/sporadic/java_async_method_example/async/method/SyncClient.java
diff --git a/src/sporadic/java_async_method_example/async/method/SyncClientImpl.java b/src/main/java/sporadic/java_async_method_example/async/method/SyncClientImpl.java
similarity index 100%
rename from src/sporadic/java_async_method_example/async/method/SyncClientImpl.java
rename to src/main/java/sporadic/java_async_method_example/async/method/SyncClientImpl.java
diff --git a/src/sporadic/java_async_method_example/async/method/Task.java b/src/main/java/sporadic/java_async_method_example/async/method/Task.java
similarity index 100%
rename from src/sporadic/java_async_method_example/async/method/Task.java
rename to src/main/java/sporadic/java_async_method_example/async/method/Task.java
diff --git a/src/sporadic/java_async_method_example/future/MainApp.java b/src/main/java/sporadic/java_async_method_example/future/MainApp.java
similarity index 100%
rename from src/sporadic/java_async_method_example/future/MainApp.java
rename to src/main/java/sporadic/java_async_method_example/future/MainApp.java
diff --git a/src/sporadic/java_async_method_example/future/MyCallable.java b/src/main/java/sporadic/java_async_method_example/future/MyCallable.java
similarity index 100%
rename from src/sporadic/java_async_method_example/future/MyCallable.java
rename to src/main/java/sporadic/java_async_method_example/future/MyCallable.java
diff --git a/src/sporadic/java_generics/GenericClass.java b/src/main/java/sporadic/java_generics/GenericClass.java
similarity index 100%
rename from src/sporadic/java_generics/GenericClass.java
rename to src/main/java/sporadic/java_generics/GenericClass.java
diff --git a/src/sporadic/java_generics/MainApp.java b/src/main/java/sporadic/java_generics/MainApp.java
similarity index 100%
rename from src/sporadic/java_generics/MainApp.java
rename to src/main/java/sporadic/java_generics/MainApp.java
diff --git a/src/sporadic/java_generics/NonGenericClass.java b/src/main/java/sporadic/java_generics/NonGenericClass.java
similarity index 100%
rename from src/sporadic/java_generics/NonGenericClass.java
rename to src/main/java/sporadic/java_generics/NonGenericClass.java
diff --git a/src/sporadic/java_generics/ParentClass.java b/src/main/java/sporadic/java_generics/ParentClass.java
similarity index 100%
rename from src/sporadic/java_generics/ParentClass.java
rename to src/main/java/sporadic/java_generics/ParentClass.java
diff --git a/src/sporadic/jsonExample/JsonDemoClass.java b/src/main/java/sporadic/jsonExample/JsonDemoClass.java
similarity index 100%
rename from src/sporadic/jsonExample/JsonDemoClass.java
rename to src/main/java/sporadic/jsonExample/JsonDemoClass.java
diff --git a/src/sporadic/jsonExample/JsonIgnoreAnnotationDemo.java b/src/main/java/sporadic/jsonExample/JsonIgnoreAnnotationDemo.java
similarity index 100%
rename from src/sporadic/jsonExample/JsonIgnoreAnnotationDemo.java
rename to src/main/java/sporadic/jsonExample/JsonIgnoreAnnotationDemo.java
diff --git a/src/sporadic/method_invoke_and_reflect/Deet.java b/src/main/java/sporadic/method_invoke_and_reflect/Deet.java
similarity index 100%
rename from src/sporadic/method_invoke_and_reflect/Deet.java
rename to src/main/java/sporadic/method_invoke_and_reflect/Deet.java
diff --git a/src/sporadic/producer_consumer_example/ProducerConsumerInJava.java b/src/main/java/sporadic/producer_consumer_example/ProducerConsumerInJava.java
similarity index 100%
rename from src/sporadic/producer_consumer_example/ProducerConsumerInJava.java
rename to src/main/java/sporadic/producer_consumer_example/ProducerConsumerInJava.java
diff --git a/src/sporadic/semaphore/ConnectionLimiter.java b/src/main/java/sporadic/semaphore/ConnectionLimiter.java
similarity index 100%
rename from src/sporadic/semaphore/ConnectionLimiter.java
rename to src/main/java/sporadic/semaphore/ConnectionLimiter.java
diff --git a/src/sporadic/socket_programming/GreetingClient.java b/src/main/java/sporadic/socket_programming/GreetingClient.java
similarity index 100%
rename from src/sporadic/socket_programming/GreetingClient.java
rename to src/main/java/sporadic/socket_programming/GreetingClient.java
diff --git a/src/sporadic/socket_programming/GreetingServer.java b/src/main/java/sporadic/socket_programming/GreetingServer.java
similarity index 100%
rename from src/sporadic/socket_programming/GreetingServer.java
rename to src/main/java/sporadic/socket_programming/GreetingServer.java
diff --git a/src/sporadic/sorting/HeapSort.java b/src/main/java/sporadic/sorting/HeapSort.java
similarity index 100%
rename from src/sporadic/sorting/HeapSort.java
rename to src/main/java/sporadic/sorting/HeapSort.java
diff --git a/src/sporadic/sorting/HeapSortAgain.java b/src/main/java/sporadic/sorting/HeapSortAgain.java
similarity index 100%
rename from src/sporadic/sorting/HeapSortAgain.java
rename to src/main/java/sporadic/sorting/HeapSortAgain.java
diff --git a/src/sporadic/sorting/InsertionSort.java b/src/main/java/sporadic/sorting/InsertionSort.java
similarity index 100%
rename from src/sporadic/sorting/InsertionSort.java
rename to src/main/java/sporadic/sorting/InsertionSort.java
diff --git a/src/sporadic/sorting/MergeSort.java b/src/main/java/sporadic/sorting/MergeSort.java
similarity index 100%
rename from src/sporadic/sorting/MergeSort.java
rename to src/main/java/sporadic/sorting/MergeSort.java
diff --git a/src/sporadic/sorting/QuickSort.java b/src/main/java/sporadic/sorting/QuickSort.java
similarity index 100%
rename from src/sporadic/sorting/QuickSort.java
rename to src/main/java/sporadic/sorting/QuickSort.java
diff --git a/src/sporadic/thread/HusbandAndWifeJob.java b/src/main/java/sporadic/thread/HusbandAndWifeJob.java
similarity index 100%
rename from src/sporadic/thread/HusbandAndWifeJob.java
rename to src/main/java/sporadic/thread/HusbandAndWifeJob.java
diff --git a/src/sporadic/thread/ThreadIsCool.java b/src/main/java/sporadic/thread/ThreadIsCool.java
similarity index 100%
rename from src/sporadic/thread/ThreadIsCool.java
rename to src/main/java/sporadic/thread/ThreadIsCool.java
diff --git a/src/sporadic/thread/ThreadLocalExample.java b/src/main/java/sporadic/thread/ThreadLocalExample.java
similarity index 100%
rename from src/sporadic/thread/ThreadLocalExample.java
rename to src/main/java/sporadic/thread/ThreadLocalExample.java
diff --git a/src/sporadic/thread/synchronization/withSynchronization/TestThread.java b/src/main/java/sporadic/thread/synchronization/withSynchronization/TestThread.java
similarity index 100%
rename from src/sporadic/thread/synchronization/withSynchronization/TestThread.java
rename to src/main/java/sporadic/thread/synchronization/withSynchronization/TestThread.java
diff --git a/src/sporadic/thread/synchronization/withoutSynchronization/TestThread.java b/src/main/java/sporadic/thread/synchronization/withoutSynchronization/TestThread.java
similarity index 100%
rename from src/sporadic/thread/synchronization/withoutSynchronization/TestThread.java
rename to src/main/java/sporadic/thread/synchronization/withoutSynchronization/TestThread.java
diff --git a/src/spring-configuration/json-spring-configuration.xml b/src/main/java/spring-configuration/json-spring-configuration.xml
similarity index 100%
rename from src/spring-configuration/json-spring-configuration.xml
rename to src/main/java/spring-configuration/json-spring-configuration.xml
diff --git a/src/spring-configuration/serialization-spring-configuration.xml b/src/main/java/spring-configuration/serialization-spring-configuration.xml
similarity index 100%
rename from src/spring-configuration/serialization-spring-configuration.xml
rename to src/main/java/spring-configuration/serialization-spring-configuration.xml

From 9ffaf681559392a7e4b29bb11de7111f25257327 Mon Sep 17 00:00:00 2001
From: Steve Sun <stevesun@coupang.com>
Date: Sun, 22 Jan 2017 16:44:10 -0800
Subject: [PATCH 020/185] [JAVA-0000] add RegexTestPatternMatcher

---
 README.md                                     |  2 +-
 .../sporadic/RegexTestPatternMatcher.java     | 38 +++++++++++++++++++
 2 files changed, 39 insertions(+), 1 deletion(-)
 create mode 100644 src/main/java/sporadic/RegexTestPatternMatcher.java

diff --git a/README.md b/README.md
index a341794..207f2fd 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,2 @@
 # RandomJava
-Please download spring-*.jar, apache-logging, JAF, Javamail and other necessary jars and put them onto your classpath or add them as external libraries, otherwise your IntelliJ/Eclipse won't smile. ^ ^
+This is a Maven project containing a bunch of Random Java programs that I used, wrote from time to time.
diff --git a/src/main/java/sporadic/RegexTestPatternMatcher.java b/src/main/java/sporadic/RegexTestPatternMatcher.java
new file mode 100644
index 0000000..482da69
--- /dev/null
+++ b/src/main/java/sporadic/RegexTestPatternMatcher.java
@@ -0,0 +1,38 @@
+package sporadic;
+
+/**
+ * Created by stevesun on 1/22/17.
+ */
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**This is a program to play around with regex, I asked a question on SO: http://stackoverflow.com/questions/41774435/how-to-split-a-string-based-on-in-java*/
+public class RegexTestPatternMatcher {
+    public static final String EXAMPLE_TEST = "This is my small example string which I'm going to use for pattern matching.";
+
+    public static void main(String[] args) {
+        String string = "[{1000, 500, 1}, {1001, 501, 1}, {1002, 501, 2}]";
+        Matcher m = Pattern.compile("\\{[0-9, ]+\\}").matcher(string);
+        while(m.find()){
+            System.out.println(m.group());
+        }
+
+        Pattern pattern = Pattern.compile("\\w+");
+        // in case you would like to ignore case sensitivity,
+        // you could use this statement:
+        // Pattern pattern = Pattern.compile("\\s+", Pattern.CASE_INSENSITIVE);
+        Matcher matcher = pattern.matcher(EXAMPLE_TEST);
+        // check all occurance
+        while (matcher.find()) {
+            System.out.print("Start index: " + matcher.start());
+            System.out.print(" End index: " + matcher.end() + " ");
+            System.out.println(matcher.group());
+        }
+        // now create a new pattern and matcher to replace whitespace with tabs
+        Pattern replace = Pattern.compile("\\s+");
+        Matcher matcher2 = replace.matcher(EXAMPLE_TEST);
+        System.out.println(matcher2.replaceAll("\t"));
+    }
+}
+

From e9d7d213739f98e9df90b5f28b4f7c78f2993aba Mon Sep 17 00:00:00 2001
From: Steve Sun <stevesun@coupang.com>
Date: Sun, 22 Jan 2017 16:49:20 -0800
Subject: [PATCH 021/185] [JAVA-0000] add minor change

---
 src/main/java/sporadic/RegexTestPatternMatcher.java | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/src/main/java/sporadic/RegexTestPatternMatcher.java b/src/main/java/sporadic/RegexTestPatternMatcher.java
index 482da69..673bc74 100644
--- a/src/main/java/sporadic/RegexTestPatternMatcher.java
+++ b/src/main/java/sporadic/RegexTestPatternMatcher.java
@@ -33,6 +33,9 @@ public static void main(String[] args) {
         Pattern replace = Pattern.compile("\\s+");
         Matcher matcher2 = replace.matcher(EXAMPLE_TEST);
         System.out.println(matcher2.replaceAll("\t"));
+
+        //use Java to print out a long string with \n inside
+        System.out.println("MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDF3xdggzWiOsbZ\nETP5JSQswsCA7PGijDAM19Vg78rPii2kWBJ7mT8SbE+3UVZgZQeHpXsD4dz+7PY2\n3HJVxPI/xHFmukarX9LM9FRcPCWnjZDC8OqlbpDPwUyHU98EMfAxCtmie/LtnxCv\nbtXLEpCV/E8Y14aJOMzwQAwc/qbcTX4cqw/gMgcNogYHcuNCIxlNAIOnsXsNm6jx\nx0spL9Z/5Cny0ys/+GkxMi1rTZROESdYI0xwHSMcl8SjO2z1aejdRC2U/3jb4X/n\nmbjAzHfFTdjtxU5b9e9xPuD2+/tv8ug8cm1HjNrxhTwcW7chqUeQAxB6Dd5kPV3n\n7pkHy/8HAgMBAAECggEAGVclvkVvc/RFDP2IA2s/Q8A5OQmfNGrxqGNnvz9WYNfY\nWoiw7UVF740RdG+lOTkXCsclhuzBCaC9M29t8RAE2ifFQhuu+zmNXJQZzaoiRF/7\n3wtNcZxETWb67wXNtNLUaONz1bw78zSAxYbTOGuLOroSQyMu5pnwnQAGzRvLsMC9\n1RnrV7kPgdf0iVbKjVGXW2TzLmiVNxnglXFAYM406vblcZaWBcdSPuSAZs7WPlle\nYOgtwcNX1TPBoujy3tMRBjjJPUt1yixgp74iKThG5FC6YCy9/MWfX9WE27/SsIh6\nC+nFJaVMwl/2iLQ123UH0kouIb9Nckmdsk6R+uSN8QKBgQD8QJhiNoPY3HARZLgZ\nqj9gbp0/170z2nii7wT/8ynQij207kFYjUnOC78KJsFmrKyf2dicoIxu6fj0cL6A\nOdLIFpmVByy6pAJpSW73xirzhmYt2f05a4D/A3LkfmwdsZ1x4DQx4U9PgKgJpIYs\n+cuGzSee0uylImLnlwqbQG0LCQKBgQDIz6qX5USrGWPInOTSb3h1N3FuOqfxrtFp\nKWjWimdU9BmuArVHHIrrHW9/xQsnpX3iaQPfTbeDpy32VZulhLhJs028JZu+/fGb\nqYUiDgwOJ+sYCC/3H5/KGt2/Xjfi213Fh9XiWj1ZbZvdj9Dygwn4yGiP4dUGVQGo\nP9zQj7BtjwKBgAQZZKCL9D6M7oFJ2rgIDTma8pE8B0YVccpsCe/C2tYZuQD8sjEn\nMqDXjgYzNQdfHPsIBj4dWcrfoH0Qa/gXeHZp75r9X9u0mJlvaQ87uCz27Sgnl7bc\nKV97hd1ytH0TCtTz6MU6vRg0pgZqFwgaExWgtdkd4lyYn3TV/oUhWeRJAoGAJX+R\n7ZdkgUbWeUnC+QDTz5+w0NKnNdxdQnP3HcjujtCeUv4yd7r+vfTbM1LKSHcA0Nyn\nWnWaxTzculk2HWxxNWIELBQhx0KIcXbwY3GYErSlk/FDc7Q2FHl72xZu/S/VjONW\nr1QGjMKJDpCihgauQAS8cdHMA8iv7IkwZMnQOkUCgYEA6yVXJ9It1fE1eisK2NY5\nfkLw1iviBWpZ4mgipTTglP5K3CEG1ygDs7PJOP0JEiDWPWf8PmvROUp1k9x+nKFP\nekd2qwZEul9Pr0jaD3y9dnpK3Sg4qxKhlRy0to3xzszbyL7gmP8l/9yxcbTyIRLT\nWDZrtCj706FGRFx/QkUkku0=");
     }
 }
 

From 7a3b2a84a158b40f1a432f40632c2147aab1896c Mon Sep 17 00:00:00 2001
From: Steve Sun <stevesun@coupang.com>
Date: Tue, 24 Jan 2017 16:44:00 -0800
Subject: [PATCH 022/185] [AVRO-0000] add avro example

---
 .travis.yml                                   |   3 +
 README.md                                     |   5 +
 pom.xml                                       |   6 +
 src/main/java/avro/SMSResult.avsc             |  27 +++
 .../avro/apacheExample/ApacheExample.java     |  52 ++++++
 .../java/avro/apacheExample/Employee.avsc     |   9 +
 src/main/java/avro/apacheExample/output.avro  | Bin 0 -> 218 bytes
 .../java/avro/rfoldesExample/Employee.avsc    |  10 +
 .../java/avro/rfoldesExample/Employee.java    | 172 ++++++++++++++++++
 .../java/avro/rfoldesExample/Employee2.avsc   |  10 +
 10 files changed, 294 insertions(+)
 create mode 100644 .travis.yml
 create mode 100644 src/main/java/avro/SMSResult.avsc
 create mode 100644 src/main/java/avro/apacheExample/ApacheExample.java
 create mode 100644 src/main/java/avro/apacheExample/Employee.avsc
 create mode 100644 src/main/java/avro/apacheExample/output.avro
 create mode 100644 src/main/java/avro/rfoldesExample/Employee.avsc
 create mode 100644 src/main/java/avro/rfoldesExample/Employee.java
 create mode 100644 src/main/java/avro/rfoldesExample/Employee2.avsc

diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..980360e
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,3 @@
+language: java
+
+script: mvn test -B
diff --git a/README.md b/README.md
index 207f2fd..3e18b42 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,7 @@
 # RandomJava
+[![Build Status](https://travis-ci.org/fishercoder1534/Leetcode.svg?branch=master)](https://travis-ci.org/fishercoder1534/Leetcode)
 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:
+File -> New -> Project from Version Control -> GitHub, then configure JDK8, then you'll fly with colors! ^ ^
diff --git a/pom.xml b/pom.xml
index 849935c..72ce814 100644
--- a/pom.xml
+++ b/pom.xml
@@ -112,6 +112,12 @@
             <version>1.5.0-b01</version>
         </dependency>
 
+        <dependency>
+            <groupId>org.apache.avro</groupId>
+            <artifactId>avro</artifactId>
+            <version>1.8.1</version>
+        </dependency>
+
     </dependencies>
 
     
diff --git a/src/main/java/avro/SMSResult.avsc b/src/main/java/avro/SMSResult.avsc
new file mode 100644
index 0000000..3e66843
--- /dev/null
+++ b/src/main/java/avro/SMSResult.avsc
@@ -0,0 +1,27 @@
+[
+{
+  "type": "record",
+  "name": "VendorItemInfo",
+  "fields": [
+      {"name": "vendorItemId", "type": "string"},
+      {"name": "price", "type": "long"},
+      {"name": "deliveryChargeType", "type": "string"}
+  ]
+},
+{
+  "type": "enum",
+  "name": "WriteType",
+  "symbols" : ["JSON", "AVRO"]
+},
+{
+  "type": "record",
+  "name": "SMSResult",
+  "fields": [
+      {"name": "writeType", "type": "WriteType"},
+      {"name": "numFound", "type": "int"},
+      {"name": "docs", "type": "string"},
+      {"name": "mainImagePath", "type": "string"},
+      {"name": "vendorItemInfos", "type": {"type": "array", "items": "VendorItemInfo"}}
+  ]
+}
+]
\ No newline at end of file
diff --git a/src/main/java/avro/apacheExample/ApacheExample.java b/src/main/java/avro/apacheExample/ApacheExample.java
new file mode 100644
index 0000000..b37d52c
--- /dev/null
+++ b/src/main/java/avro/apacheExample/ApacheExample.java
@@ -0,0 +1,52 @@
+package avro.apacheExample;
+
+import org.apache.avro.Schema;
+import org.apache.avro.file.DataFileReader;
+import org.apache.avro.file.DataFileWriter;
+import org.apache.avro.generic.GenericData;
+import org.apache.avro.generic.GenericDatumReader;
+import org.apache.avro.generic.GenericDatumWriter;
+import org.apache.avro.generic.GenericRecord;
+import org.apache.avro.io.DatumReader;
+import org.apache.avro.io.DatumWriter;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * Created by stevesun on 1/24/17.
+ */
+public class ApacheExample {
+    public static void main(String[] args) throws IOException {
+        Schema schema = new Schema.Parser().parse(new File("/Users/stevesun/personal_dev/RandomJava/src/main/java/avro/apacheExample/Employee.avsc"));
+        GenericRecord emp1 = new GenericData.Record(schema);
+        emp1.put("name", "Siva");
+        emp1.put("age", 45);
+
+        GenericRecord emp2 = new GenericData.Record(schema);
+        emp2.put("name", "Krish");
+        emp2.put("age", 28);
+
+        File file = new File("/Users/stevesun/personal_dev/RandomJava/src/main/java/avro/apacheExample/output.avro");
+        DatumWriter<GenericRecord> datumWriter = new GenericDatumWriter<GenericRecord>(schema);
+        DataFileWriter<GenericRecord> dataFileWriter = new DataFileWriter<GenericRecord>(datumWriter);
+        dataFileWriter.create(schema, file);
+        dataFileWriter.append(emp1);
+        dataFileWriter.append(emp2);
+        dataFileWriter.close();
+        System.out.println("Serialization finished.");
+
+        File fileToDeserialize = new File("/Users/stevesun/personal_dev/RandomJava/src/main/java/avro/apacheExample/output.avro");
+
+        DatumReader<GenericRecord> datumReader = new GenericDatumReader<GenericRecord>(schema);
+        DataFileReader<GenericRecord> dataFileReader = new DataFileReader<GenericRecord>(file, datumReader);
+
+        GenericRecord emp = new GenericData.Record(schema);
+        while (dataFileReader.hasNext()) {
+            emp = dataFileReader.next();
+            System.out.println(emp);
+        }
+
+        System.out.println("Program finished.");
+    }
+}
diff --git a/src/main/java/avro/apacheExample/Employee.avsc b/src/main/java/avro/apacheExample/Employee.avsc
new file mode 100644
index 0000000..5790674
--- /dev/null
+++ b/src/main/java/avro/apacheExample/Employee.avsc
@@ -0,0 +1,9 @@
+{
+  "type": "record",
+  "name": "Employee",
+  "fields": [
+      {"name": "name", "type": "string"},
+      {"name": "age", "type": "int"},
+      {"name": "boss", "type": ["Employee","null"]}
+  ]
+}
\ No newline at end of file
diff --git a/src/main/java/avro/apacheExample/output.avro b/src/main/java/avro/apacheExample/output.avro
new file mode 100644
index 0000000000000000000000000000000000000000..af3ef01389196e4f1ed777418a99880cd65cb322
GIT binary patch
diff --git a/src/main/java/avro/rfoldesExample/Employee.avsc b/src/main/java/avro/rfoldesExample/Employee.avsc
new file mode 100644
index 0000000..c2e609f
--- /dev/null
+++ b/src/main/java/avro/rfoldesExample/Employee.avsc
@@ -0,0 +1,10 @@
+{
+  "type": "record",
+  "name": "Employee",
+  "fields": [
+      {"name": "name", "type": "string"},
+      {"name": "age", "type": "int"},
+      {"name": "emails", "type": {"type": "array", "items": "string"}},
+      {"name": "boss", "type": ["Employee","null"]}
+  ]
+}
\ No newline at end of file
diff --git a/src/main/java/avro/rfoldesExample/Employee.java b/src/main/java/avro/rfoldesExample/Employee.java
new file mode 100644
index 0000000..2287ffe
--- /dev/null
+++ b/src/main/java/avro/rfoldesExample/Employee.java
@@ -0,0 +1,172 @@
+package avro.rfoldesExample;
+
+import org.apache.avro.Schema;
+import org.apache.avro.file.DataFileReader;
+import org.apache.avro.file.DataFileWriter;
+import org.apache.avro.generic.GenericData;
+import org.apache.avro.generic.GenericDatumReader;
+import org.apache.avro.generic.GenericDatumWriter;
+import org.apache.avro.io.Encoder;
+import org.apache.avro.io.EncoderFactory;
+import org.apache.avro.util.Utf8;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * Broken!!
+ *
+ * I copied this example from https://github.com/rfoldes/Avro-Test, but it throws NPE, so I filed an issue here: https://github.com/rfoldes/Avro-Test/issues/1
+ */
+public class Employee {
+    public static Schema SCHEMA;	//writer's schema
+    public static Schema SCHEMA2;	//reader's schema
+
+    static {
+        try {
+            InputStream is = Employee.class.getResourceAsStream("Employee.avsc");
+            SCHEMA = Schema.parse(is);
+            SCHEMA2 = Schema.parse(Employee.class.getResourceAsStream("Employee2.avsc"));
+        }
+        catch (IOException e)
+        {
+            System.out.println("Couldn't load a schema: "+e.getMessage());
+        }
+    }
+
+    private String name;
+    private int age;
+    private String[] mails;
+    private Employee boss;
+
+    public Employee(String name, int age, String[] emails, Employee b){
+        this.name = name;
+        this.age = age;
+        this.mails = emails;
+        this.boss = b;
+    }
+
+    /**
+     * This method serializes the java object into Avro record.
+     * @return Avro generic record
+     */
+    public GenericData.Record serialize() {
+        GenericData.Record record = new GenericData.Record(SCHEMA);
+
+        record.put("name", this.name);
+        record.put("age", this.age);
+
+
+        int nemails = (mails != null) ? this.mails.length : 0;
+        GenericData.Array emails = new GenericData.Array(nemails, SCHEMA.getField("emails").schema());
+        for (int i = 0; i < nemails; ++i)
+            emails.add(new Utf8(this.mails[i]));
+        record.put("emails", emails);
+
+        if (this.boss != null)
+            record.put("boss", this.boss.serialize());
+
+        return record;
+    }
+
+    /**
+     * Writes out Java objects into a binary Avro-encoded file
+     * @param file where to store serialized Avro records
+     * @param people is an array of objects to be serialized
+     * @throws IOException
+     */
+    public static void testWrite(File file, Employee[] people) throws IOException {
+        GenericDatumWriter datum = new GenericDatumWriter(Employee.SCHEMA);
+        DataFileWriter writer = new DataFileWriter(datum);
+
+        writer.setMeta("Meta-Key0", "Meta-Value0");
+        writer.setMeta("Meta-Key1", "Meta-Value1");
+
+        writer.create(Employee.SCHEMA, file);
+        for (Employee p : people)
+            writer.append(p.serialize());
+
+        writer.close();
+    }
+
+    /**
+     * Writes out Java objects into a JSON-encoded file
+     * @param file where to store serialized Avro records
+     * @param people people is an array of objects to be serialized
+     * @throws IOException
+     */
+    public static void testJsonWrite(File file, Employee[] people) throws IOException {
+        GenericDatumWriter writer = new GenericDatumWriter(Employee.SCHEMA);
+        Encoder e = EncoderFactory.get().jsonEncoder(Employee.SCHEMA, new FileOutputStream(file));
+
+        for (Employee p : people)
+            writer.write(p.serialize(), e);
+
+        e.flush();
+    }
+
+    /**
+     * Reads in binary Avro-encoded entities using the schema stored in the file and prints them out.
+     * @param file
+     * @throws IOException
+     */
+    public static void testRead(File file) throws IOException {
+        GenericDatumReader datum = new GenericDatumReader();
+        DataFileReader reader = new DataFileReader(file, datum);
+
+        GenericData.Record record = new GenericData.Record(reader.getSchema());
+        while (reader.hasNext()) {
+            reader.next(record);
+            System.out.println("Name " + record.get("name") +
+                    " Age " + record.get("age") +
+                    " @ "+record.get("emails"));
+        }
+
+        reader.close();
+    }
+
+    /**
+     * Reads in binary Avro-encoded entities using a schema that is different from the writer's schema.
+     * @param file
+     * @throws IOException
+     */
+    public static void testRead2(File file) throws IOException {
+        GenericDatumReader datum = new GenericDatumReader(Employee.SCHEMA2);
+        DataFileReader reader = new DataFileReader(file, datum);
+
+        GenericData.Record record = new GenericData.Record(Employee.SCHEMA2);
+        while (reader.hasNext()) {
+            reader.next(record);
+            System.out.println("Name " + record.get("name") +
+                    " " + record.get("yrs") + " yrs old " +
+                    " Gender " + record.get("gender") +
+                    " @ "+record.get("emails"));
+        }
+
+        reader.close();
+    }
+
+    public static void main(String[] args) {
+        Employee e1 = new Employee("Joe",31,new String[] {"joe@abc.com","joe@gmail.com"},null);
+        Employee e2 = new Employee("Jane",30,null,e1);
+        Employee e3 = new Employee("Zoe",21,null,e2);
+        Employee[] all = new Employee[] {e1,e2,e3};
+
+        File bf = new File("test.avro");
+        File jf = new File("test.json");
+
+        try {
+            testWrite(bf,all);
+            testRead(bf);
+            testRead2(bf);
+
+            testJsonWrite(jf,all);
+        }
+        catch (IOException e) {
+            System.out.println("Main: "+e.getMessage());
+        }
+    }
+
+}
diff --git a/src/main/java/avro/rfoldesExample/Employee2.avsc b/src/main/java/avro/rfoldesExample/Employee2.avsc
new file mode 100644
index 0000000..0483706
--- /dev/null
+++ b/src/main/java/avro/rfoldesExample/Employee2.avsc
@@ -0,0 +1,10 @@
+{
+  "type": "record",
+  "name": "Employee",
+  "fields": [
+      {"name": "name", "type": "string"},
+      {"name": "yrs", "type": "int", "aliases": ["age"]},
+      {"name": "gender", "type": "string", "default":"unknown"},
+      {"name": "emails", "type": {"type": "array", "items": "string"}}
+  ]
+}
\ No newline at end of file

From 8907b6b01156f745c38bd5d5a64d73bc4e7ebd7d Mon Sep 17 00:00:00 2001
From: Steve Sun <stevesun@coupang.com>
Date: Tue, 24 Jan 2017 16:46:17 -0800
Subject: [PATCH 023/185] [AVRO-0000] change travis script

---
 .travis.yml | 2 +-
 README.md   | 3 +--
 2 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index 980360e..f64f09a 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,3 +1,3 @@
 language: java
 
-script: mvn test -B
+script: mvn package
diff --git a/README.md b/README.md
index 3e18b42..dec5902 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,4 @@
-# RandomJava
-[![Build Status](https://travis-ci.org/fishercoder1534/Leetcode.svg?branch=master)](https://travis-ci.org/fishercoder1534/Leetcode)
+# RandomJava [![Build Status](https://travis-ci.org/fishercoder1534/RandomJava.svg?branch=master)](https://travis-ci.org/fishercoder1534/RandomJava)
 This is a Maven project containing a bunch of Random Java programs that I used, wrote from time to time.
 
 Build instructions:

From 36eb44d46a5b1ae04176d430b8dcef118b02d783 Mon Sep 17 00:00:00 2001
From: Steve Sun <stevesun@coupang.com>
Date: Tue, 24 Jan 2017 16:49:54 -0800
Subject: [PATCH 024/185] [AVRO-0000] change Java to 1.7

---
 pom.xml                                      |   4 ++--
 src/main/java/avro/apacheExample/output.avro | Bin 218 -> 218 bytes
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/pom.xml b/pom.xml
index 72ce814..cede47b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -8,8 +8,8 @@
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-compiler-plugin</artifactId>
                 <configuration>
-                    <source>1.8</source>
-                    <target>1.8</target>
+                    <source>1.7</source>
+                    <target>1.7</target>
                 </configuration>
             </plugin>
         </plugins>
diff --git a/src/main/java/avro/apacheExample/output.avro b/src/main/java/avro/apacheExample/output.avro
index af3ef01389196e4f1ed777418a99880cd65cb322..5a5e90073bef6aa4ecb5fb59798d0686c674d64e 100644
GIT binary patch

From ef67f1dbc71deb563a8145b570b5c9602d1420fc Mon Sep 17 00:00:00 2001
From: Steve Sun <stevesun@coupang.com>
Date: Wed, 25 Jan 2017 13:48:32 -0800
Subject: [PATCH 025/185] [AVRO-0000] remove unncessary files

---
 src/main/java/avro/SMSResult.avsc             | 27 -------------------
 .../avro/apacheExample/ApacheExample.java     |  1 +
 2 files changed, 1 insertion(+), 27 deletions(-)
 delete mode 100644 src/main/java/avro/SMSResult.avsc

diff --git a/src/main/java/avro/SMSResult.avsc b/src/main/java/avro/SMSResult.avsc
deleted file mode 100644
index 3e66843..0000000
--- a/src/main/java/avro/SMSResult.avsc
+++ /dev/null
@@ -1,27 +0,0 @@
-[
-{
-  "type": "record",
-  "name": "VendorItemInfo",
-  "fields": [
-      {"name": "vendorItemId", "type": "string"},
-      {"name": "price", "type": "long"},
-      {"name": "deliveryChargeType", "type": "string"}
-  ]
-},
-{
-  "type": "enum",
-  "name": "WriteType",
-  "symbols" : ["JSON", "AVRO"]
-},
-{
-  "type": "record",
-  "name": "SMSResult",
-  "fields": [
-      {"name": "writeType", "type": "WriteType"},
-      {"name": "numFound", "type": "int"},
-      {"name": "docs", "type": "string"},
-      {"name": "mainImagePath", "type": "string"},
-      {"name": "vendorItemInfos", "type": {"type": "array", "items": "VendorItemInfo"}}
-  ]
-}
-]
\ No newline at end of file
diff --git a/src/main/java/avro/apacheExample/ApacheExample.java b/src/main/java/avro/apacheExample/ApacheExample.java
index b37d52c..98b56dd 100644
--- a/src/main/java/avro/apacheExample/ApacheExample.java
+++ b/src/main/java/avro/apacheExample/ApacheExample.java
@@ -14,6 +14,7 @@
 import java.io.IOException;
 
 /**
+ * This code is credited to: http://hadooptutorial.info/avro-serializing-and-deserializing-example-java-api/
  * Created by stevesun on 1/24/17.
  */
 public class ApacheExample {

From 0166cfd46f465cd130d4612110eece09ceb38389 Mon Sep 17 00:00:00 2001
From: Steve Sun <stevesun@coupang.com>
Date: Sun, 29 Jan 2017 18:18:28 -0800
Subject: [PATCH 026/185] [JAVA-0000] move classes to root folder

---
 src/main/java/{sporadic => }/IO_example/JavaFileExample.java | 2 +-
 src/main/java/{sporadic => }/IO_example/JavaIOExample.java   | 2 +-
 .../AnotherSimpleTestCase.java                               | 2 +-
 .../Main.java                                                | 2 +-
 .../MyTestRunner.java                                        | 2 +-
 .../MyTestState.java                                         | 5 +++++
 .../SimpleTestCase.java                                      | 2 +-
 .../SteveSunFirstCustomAnnotation.java                       | 2 +-
 .../exceptionsCanBeSelfDefined/SteveSunException.java        | 2 +-
 .../UnderstandExceptionTryCatch.java                         | 2 +-
 .../java_async_method_example/async/method/AsyncClient.java  | 2 +-
 .../async/method/AsyncClientImpl.java                        | 2 +-
 .../java_async_method_example/async/method/MainApp.java      | 2 +-
 .../java_async_method_example/async/method/SyncClient.java   | 2 +-
 .../async/method/SyncClientImpl.java                         | 2 +-
 .../java_async_method_example/async/method/Task.java         | 2 +-
 .../java_async_method_example/future/MainApp.java            | 2 +-
 .../java_async_method_example/future/MyCallable.java         | 2 +-
 src/main/java/{sporadic => }/java_generics/GenericClass.java | 2 +-
 src/main/java/{sporadic => }/java_generics/MainApp.java      | 2 +-
 .../java/{sporadic => }/java_generics/NonGenericClass.java   | 2 +-
 src/main/java/{sporadic => }/java_generics/ParentClass.java  | 2 +-
 src/main/java/{sporadic => }/jsonExample/JsonDemoClass.java  | 2 +-
 .../{sporadic => }/jsonExample/JsonIgnoreAnnotationDemo.java | 2 +-
 .../java/{sporadic => }/method_invoke_and_reflect/Deet.java  | 2 +-
 .../producer_consumer_example/ProducerConsumerInJava.java    | 2 +-
 .../java/{sporadic => }/semaphore/ConnectionLimiter.java     | 2 +-
 .../{sporadic => }/socket_programming/GreetingClient.java    | 2 +-
 .../{sporadic => }/socket_programming/GreetingServer.java    | 2 +-
 src/main/java/{sporadic => }/sorting/HeapSort.java           | 2 +-
 src/main/java/{sporadic => }/sorting/HeapSortAgain.java      | 2 +-
 src/main/java/{sporadic => }/sorting/InsertionSort.java      | 2 +-
 src/main/java/{sporadic => }/sorting/MergeSort.java          | 2 +-
 src/main/java/{sporadic => }/sorting/QuickSort.java          | 2 +-
 .../MyTestState.java                                         | 5 -----
 src/main/java/{sporadic => }/thread/HusbandAndWifeJob.java   | 2 +-
 src/main/java/{sporadic => }/thread/ThreadIsCool.java        | 2 +-
 src/main/java/{sporadic => }/thread/ThreadLocalExample.java  | 2 +-
 .../synchronization/withSynchronization/TestThread.java      | 2 +-
 .../synchronization/withoutSynchronization/TestThread.java   | 2 +-
 40 files changed, 43 insertions(+), 43 deletions(-)
 rename src/main/java/{sporadic => }/IO_example/JavaFileExample.java (98%)
 rename src/main/java/{sporadic => }/IO_example/JavaIOExample.java (99%)
 rename src/main/java/{sporadic => }/customize_annotations_generics_wildcards_examples/AnotherSimpleTestCase.java (83%)
 rename src/main/java/{sporadic => }/customize_annotations_generics_wildcards_examples/Main.java (88%)
 rename src/main/java/{sporadic => }/customize_annotations_generics_wildcards_examples/MyTestRunner.java (96%)
 create mode 100644 src/main/java/customize_annotations_generics_wildcards_examples/MyTestState.java
 rename src/main/java/{sporadic => }/customize_annotations_generics_wildcards_examples/SimpleTestCase.java (89%)
 rename src/main/java/{sporadic => }/customize_annotations_generics_wildcards_examples/SteveSunFirstCustomAnnotation.java (88%)
 rename src/main/java/{sporadic => }/exceptionsCanBeSelfDefined/SteveSunException.java (93%)
 rename src/main/java/{sporadic => }/exceptionsCanBeSelfDefined/UnderstandExceptionTryCatch.java (97%)
 rename src/main/java/{sporadic => }/java_async_method_example/async/method/AsyncClient.java (66%)
 rename src/main/java/{sporadic => }/java_async_method_example/async/method/AsyncClientImpl.java (94%)
 rename src/main/java/{sporadic => }/java_async_method_example/async/method/MainApp.java (91%)
 rename src/main/java/{sporadic => }/java_async_method_example/async/method/SyncClient.java (65%)
 rename src/main/java/{sporadic => }/java_async_method_example/async/method/SyncClientImpl.java (94%)
 rename src/main/java/{sporadic => }/java_async_method_example/async/method/Task.java (85%)
 rename src/main/java/{sporadic => }/java_async_method_example/future/MainApp.java (97%)
 rename src/main/java/{sporadic => }/java_async_method_example/future/MyCallable.java (91%)
 rename src/main/java/{sporadic => }/java_generics/GenericClass.java (91%)
 rename src/main/java/{sporadic => }/java_generics/MainApp.java (93%)
 rename src/main/java/{sporadic => }/java_generics/NonGenericClass.java (88%)
 rename src/main/java/{sporadic => }/java_generics/ParentClass.java (92%)
 rename src/main/java/{sporadic => }/jsonExample/JsonDemoClass.java (98%)
 rename src/main/java/{sporadic => }/jsonExample/JsonIgnoreAnnotationDemo.java (97%)
 rename src/main/java/{sporadic => }/method_invoke_and_reflect/Deet.java (98%)
 rename src/main/java/{sporadic => }/producer_consumer_example/ProducerConsumerInJava.java (99%)
 rename src/main/java/{sporadic => }/semaphore/ConnectionLimiter.java (98%)
 rename src/main/java/{sporadic => }/socket_programming/GreetingClient.java (96%)
 rename src/main/java/{sporadic => }/socket_programming/GreetingServer.java (98%)
 rename src/main/java/{sporadic => }/sorting/HeapSort.java (98%)
 rename src/main/java/{sporadic => }/sorting/HeapSortAgain.java (98%)
 rename src/main/java/{sporadic => }/sorting/InsertionSort.java (98%)
 rename src/main/java/{sporadic => }/sorting/MergeSort.java (98%)
 rename src/main/java/{sporadic => }/sorting/QuickSort.java (99%)
 delete mode 100644 src/main/java/sporadic/customize_annotations_generics_wildcards_examples/MyTestState.java
 rename src/main/java/{sporadic => }/thread/HusbandAndWifeJob.java (98%)
 rename src/main/java/{sporadic => }/thread/ThreadIsCool.java (98%)
 rename src/main/java/{sporadic => }/thread/ThreadLocalExample.java (98%)
 rename src/main/java/{sporadic => }/thread/synchronization/withSynchronization/TestThread.java (98%)
 rename src/main/java/{sporadic => }/thread/synchronization/withoutSynchronization/TestThread.java (96%)

diff --git a/src/main/java/sporadic/IO_example/JavaFileExample.java b/src/main/java/IO_example/JavaFileExample.java
similarity index 98%
rename from src/main/java/sporadic/IO_example/JavaFileExample.java
rename to src/main/java/IO_example/JavaFileExample.java
index 7dfc651..bc4d2bf 100644
--- a/src/main/java/sporadic/IO_example/JavaFileExample.java
+++ b/src/main/java/IO_example/JavaFileExample.java
@@ -1,4 +1,4 @@
-package sporadic.IO_example;
+package IO_example;
 
 import java.io.File;
 
diff --git a/src/main/java/sporadic/IO_example/JavaIOExample.java b/src/main/java/IO_example/JavaIOExample.java
similarity index 99%
rename from src/main/java/sporadic/IO_example/JavaIOExample.java
rename to src/main/java/IO_example/JavaIOExample.java
index 260f108..3204c7d 100644
--- a/src/main/java/sporadic/IO_example/JavaIOExample.java
+++ b/src/main/java/IO_example/JavaIOExample.java
@@ -1,4 +1,4 @@
-package sporadic.IO_example;
+package IO_example;
 
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
diff --git a/src/main/java/sporadic/customize_annotations_generics_wildcards_examples/AnotherSimpleTestCase.java b/src/main/java/customize_annotations_generics_wildcards_examples/AnotherSimpleTestCase.java
similarity index 83%
rename from src/main/java/sporadic/customize_annotations_generics_wildcards_examples/AnotherSimpleTestCase.java
rename to src/main/java/customize_annotations_generics_wildcards_examples/AnotherSimpleTestCase.java
index 3a7d85c..7c27453 100644
--- a/src/main/java/sporadic/customize_annotations_generics_wildcards_examples/AnotherSimpleTestCase.java
+++ b/src/main/java/customize_annotations_generics_wildcards_examples/AnotherSimpleTestCase.java
@@ -1,4 +1,4 @@
-package sporadic.customize_annotations_generics_wildcards_examples;
+package customize_annotations_generics_wildcards_examples;
 
 
 public class AnotherSimpleTestCase {
diff --git a/src/main/java/sporadic/customize_annotations_generics_wildcards_examples/Main.java b/src/main/java/customize_annotations_generics_wildcards_examples/Main.java
similarity index 88%
rename from src/main/java/sporadic/customize_annotations_generics_wildcards_examples/Main.java
rename to src/main/java/customize_annotations_generics_wildcards_examples/Main.java
index 9889bfa..3e7beea 100644
--- a/src/main/java/sporadic/customize_annotations_generics_wildcards_examples/Main.java
+++ b/src/main/java/customize_annotations_generics_wildcards_examples/Main.java
@@ -1,4 +1,4 @@
-package sporadic.customize_annotations_generics_wildcards_examples;
+package customize_annotations_generics_wildcards_examples;
 
 import java.io.IOException;
 import java.util.ArrayList;
diff --git a/src/main/java/sporadic/customize_annotations_generics_wildcards_examples/MyTestRunner.java b/src/main/java/customize_annotations_generics_wildcards_examples/MyTestRunner.java
similarity index 96%
rename from src/main/java/sporadic/customize_annotations_generics_wildcards_examples/MyTestRunner.java
rename to src/main/java/customize_annotations_generics_wildcards_examples/MyTestRunner.java
index c57df00..20fafd0 100644
--- a/src/main/java/sporadic/customize_annotations_generics_wildcards_examples/MyTestRunner.java
+++ b/src/main/java/customize_annotations_generics_wildcards_examples/MyTestRunner.java
@@ -1,4 +1,4 @@
-package sporadic.customize_annotations_generics_wildcards_examples;
+package customize_annotations_generics_wildcards_examples;
 
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
diff --git a/src/main/java/customize_annotations_generics_wildcards_examples/MyTestState.java b/src/main/java/customize_annotations_generics_wildcards_examples/MyTestState.java
new file mode 100644
index 0000000..cb2f721
--- /dev/null
+++ b/src/main/java/customize_annotations_generics_wildcards_examples/MyTestState.java
@@ -0,0 +1,5 @@
+package customize_annotations_generics_wildcards_examples;
+
+public enum MyTestState {
+	ACTIVE, INACTIVE
+}
diff --git a/src/main/java/sporadic/customize_annotations_generics_wildcards_examples/SimpleTestCase.java b/src/main/java/customize_annotations_generics_wildcards_examples/SimpleTestCase.java
similarity index 89%
rename from src/main/java/sporadic/customize_annotations_generics_wildcards_examples/SimpleTestCase.java
rename to src/main/java/customize_annotations_generics_wildcards_examples/SimpleTestCase.java
index b2b9c95..7463570 100644
--- a/src/main/java/sporadic/customize_annotations_generics_wildcards_examples/SimpleTestCase.java
+++ b/src/main/java/customize_annotations_generics_wildcards_examples/SimpleTestCase.java
@@ -1,4 +1,4 @@
-package sporadic.customize_annotations_generics_wildcards_examples;
+package customize_annotations_generics_wildcards_examples;
 
 import org.junit.Assert;
 
diff --git a/src/main/java/sporadic/customize_annotations_generics_wildcards_examples/SteveSunFirstCustomAnnotation.java b/src/main/java/customize_annotations_generics_wildcards_examples/SteveSunFirstCustomAnnotation.java
similarity index 88%
rename from src/main/java/sporadic/customize_annotations_generics_wildcards_examples/SteveSunFirstCustomAnnotation.java
rename to src/main/java/customize_annotations_generics_wildcards_examples/SteveSunFirstCustomAnnotation.java
index da949a5..9847ada 100644
--- a/src/main/java/sporadic/customize_annotations_generics_wildcards_examples/SteveSunFirstCustomAnnotation.java
+++ b/src/main/java/customize_annotations_generics_wildcards_examples/SteveSunFirstCustomAnnotation.java
@@ -1,4 +1,4 @@
-package sporadic.customize_annotations_generics_wildcards_examples;
+package customize_annotations_generics_wildcards_examples;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.Target;
diff --git a/src/main/java/sporadic/exceptionsCanBeSelfDefined/SteveSunException.java b/src/main/java/exceptionsCanBeSelfDefined/SteveSunException.java
similarity index 93%
rename from src/main/java/sporadic/exceptionsCanBeSelfDefined/SteveSunException.java
rename to src/main/java/exceptionsCanBeSelfDefined/SteveSunException.java
index 761f309..ab8ecef 100644
--- a/src/main/java/sporadic/exceptionsCanBeSelfDefined/SteveSunException.java
+++ b/src/main/java/exceptionsCanBeSelfDefined/SteveSunException.java
@@ -1,4 +1,4 @@
-package sporadic.exceptionsCanBeSelfDefined;
+package exceptionsCanBeSelfDefined;
 
 /**
  * Base exception for all kinds of exceptions that I wrote myself for fun.
diff --git a/src/main/java/sporadic/exceptionsCanBeSelfDefined/UnderstandExceptionTryCatch.java b/src/main/java/exceptionsCanBeSelfDefined/UnderstandExceptionTryCatch.java
similarity index 97%
rename from src/main/java/sporadic/exceptionsCanBeSelfDefined/UnderstandExceptionTryCatch.java
rename to src/main/java/exceptionsCanBeSelfDefined/UnderstandExceptionTryCatch.java
index 8836b87..367208e 100644
--- a/src/main/java/sporadic/exceptionsCanBeSelfDefined/UnderstandExceptionTryCatch.java
+++ b/src/main/java/exceptionsCanBeSelfDefined/UnderstandExceptionTryCatch.java
@@ -1,4 +1,4 @@
-package sporadic.exceptionsCanBeSelfDefined;
+package exceptionsCanBeSelfDefined;
 
 /**
  * This is a simple program to help myself better understand what it really
diff --git a/src/main/java/sporadic/java_async_method_example/async/method/AsyncClient.java b/src/main/java/java_async_method_example/async/method/AsyncClient.java
similarity index 66%
rename from src/main/java/sporadic/java_async_method_example/async/method/AsyncClient.java
rename to src/main/java/java_async_method_example/async/method/AsyncClient.java
index 199abeb..6e1fe8f 100644
--- a/src/main/java/sporadic/java_async_method_example/async/method/AsyncClient.java
+++ b/src/main/java/java_async_method_example/async/method/AsyncClient.java
@@ -1,4 +1,4 @@
-package sporadic.java_async_method_example.async.method;
+package java_async_method_example.async.method;
 
 public interface AsyncClient {
 
diff --git a/src/main/java/sporadic/java_async_method_example/async/method/AsyncClientImpl.java b/src/main/java/java_async_method_example/async/method/AsyncClientImpl.java
similarity index 94%
rename from src/main/java/sporadic/java_async_method_example/async/method/AsyncClientImpl.java
rename to src/main/java/java_async_method_example/async/method/AsyncClientImpl.java
index 594e2c7..a466d99 100644
--- a/src/main/java/sporadic/java_async_method_example/async/method/AsyncClientImpl.java
+++ b/src/main/java/java_async_method_example/async/method/AsyncClientImpl.java
@@ -1,4 +1,4 @@
-package sporadic.java_async_method_example.async.method;
+package java_async_method_example.async.method;
 
 import java.util.ArrayList;
 import java.util.Date;
diff --git a/src/main/java/sporadic/java_async_method_example/async/method/MainApp.java b/src/main/java/java_async_method_example/async/method/MainApp.java
similarity index 91%
rename from src/main/java/sporadic/java_async_method_example/async/method/MainApp.java
rename to src/main/java/java_async_method_example/async/method/MainApp.java
index 1d90ed5..f8ad438 100644
--- a/src/main/java/sporadic/java_async_method_example/async/method/MainApp.java
+++ b/src/main/java/java_async_method_example/async/method/MainApp.java
@@ -1,4 +1,4 @@
-package sporadic.java_async_method_example.async.method;
+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!*/
diff --git a/src/main/java/sporadic/java_async_method_example/async/method/SyncClient.java b/src/main/java/java_async_method_example/async/method/SyncClient.java
similarity index 65%
rename from src/main/java/sporadic/java_async_method_example/async/method/SyncClient.java
rename to src/main/java/java_async_method_example/async/method/SyncClient.java
index 4b9a1c4..88ab87b 100644
--- a/src/main/java/sporadic/java_async_method_example/async/method/SyncClient.java
+++ b/src/main/java/java_async_method_example/async/method/SyncClient.java
@@ -1,4 +1,4 @@
-package sporadic.java_async_method_example.async.method;
+package java_async_method_example.async.method;
 
 public interface SyncClient {
 	// for synchronous
diff --git a/src/main/java/sporadic/java_async_method_example/async/method/SyncClientImpl.java b/src/main/java/java_async_method_example/async/method/SyncClientImpl.java
similarity index 94%
rename from src/main/java/sporadic/java_async_method_example/async/method/SyncClientImpl.java
rename to src/main/java/java_async_method_example/async/method/SyncClientImpl.java
index e74ded4..2dd400f 100644
--- a/src/main/java/sporadic/java_async_method_example/async/method/SyncClientImpl.java
+++ b/src/main/java/java_async_method_example/async/method/SyncClientImpl.java
@@ -1,4 +1,4 @@
-package sporadic.java_async_method_example.async.method;
+package java_async_method_example.async.method;
 
 import java.util.ArrayList;
 import java.util.Date;
diff --git a/src/main/java/sporadic/java_async_method_example/async/method/Task.java b/src/main/java/java_async_method_example/async/method/Task.java
similarity index 85%
rename from src/main/java/sporadic/java_async_method_example/async/method/Task.java
rename to src/main/java/java_async_method_example/async/method/Task.java
index 6d6732c..9517d41 100644
--- a/src/main/java/sporadic/java_async_method_example/async/method/Task.java
+++ b/src/main/java/java_async_method_example/async/method/Task.java
@@ -1,4 +1,4 @@
-package sporadic.java_async_method_example.async.method;
+package java_async_method_example.async.method;
 
 import java.util.concurrent.Callable;
 
diff --git a/src/main/java/sporadic/java_async_method_example/future/MainApp.java b/src/main/java/java_async_method_example/future/MainApp.java
similarity index 97%
rename from src/main/java/sporadic/java_async_method_example/future/MainApp.java
rename to src/main/java/java_async_method_example/future/MainApp.java
index b3201f1..cd94c55 100644
--- a/src/main/java/sporadic/java_async_method_example/future/MainApp.java
+++ b/src/main/java/java_async_method_example/future/MainApp.java
@@ -1,4 +1,4 @@
-package sporadic.java_async_method_example.future;
+package java_async_method_example.future;
 
 import java.util.ArrayList;
 import java.util.Date;
diff --git a/src/main/java/sporadic/java_async_method_example/future/MyCallable.java b/src/main/java/java_async_method_example/future/MyCallable.java
similarity index 91%
rename from src/main/java/sporadic/java_async_method_example/future/MyCallable.java
rename to src/main/java/java_async_method_example/future/MyCallable.java
index a2eebcc..2e9669d 100644
--- a/src/main/java/sporadic/java_async_method_example/future/MyCallable.java
+++ b/src/main/java/java_async_method_example/future/MyCallable.java
@@ -1,4 +1,4 @@
-package sporadic.java_async_method_example.future;
+package java_async_method_example.future;
 
 import java.util.concurrent.Callable;
 
diff --git a/src/main/java/sporadic/java_generics/GenericClass.java b/src/main/java/java_generics/GenericClass.java
similarity index 91%
rename from src/main/java/sporadic/java_generics/GenericClass.java
rename to src/main/java/java_generics/GenericClass.java
index 6d7c2ec..f118b97 100644
--- a/src/main/java/sporadic/java_generics/GenericClass.java
+++ b/src/main/java/java_generics/GenericClass.java
@@ -1,4 +1,4 @@
-package sporadic.java_generics;
+package java_generics;
 
 /**
  * This is a generic class that operates on objects of only T
diff --git a/src/main/java/sporadic/java_generics/MainApp.java b/src/main/java/java_generics/MainApp.java
similarity index 93%
rename from src/main/java/sporadic/java_generics/MainApp.java
rename to src/main/java/java_generics/MainApp.java
index 79fb69a..daa3213 100644
--- a/src/main/java/sporadic/java_generics/MainApp.java
+++ b/src/main/java/java_generics/MainApp.java
@@ -1,4 +1,4 @@
-package sporadic.java_generics;
+package java_generics;
 
 /**
  * Created by stevesun on 12/7/16.
diff --git a/src/main/java/sporadic/java_generics/NonGenericClass.java b/src/main/java/java_generics/NonGenericClass.java
similarity index 88%
rename from src/main/java/sporadic/java_generics/NonGenericClass.java
rename to src/main/java/java_generics/NonGenericClass.java
index ab7ee45..79013f0 100644
--- a/src/main/java/sporadic/java_generics/NonGenericClass.java
+++ b/src/main/java/java_generics/NonGenericClass.java
@@ -1,4 +1,4 @@
-package sporadic.java_generics;
+package java_generics;
 
 /**
  * This is a non-generic Box class that operates on objects of any type. */
diff --git a/src/main/java/sporadic/java_generics/ParentClass.java b/src/main/java/java_generics/ParentClass.java
similarity index 92%
rename from src/main/java/sporadic/java_generics/ParentClass.java
rename to src/main/java/java_generics/ParentClass.java
index d48b31a..d2be750 100644
--- a/src/main/java/sporadic/java_generics/ParentClass.java
+++ b/src/main/java/java_generics/ParentClass.java
@@ -1,4 +1,4 @@
-package sporadic.java_generics;
+package java_generics;
 
 public class ParentClass {
 
diff --git a/src/main/java/sporadic/jsonExample/JsonDemoClass.java b/src/main/java/jsonExample/JsonDemoClass.java
similarity index 98%
rename from src/main/java/sporadic/jsonExample/JsonDemoClass.java
rename to src/main/java/jsonExample/JsonDemoClass.java
index f536c43..bfa4687 100644
--- a/src/main/java/sporadic/jsonExample/JsonDemoClass.java
+++ b/src/main/java/jsonExample/JsonDemoClass.java
@@ -1,4 +1,4 @@
-package sporadic.jsonExample;
+package jsonExample;
 
 import org.codehaus.jackson.annotate.JsonIgnore;
 import org.codehaus.jackson.annotate.JsonIgnoreProperties;
diff --git a/src/main/java/sporadic/jsonExample/JsonIgnoreAnnotationDemo.java b/src/main/java/jsonExample/JsonIgnoreAnnotationDemo.java
similarity index 97%
rename from src/main/java/sporadic/jsonExample/JsonIgnoreAnnotationDemo.java
rename to src/main/java/jsonExample/JsonIgnoreAnnotationDemo.java
index 9a88e68..dcaa97f 100644
--- a/src/main/java/sporadic/jsonExample/JsonIgnoreAnnotationDemo.java
+++ b/src/main/java/jsonExample/JsonIgnoreAnnotationDemo.java
@@ -1,4 +1,4 @@
-package sporadic.jsonExample;
+package jsonExample;
 
 import java.io.IOException;
 
diff --git a/src/main/java/sporadic/method_invoke_and_reflect/Deet.java b/src/main/java/method_invoke_and_reflect/Deet.java
similarity index 98%
rename from src/main/java/sporadic/method_invoke_and_reflect/Deet.java
rename to src/main/java/method_invoke_and_reflect/Deet.java
index 99d4a6f..b60e286 100644
--- a/src/main/java/sporadic/method_invoke_and_reflect/Deet.java
+++ b/src/main/java/method_invoke_and_reflect/Deet.java
@@ -1,4 +1,4 @@
-package sporadic.method_invoke_and_reflect;
+package method_invoke_and_reflect;
 
 import static java.lang.System.err;
 import static java.lang.System.out;
diff --git a/src/main/java/sporadic/producer_consumer_example/ProducerConsumerInJava.java b/src/main/java/producer_consumer_example/ProducerConsumerInJava.java
similarity index 99%
rename from src/main/java/sporadic/producer_consumer_example/ProducerConsumerInJava.java
rename to src/main/java/producer_consumer_example/ProducerConsumerInJava.java
index c9cc3f4..e7c45c3 100644
--- a/src/main/java/sporadic/producer_consumer_example/ProducerConsumerInJava.java
+++ b/src/main/java/producer_consumer_example/ProducerConsumerInJava.java
@@ -1,7 +1,7 @@
 /**
  * 
  */
-package sporadic.producer_consumer_example;
+package producer_consumer_example;
 
 import java.util.LinkedList;
 import java.util.Queue;
diff --git a/src/main/java/sporadic/semaphore/ConnectionLimiter.java b/src/main/java/semaphore/ConnectionLimiter.java
similarity index 98%
rename from src/main/java/sporadic/semaphore/ConnectionLimiter.java
rename to src/main/java/semaphore/ConnectionLimiter.java
index 3f048c1..d3b8c6e 100644
--- a/src/main/java/sporadic/semaphore/ConnectionLimiter.java
+++ b/src/main/java/semaphore/ConnectionLimiter.java
@@ -1,4 +1,4 @@
-package sporadic.semaphore;
+package semaphore;
 
 import java.util.concurrent.Semaphore;
 
diff --git a/src/main/java/sporadic/socket_programming/GreetingClient.java b/src/main/java/socket_programming/GreetingClient.java
similarity index 96%
rename from src/main/java/sporadic/socket_programming/GreetingClient.java
rename to src/main/java/socket_programming/GreetingClient.java
index 852dabf..ee2760b 100644
--- a/src/main/java/sporadic/socket_programming/GreetingClient.java
+++ b/src/main/java/socket_programming/GreetingClient.java
@@ -1,4 +1,4 @@
-package sporadic.socket_programming;
+package socket_programming;
 
 import java.io.DataInputStream;
 import java.io.DataOutputStream;
diff --git a/src/main/java/sporadic/socket_programming/GreetingServer.java b/src/main/java/socket_programming/GreetingServer.java
similarity index 98%
rename from src/main/java/sporadic/socket_programming/GreetingServer.java
rename to src/main/java/socket_programming/GreetingServer.java
index 49dc5e2..8501c86 100644
--- a/src/main/java/sporadic/socket_programming/GreetingServer.java
+++ b/src/main/java/socket_programming/GreetingServer.java
@@ -1,4 +1,4 @@
-package sporadic.socket_programming;
+package socket_programming;
 
 import java.io.DataInputStream;
 import java.io.DataOutputStream;
diff --git a/src/main/java/sporadic/sorting/HeapSort.java b/src/main/java/sorting/HeapSort.java
similarity index 98%
rename from src/main/java/sporadic/sorting/HeapSort.java
rename to src/main/java/sorting/HeapSort.java
index a394cc2..1e493af 100644
--- a/src/main/java/sporadic/sorting/HeapSort.java
+++ b/src/main/java/sorting/HeapSort.java
@@ -1,4 +1,4 @@
-package sporadic.sorting;
+package sorting;
 
 public class HeapSort {
 	private static int N;
diff --git a/src/main/java/sporadic/sorting/HeapSortAgain.java b/src/main/java/sorting/HeapSortAgain.java
similarity index 98%
rename from src/main/java/sporadic/sorting/HeapSortAgain.java
rename to src/main/java/sorting/HeapSortAgain.java
index 88c3c29..272b97b 100644
--- a/src/main/java/sporadic/sorting/HeapSortAgain.java
+++ b/src/main/java/sorting/HeapSortAgain.java
@@ -1,4 +1,4 @@
-package sporadic.sorting;
+package sorting;
 
 /**After completing understanding this algorithm, I implemented myself, so this class is called HeapSortAgain.*/
 public class HeapSortAgain {
diff --git a/src/main/java/sporadic/sorting/InsertionSort.java b/src/main/java/sorting/InsertionSort.java
similarity index 98%
rename from src/main/java/sporadic/sorting/InsertionSort.java
rename to src/main/java/sorting/InsertionSort.java
index 80aaa83..90041ea 100644
--- a/src/main/java/sporadic/sorting/InsertionSort.java
+++ b/src/main/java/sorting/InsertionSort.java
@@ -1,4 +1,4 @@
-package sporadic.sorting;
+package sorting;
 
 import java.util.Random;
 
diff --git a/src/main/java/sporadic/sorting/MergeSort.java b/src/main/java/sorting/MergeSort.java
similarity index 98%
rename from src/main/java/sporadic/sorting/MergeSort.java
rename to src/main/java/sorting/MergeSort.java
index ea22303..18adafb 100644
--- a/src/main/java/sporadic/sorting/MergeSort.java
+++ b/src/main/java/sorting/MergeSort.java
@@ -1,4 +1,4 @@
-package sporadic.sorting;
+package sorting;
 
 public class MergeSort {
 	public static void main(String...strings){
diff --git a/src/main/java/sporadic/sorting/QuickSort.java b/src/main/java/sorting/QuickSort.java
similarity index 99%
rename from src/main/java/sporadic/sorting/QuickSort.java
rename to src/main/java/sorting/QuickSort.java
index 53b7591..4e8c314 100644
--- a/src/main/java/sporadic/sorting/QuickSort.java
+++ b/src/main/java/sorting/QuickSort.java
@@ -1,4 +1,4 @@
-package sporadic.sorting;
+package sorting;
 
 public class QuickSort {
 	public int[] quickSort(int[] nums){
diff --git a/src/main/java/sporadic/customize_annotations_generics_wildcards_examples/MyTestState.java b/src/main/java/sporadic/customize_annotations_generics_wildcards_examples/MyTestState.java
deleted file mode 100644
index 113a571..0000000
--- a/src/main/java/sporadic/customize_annotations_generics_wildcards_examples/MyTestState.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package sporadic.customize_annotations_generics_wildcards_examples;
-
-public enum MyTestState {
-	ACTIVE, INACTIVE
-}
diff --git a/src/main/java/sporadic/thread/HusbandAndWifeJob.java b/src/main/java/thread/HusbandAndWifeJob.java
similarity index 98%
rename from src/main/java/sporadic/thread/HusbandAndWifeJob.java
rename to src/main/java/thread/HusbandAndWifeJob.java
index 6664f9c..4beea81 100644
--- a/src/main/java/sporadic/thread/HusbandAndWifeJob.java
+++ b/src/main/java/thread/HusbandAndWifeJob.java
@@ -1,4 +1,4 @@
-package sporadic.thread;
+package thread;
 
 public class HusbandAndWifeJob implements Runnable {
 
diff --git a/src/main/java/sporadic/thread/ThreadIsCool.java b/src/main/java/thread/ThreadIsCool.java
similarity index 98%
rename from src/main/java/sporadic/thread/ThreadIsCool.java
rename to src/main/java/thread/ThreadIsCool.java
index d2a78c7..6f677dc 100644
--- a/src/main/java/sporadic/thread/ThreadIsCool.java
+++ b/src/main/java/thread/ThreadIsCool.java
@@ -1,4 +1,4 @@
-package sporadic.thread;
+package thread;
 
 /** 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.*/
diff --git a/src/main/java/sporadic/thread/ThreadLocalExample.java b/src/main/java/thread/ThreadLocalExample.java
similarity index 98%
rename from src/main/java/sporadic/thread/ThreadLocalExample.java
rename to src/main/java/thread/ThreadLocalExample.java
index 3fba541..9a1b6f1 100644
--- a/src/main/java/sporadic/thread/ThreadLocalExample.java
+++ b/src/main/java/thread/ThreadLocalExample.java
@@ -1,4 +1,4 @@
-package sporadic.thread;
+package thread;
 
 /**
  * The ThreadLocal class in Java enables you to create variables that can only
diff --git a/src/main/java/sporadic/thread/synchronization/withSynchronization/TestThread.java b/src/main/java/thread/synchronization/withSynchronization/TestThread.java
similarity index 98%
rename from src/main/java/sporadic/thread/synchronization/withSynchronization/TestThread.java
rename to src/main/java/thread/synchronization/withSynchronization/TestThread.java
index cb81460..680fbfc 100644
--- a/src/main/java/sporadic/thread/synchronization/withSynchronization/TestThread.java
+++ b/src/main/java/thread/synchronization/withSynchronization/TestThread.java
@@ -1,7 +1,7 @@
 /**
  * 
  */
-package sporadic.thread.synchronization.withSynchronization;
+package thread.synchronization.withSynchronization;
 
 /**
  * This produces the SAME result every time you run this program, in contrast to
diff --git a/src/main/java/sporadic/thread/synchronization/withoutSynchronization/TestThread.java b/src/main/java/thread/synchronization/withoutSynchronization/TestThread.java
similarity index 96%
rename from src/main/java/sporadic/thread/synchronization/withoutSynchronization/TestThread.java
rename to src/main/java/thread/synchronization/withoutSynchronization/TestThread.java
index e71367f..76ec63f 100644
--- a/src/main/java/sporadic/thread/synchronization/withoutSynchronization/TestThread.java
+++ b/src/main/java/thread/synchronization/withoutSynchronization/TestThread.java
@@ -1,7 +1,7 @@
 /**
  * 
  */
-package sporadic.thread.synchronization.withoutSynchronization;
+package thread.synchronization.withoutSynchronization;
 
 /**
  * @author jiahuan

From 9fac05410c8b639e9ddb069f64094dc250972bf8 Mon Sep 17 00:00:00 2001
From: Steve Sun <stevesun@coupang.com>
Date: Sun, 29 Jan 2017 19:50:10 -0800
Subject: [PATCH 027/185] [JAVA-0000] more thread examples

---
 .gitignore                                    |  7 ++
 .../HusbandAndWifeJob.java                    |  2 +-
 .../{thread => multithread}/ThreadIsCool.java | 26 +++----
 .../ThreadLocalExample.java                   |  2 +-
 src/main/java/multithread/Worker.java         | 61 ++++++++++++++++
 .../withSynchronization/TestThread.java       |  2 +-
 .../withoutSynchronization/TestThread.java    | 67 +++++++++++++++++
 .../ProducerConsumerInJava.java               |  3 -
 .../withoutSynchronization/TestThread.java    | 73 -------------------
 9 files changed, 151 insertions(+), 92 deletions(-)
 create mode 100644 .gitignore
 rename src/main/java/{thread => multithread}/HusbandAndWifeJob.java (99%)
 rename src/main/java/{thread => multithread}/ThreadIsCool.java (75%)
 rename src/main/java/{thread => multithread}/ThreadLocalExample.java (98%)
 create mode 100644 src/main/java/multithread/Worker.java
 rename src/main/java/{thread => multithread}/synchronization/withSynchronization/TestThread.java (98%)
 create mode 100644 src/main/java/multithread/synchronization/withoutSynchronization/TestThread.java
 delete mode 100644 src/main/java/thread/synchronization/withoutSynchronization/TestThread.java

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..1df76d8
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,7 @@
+# Created by .ignore support plugin (hsz.mobi)
+*.iml
+*.idea
+*.class
+out/
+target/
+
diff --git a/src/main/java/thread/HusbandAndWifeJob.java b/src/main/java/multithread/HusbandAndWifeJob.java
similarity index 99%
rename from src/main/java/thread/HusbandAndWifeJob.java
rename to src/main/java/multithread/HusbandAndWifeJob.java
index 4beea81..44e8dab 100644
--- a/src/main/java/thread/HusbandAndWifeJob.java
+++ b/src/main/java/multithread/HusbandAndWifeJob.java
@@ -1,4 +1,4 @@
-package thread;
+package multithread;
 
 public class HusbandAndWifeJob implements Runnable {
 
diff --git a/src/main/java/thread/ThreadIsCool.java b/src/main/java/multithread/ThreadIsCool.java
similarity index 75%
rename from src/main/java/thread/ThreadIsCool.java
rename to src/main/java/multithread/ThreadIsCool.java
index 6f677dc..f3d97b8 100644
--- a/src/main/java/thread/ThreadIsCool.java
+++ b/src/main/java/multithread/ThreadIsCool.java
@@ -1,4 +1,4 @@
-package thread;
+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.*/
@@ -7,32 +7,32 @@ public class ThreadIsCool implements Runnable{
 
 	public static void main(String [] args){
 		ThreadIsCool threadIsCool = new ThreadIsCool();
-		Thread abc = new Thread(threadIsCool);
-		Thread def = new Thread(threadIsCool);
-		Thread ghi = new Thread(threadIsCool);
-		abc.setName("abc");
-		def.setName("def");
-		ghi.setName("ghi");
+		Thread thread1 = new Thread(threadIsCool);
+		Thread thread2 = new Thread(threadIsCool);
+		Thread thread3 = new Thread(threadIsCool);
+		thread1.setName("abc");
+		thread2.setName("def");
+		thread3.setName("ghi");
 		System.out.println("Now the three threads kick off:");
 		
-		abc.start();
+		thread1.start();
 		try {
 		    /* Start second thread(def) only when first thread(abc) is dead*/
-            abc.join();
+            thread1.join();
         } catch (InterruptedException e) {
             e.printStackTrace();
         }
 		
-		def.start();
+		thread2.start();
 		try {
-            def.join();
+            thread2.join();
         } catch (InterruptedException e) {
             e.printStackTrace();
         }
 		
-		ghi.start();
+		thread3.start();
 		try {
-            ghi.join();
+            thread3.join();
         } catch (InterruptedException e) {
             e.printStackTrace();
         }
diff --git a/src/main/java/thread/ThreadLocalExample.java b/src/main/java/multithread/ThreadLocalExample.java
similarity index 98%
rename from src/main/java/thread/ThreadLocalExample.java
rename to src/main/java/multithread/ThreadLocalExample.java
index 9a1b6f1..2a1d687 100644
--- a/src/main/java/thread/ThreadLocalExample.java
+++ b/src/main/java/multithread/ThreadLocalExample.java
@@ -1,4 +1,4 @@
-package thread;
+package multithread;
 
 /**
  * The ThreadLocal class in Java enables you to create variables that can only
diff --git a/src/main/java/multithread/Worker.java b/src/main/java/multithread/Worker.java
new file mode 100644
index 0000000..a791231
--- /dev/null
+++ b/src/main/java/multithread/Worker.java
@@ -0,0 +1,61 @@
+package multithread;
+
+import sun.jvm.hotspot.debugger.ThreadAccess;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * Created by stevesun on 1/29/17.
+ */
+public class Worker implements Runnable {
+    public boolean running = false;
+
+    public static void main(String... args) throws InterruptedException {
+        Worker mainThreadWorker = new Worker();
+        List<Thread> workers = new ArrayList<>();
+
+        System.out.println("Main thread is running with thread ID: " + Thread.currentThread().getId());
+
+        Date start = new Date();
+
+        //let's start 10 workers
+        for (int i = 0; i < 10; i++){
+            System.out.println("i = " + i);
+            Thread thread = new Thread(mainThreadWorker);
+            workers.add(thread);
+            thread.start();
+        }
+
+        //now we need to force the MAIN thread to wait until all Worker threads end, so we could calculate the duration
+        for (Thread worker : workers){
+            System.out.println("Checking thread " + worker.currentThread().getId() + " now.");
+            System.out.println("worker.isAlive() = " + worker.isAlive());
+            while (worker.isAlive()){
+                Thread.sleep(1000);
+            }
+        }
+
+        Date end = new Date();
+
+        Long duration = end.getTime() - start.getTime();
+
+        System.out.println("This whole process took " + duration/1000 + " seconds.");
+    }
+
+    @Override
+    public void run() {
+        this.running = true;
+        System.out.println("Thread " + Thread.currentThread().getId() + " is running.");
+
+        try {
+            //this pauses this spawned thread to sleep for 5 seconds.
+            Thread.sleep(5000);
+        } catch (InterruptedException e) {
+            //an InterruptedException should never be swallowed
+            Thread.currentThread().interrupt();
+        }
+        this.running = false;
+    }
+}
diff --git a/src/main/java/thread/synchronization/withSynchronization/TestThread.java b/src/main/java/multithread/synchronization/withSynchronization/TestThread.java
similarity index 98%
rename from src/main/java/thread/synchronization/withSynchronization/TestThread.java
rename to src/main/java/multithread/synchronization/withSynchronization/TestThread.java
index 680fbfc..819269c 100644
--- a/src/main/java/thread/synchronization/withSynchronization/TestThread.java
+++ b/src/main/java/multithread/synchronization/withSynchronization/TestThread.java
@@ -1,7 +1,7 @@
 /**
  * 
  */
-package thread.synchronization.withSynchronization;
+package multithread.synchronization.withSynchronization;
 
 /**
  * This produces the SAME result every time you run this program, in contrast to
diff --git a/src/main/java/multithread/synchronization/withoutSynchronization/TestThread.java b/src/main/java/multithread/synchronization/withoutSynchronization/TestThread.java
new file mode 100644
index 0000000..4d00263
--- /dev/null
+++ b/src/main/java/multithread/synchronization/withoutSynchronization/TestThread.java
@@ -0,0 +1,67 @@
+package multithread.synchronization.withoutSynchronization;
+
+/**
+ * This produces DIFFERENT result every time you run this program, in contrast to the one with synchronization.
+ * Here is a simple example which may or may not print counter value in sequence and every time we run it, it produces different result based on CPU availability to a thread.
+ * Copied from this link: http://www.tutorialspoint.com/java/java_thread_synchronization.htm, refer to this link for further info.
+ */
+public class TestThread {
+    public static void main(String args[]) {
+
+        PrintDemo PD = new PrintDemo();
+
+        ThreadDemo T1 = new ThreadDemo("Thread - 1 ", PD);
+        ThreadDemo T2 = new ThreadDemo("Thread - 2 ", PD);
+
+        T1.start();
+        T2.start();
+
+        // wait for threads to end
+        try {
+            T1.join();
+            T2.join();
+        } catch (Exception e) {
+            System.out.println("Interrupted");
+        }
+    }
+
+}
+
+
+class PrintDemo {
+    public void printCount() {
+        try {
+            for (int i = 5; i > 0; i--) {
+                System.out.println("Counter   ---   " + i);
+            }
+        } catch (Exception e) {
+            System.out.println("Thread  interrupted.");
+        }
+    }
+
+}
+
+class ThreadDemo extends Thread {
+    private Thread t;
+    private String threadName;
+    PrintDemo PD;
+
+    ThreadDemo(String name, PrintDemo pd) {
+        threadName = name;
+        PD = pd;
+    }
+
+    public void run() {
+        PD.printCount();
+        System.out.println("Thread " + threadName + " exiting.");
+    }
+
+    public void start() {
+        System.out.println("Starting " + threadName);
+        if (t == null) {
+            t = new Thread(this, threadName);
+            t.start();
+        }
+    }
+
+}
diff --git a/src/main/java/producer_consumer_example/ProducerConsumerInJava.java b/src/main/java/producer_consumer_example/ProducerConsumerInJava.java
index e7c45c3..fec4209 100644
--- a/src/main/java/producer_consumer_example/ProducerConsumerInJava.java
+++ b/src/main/java/producer_consumer_example/ProducerConsumerInJava.java
@@ -1,6 +1,3 @@
-/**
- * 
- */
 package producer_consumer_example;
 
 import java.util.LinkedList;
diff --git a/src/main/java/thread/synchronization/withoutSynchronization/TestThread.java b/src/main/java/thread/synchronization/withoutSynchronization/TestThread.java
deleted file mode 100644
index 76ec63f..0000000
--- a/src/main/java/thread/synchronization/withoutSynchronization/TestThread.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/**
- * 
- */
-package thread.synchronization.withoutSynchronization;
-
-/**
- * @author jiahuan
- * This produces DIFFERENT result every time you run this program, in contrast to the one with synchronization.
- * Here is a simple example which may or may not print counter value in sequence and every time we run it, it produces different result based on CPU availability to a thread.
- * Copied from this link: http://www.tutorialspoint.com/java/java_thread_synchronization.htm, refer to this link for further info.
- * 
- */
-public class TestThread {
-	public static void main(String args[]) {
-
-	      PrintDemo PD = new PrintDemo();
-
-	      ThreadDemo T1 = new ThreadDemo( "Thread - 1 ", PD );
-	      ThreadDemo T2 = new ThreadDemo( "Thread - 2 ", PD );
-
-	      T1.start();
-	      T2.start();
-
-	      // wait for threads to end
-	      try {
-	         T1.join();
-	         T2.join();
-	      } catch( Exception e) {
-	         System.out.println("Interrupted");
-	      }
-	   }
-
-}
-
-
-class PrintDemo {
-	   public void printCount(){
-	    try {
-	         for(int i = 5; i > 0; i--) {
-	            System.out.println("Counter   ---   "  + i );
-	         }
-	     } catch (Exception e) {
-	         System.out.println("Thread  interrupted.");
-	     }
-	   }
-
-	}
-
-	class ThreadDemo extends Thread {
-	   private Thread t;
-	   private String threadName;
-	   PrintDemo  PD;
-
-	   ThreadDemo( String name,  PrintDemo pd){
-	       threadName = name;
-	        PD = pd;
-	   }
-	   public void run() {
-	     PD.printCount();
-	     System.out.println("Thread " +  threadName + " exiting.");
-	   }
-
-	   public void start ()
-	   {
-	      System.out.println("Starting " +  threadName );
-	      if (t == null)
-	      {
-	         t = new Thread (this, threadName);
-	         t.start ();
-	      }
-	   }
-
-	}

From 4335516b1e2b9c5e2ad99cd633830ee803766d99 Mon Sep 17 00:00:00 2001
From: Steve Sun <stevesun@coupang.com>
Date: Sun, 29 Jan 2017 19:55:00 -0800
Subject: [PATCH 028/185] [JAVA-0000] remove unused import

---
 src/main/java/multithread/Worker.java | 2 --
 1 file changed, 2 deletions(-)

diff --git a/src/main/java/multithread/Worker.java b/src/main/java/multithread/Worker.java
index a791231..3797c4c 100644
--- a/src/main/java/multithread/Worker.java
+++ b/src/main/java/multithread/Worker.java
@@ -1,7 +1,5 @@
 package multithread;
 
-import sun.jvm.hotspot.debugger.ThreadAccess;
-
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;

From 930ef2619cc2dc6d4aed5b3dd9db54d7e2908871 Mon Sep 17 00:00:00 2001
From: stevesun <stevesun@coupang.com>
Date: Sun, 16 Apr 2017 15:34:57 -0700
Subject: [PATCH 029/185] add Java 8 tutorials

---
 pom.xml                                         |  4 ++--
 .../defaultMethodsForInterfaces/Formula.java    | 12 ++++++++++++
 .../FormulaImpl.java                            | 17 +++++++++++++++++
 src/main/java/sorting/BucketSort.java           |  7 +++++++
 src/main/java/sorting/RadixSort.java            |  7 +++++++
 5 files changed, 45 insertions(+), 2 deletions(-)
 create mode 100644 src/main/java/java8tutorials/defaultMethodsForInterfaces/Formula.java
 create mode 100644 src/main/java/java8tutorials/defaultMethodsForInterfaces/FormulaImpl.java
 create mode 100644 src/main/java/sorting/BucketSort.java
 create mode 100644 src/main/java/sorting/RadixSort.java

diff --git a/pom.xml b/pom.xml
index cede47b..72ce814 100644
--- a/pom.xml
+++ b/pom.xml
@@ -8,8 +8,8 @@
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-compiler-plugin</artifactId>
                 <configuration>
-                    <source>1.7</source>
-                    <target>1.7</target>
+                    <source>1.8</source>
+                    <target>1.8</target>
                 </configuration>
             </plugin>
         </plugins>
diff --git a/src/main/java/java8tutorials/defaultMethodsForInterfaces/Formula.java b/src/main/java/java8tutorials/defaultMethodsForInterfaces/Formula.java
new file mode 100644
index 0000000..4db6c64
--- /dev/null
+++ b/src/main/java/java8tutorials/defaultMethodsForInterfaces/Formula.java
@@ -0,0 +1,12 @@
+package java8tutorials.defaultMethodsForInterfaces;
+
+/**
+ * Created by stevesun on 4/16/17.
+ */
+public interface Formula {
+    double calculate(int a);
+
+    default double sqrt(int a) {
+        return Math.sqrt(a);
+    }
+}
diff --git a/src/main/java/java8tutorials/defaultMethodsForInterfaces/FormulaImpl.java b/src/main/java/java8tutorials/defaultMethodsForInterfaces/FormulaImpl.java
new file mode 100644
index 0000000..27dccdb
--- /dev/null
+++ b/src/main/java/java8tutorials/defaultMethodsForInterfaces/FormulaImpl.java
@@ -0,0 +1,17 @@
+package java8tutorials.defaultMethodsForInterfaces;
+
+/**
+ * Created by stevesun on 4/16/17.
+ */
+public class FormulaImpl implements Formula {
+    @Override
+    public double calculate(int a) {
+        return sqrt(a*100);
+    }
+
+    public static void main(String... args) {
+        Formula formula = new FormulaImpl();
+        System.out.println(formula.sqrt(16));
+        System.out.println(formula.calculate(100));
+    }
+}
diff --git a/src/main/java/sorting/BucketSort.java b/src/main/java/sorting/BucketSort.java
new file mode 100644
index 0000000..00cac8c
--- /dev/null
+++ b/src/main/java/sorting/BucketSort.java
@@ -0,0 +1,7 @@
+package sorting;
+
+/**
+ * Created by stevesun on 2/18/17.
+ */
+public class BucketSort {
+}
diff --git a/src/main/java/sorting/RadixSort.java b/src/main/java/sorting/RadixSort.java
new file mode 100644
index 0000000..9f8ee91
--- /dev/null
+++ b/src/main/java/sorting/RadixSort.java
@@ -0,0 +1,7 @@
+package sorting;
+
+/**
+ * Created by stevesun on 2/18/17.
+ */
+public class RadixSort {
+}

From daa1e76cec1de0919d12803a5c4b95b537d90703 Mon Sep 17 00:00:00 2001
From: stevesun <stevesun@coupang.com>
Date: Sun, 16 Apr 2017 17:34:00 -0700
Subject: [PATCH 030/185] lamda expressions

---
 .../lamdaExpressions/LamdaDemo.java           | 94 +++++++++++++++++++
 1 file changed, 94 insertions(+)
 create mode 100644 src/main/java/java8tutorials/lamdaExpressions/LamdaDemo.java

diff --git a/src/main/java/java8tutorials/lamdaExpressions/LamdaDemo.java b/src/main/java/java8tutorials/lamdaExpressions/LamdaDemo.java
new file mode 100644
index 0000000..e4c54c5
--- /dev/null
+++ b/src/main/java/java8tutorials/lamdaExpressions/LamdaDemo.java
@@ -0,0 +1,94 @@
+package java8tutorials.lamdaExpressions;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+/**
+ * Created by stevesun on 4/16/17.
+ */
+public class LamdaDemo {
+    public static void sortInPreJava8() {
+        List<Person> names = Arrays.asList(new Person("Sophie", 27), new Person("Ada", 1),
+                new Person("Steve", 28), new Person("Eason", 26), new Person("Jenny", 31));
+
+        print(names, "Prior to sort: ");
+
+        Collections.sort(names, new Comparator<Person>() {
+            @Override
+            public int compare(Person o1, Person o2) {
+                return o1.age - o2.age;
+            }
+        });
+
+        print(names, "After sorting: ");
+    }
+
+    private static void print(List<Person> persons, String context) {
+        System.out.println(context);
+        for (Person person : persons) {
+            System.out.println(person.toString());
+        }
+        System.out.println();
+    }
+
+    public static void sortInJava8_use_lamda_expressions() {
+        List<Person> names = Arrays.asList(new Person("Sophie", 27), new Person("Ada", 1),
+                new Person("Steve", 28), new Person("Eason", 26), new Person("Jenny", 31));
+
+        print(names, "Prior to sort: ");
+
+        Collections.sort(names, (Person a, Person b) -> {
+            return a.age - b.age;
+        });
+
+        print(names, "After sorting: ");
+    }
+
+    public static void sortInJava8_use_lamda_expressions_shorter() {
+        List<Person> names = Arrays.asList(new Person("Sophie", 27), new Person("Ada", 1),
+                new Person("Steve", 28), new Person("Eason", 26), new Person("Jenny", 31));
+
+        print(names, "Prior to sort: ");
+
+        Collections.sort(names, (Person a, Person b) -> a.age - b.age);
+
+        print(names, "After sorting: ");
+    }
+
+    public static void sortInJava8_use_lamda_expressions_shorter_even() {
+        List<Person> names = Arrays.asList(new Person("Sophie", 27), new Person("Ada", 1),
+                new Person("Steve", 28), new Person("Eason", 26), new Person("Jenny", 31));
+
+        print(names, "Prior to sort: ");
+
+        Collections.sort(names, (a, b) -> a.age - b.age);
+
+        print(names, "After sorting: ");
+    }
+
+    public static void main(String...args) {
+        sortInPreJava8();
+        sortInJava8_use_lamda_expressions();
+        sortInJava8_use_lamda_expressions_shorter();
+        sortInJava8_use_lamda_expressions_shorter_even();
+    }
+}
+
+class Person {
+    String name;
+    int age;
+    public Person (String name, int age) {
+        this.name = name;
+        this.age = age;
+    }
+
+    @Override
+    public String toString() {
+        return "Person{" +
+                "name='" + name + '\'' +
+                ", age=" + age +
+                '}';
+    }
+}

From 25ac23df136dfce020afb0fa1631e6c3a629276e Mon Sep 17 00:00:00 2001
From: stevesun <stevesun@coupang.com>
Date: Sun, 16 Apr 2017 17:57:50 -0700
Subject: [PATCH 031/185] [JAVA8] FunctionalInterfaces

---
 .../functionalInterfaces/Converter.java       |  8 +++++++
 .../FunctionalInterfacesDemo.java             | 24 +++++++++++++++++++
 2 files changed, 32 insertions(+)
 create mode 100644 src/main/java/java8tutorials/functionalInterfaces/Converter.java
 create mode 100644 src/main/java/java8tutorials/functionalInterfaces/FunctionalInterfacesDemo.java

diff --git a/src/main/java/java8tutorials/functionalInterfaces/Converter.java b/src/main/java/java8tutorials/functionalInterfaces/Converter.java
new file mode 100644
index 0000000..cc09d85
--- /dev/null
+++ b/src/main/java/java8tutorials/functionalInterfaces/Converter.java
@@ -0,0 +1,8 @@
+package java8tutorials.functionalInterfaces;
+
+/**
+ * Created by stevesun on 4/16/17.
+ */
+public interface Converter<F, T> {
+    T convert(F from);
+}
diff --git a/src/main/java/java8tutorials/functionalInterfaces/FunctionalInterfacesDemo.java b/src/main/java/java8tutorials/functionalInterfaces/FunctionalInterfacesDemo.java
new file mode 100644
index 0000000..70c2162
--- /dev/null
+++ b/src/main/java/java8tutorials/functionalInterfaces/FunctionalInterfacesDemo.java
@@ -0,0 +1,24 @@
+package java8tutorials.functionalInterfaces;
+
+/**
+ * Created by stevesun on 4/16/17.
+ */
+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.
+     * 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.
+     * 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.*/
+
+    public static void main(String ... args) {
+        Converter<String, Integer> converter = (from -> Integer.valueOf(from));
+        Integer converted = converter.convert("123");
+        System.out.println(converted);
+    }
+
+}

From 64947dec803a836e6f7b56f78dceba662c791945 Mon Sep 17 00:00:00 2001
From: stevesun <stevesun@coupang.com>
Date: Sun, 16 Apr 2017 18:01:53 -0700
Subject: [PATCH 032/185] add README.md

---
 README.md | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/README.md b/README.md
index dec5902..7a1ee44 100644
--- a/README.md
+++ b/README.md
@@ -4,3 +4,7 @@ This is a Maven project containing a bunch of Random Java programs that I used,
 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:
 File -> New -> Project from Version Control -> GitHub, then configure JDK8, then you'll fly with colors! ^ ^
+
+|      Package   |   code
+|----------------|---------------
+|Avro|[Solution](../master/src/main/avro)

From 6f5374afe9e7bb584c04d73845361a959b2fd52a Mon Sep 17 00:00:00 2001
From: stevesun <stevesun@coupang.com>
Date: Sun, 16 Apr 2017 18:02:51 -0700
Subject: [PATCH 033/185] fix path

---
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/README.md b/README.md
index 7a1ee44..4d7fa30 100644
--- a/README.md
+++ b/README.md
@@ -7,4 +7,4 @@ File -> New -> Project from Version Control -> GitHub, then configure JDK8, then
 
 |      Package   |   code
 |----------------|---------------
-|Avro|[Solution](../master/src/main/avro)
+|Avro|[Solution](../master/src/main/java/avro)

From 30aa13f3eaacacced6b8700cc5995500a6a54125 Mon Sep 17 00:00:00 2001
From: stevesun <stevesun@coupang.com>
Date: Sun, 16 Apr 2017 18:04:35 -0700
Subject: [PATCH 034/185] add more links

---
 README.md | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/README.md b/README.md
index 4d7fa30..f47f80c 100644
--- a/README.md
+++ b/README.md
@@ -5,6 +5,7 @@ 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:
 File -> New -> Project from Version Control -> GitHub, then configure JDK8, then you'll fly with colors! ^ ^
 
-|      Package   |   code
+|      Package/Theme   |   Code
 |----------------|---------------
-|Avro|[Solution](../master/src/main/java/avro)
+|Avro|[Avro code](../master/src/main/java/avro)
+|Java 8 tutorials|[Java 8](../master/src/main/java/java8tutorials)

From 41255dee8c6e021848da962fd2ea92ae6abf2fa3 Mon Sep 17 00:00:00 2001
From: stevesun <stevesun@coupang.com>
Date: Sun, 16 Apr 2017 18:10:35 -0700
Subject: [PATCH 035/185] add more links

---
 README.md | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/README.md b/README.md
index f47f80c..a10548f 100644
--- a/README.md
+++ b/README.md
@@ -8,4 +8,8 @@ File -> New -> Project from Version Control -> GitHub, then configure JDK8, then
 |      Package/Theme   |   Code
 |----------------|---------------
 |Avro|[Avro code](../master/src/main/java/avro)
+|Java annotations|[annotations](../master/src/main/java/customize_annotations_generics_wildcards_examples)
+|Design Patterns|[Design patterns](../master/src/main/java/designPatterns)
+|Java Exceptions|[exceptions](../master/src/main/java/exceptionsCanBeSelfDefined)
+|Some interview questions|[questions](../master/src/main/java/interviewQuestions)
 |Java 8 tutorials|[Java 8](../master/src/main/java/java8tutorials)

From b29f66a21c03acc099cc0d3b98185164c3d3a433 Mon Sep 17 00:00:00 2001
From: stevesun <stevesun@coupang.com>
Date: Sun, 16 Apr 2017 18:12:06 -0700
Subject: [PATCH 036/185] change package name to be lowercase

---
 .../BinarySearch.java                                           | 0
 .../{InterviewQuestions => interviewQuestions}/BuildOrder.java  | 0
 .../ColorCombinations.java                                      | 0
 .../ConcatenatedWords.java                                      | 0
 .../ConcatenatedWordsII.java                                    | 2 +-
 .../FindLongestSuffixInTwoLists.java                            | 0
 .../FindWordFromNumber.java                                     | 2 +-
 .../LongestConsecutivePathInAMatrix.java                        | 0
 .../MaximumSizeSubarraySumEqualsOrSmallerThanK.java             | 2 +-
 .../{InterviewQuestions => interviewQuestions}/MinFloors.java   | 2 +-
 .../SetValueInDependencyGraph.java                              | 0
 11 files changed, 4 insertions(+), 4 deletions(-)
 rename src/main/java/{InterviewQuestions => interviewQuestions}/BinarySearch.java (100%)
 rename src/main/java/{InterviewQuestions => interviewQuestions}/BuildOrder.java (100%)
 rename src/main/java/{InterviewQuestions => interviewQuestions}/ColorCombinations.java (100%)
 rename src/main/java/{InterviewQuestions => interviewQuestions}/ConcatenatedWords.java (100%)
 rename src/main/java/{InterviewQuestions => interviewQuestions}/ConcatenatedWordsII.java (99%)
 rename src/main/java/{InterviewQuestions => interviewQuestions}/FindLongestSuffixInTwoLists.java (100%)
 rename src/main/java/{InterviewQuestions => interviewQuestions}/FindWordFromNumber.java (99%)
 rename src/main/java/{InterviewQuestions => interviewQuestions}/LongestConsecutivePathInAMatrix.java (100%)
 rename src/main/java/{InterviewQuestions => interviewQuestions}/MaximumSizeSubarraySumEqualsOrSmallerThanK.java (96%)
 rename src/main/java/{InterviewQuestions => interviewQuestions}/MinFloors.java (98%)
 rename src/main/java/{InterviewQuestions => interviewQuestions}/SetValueInDependencyGraph.java (100%)

diff --git a/src/main/java/InterviewQuestions/BinarySearch.java b/src/main/java/interviewQuestions/BinarySearch.java
similarity index 100%
rename from src/main/java/InterviewQuestions/BinarySearch.java
rename to src/main/java/interviewQuestions/BinarySearch.java
diff --git a/src/main/java/InterviewQuestions/BuildOrder.java b/src/main/java/interviewQuestions/BuildOrder.java
similarity index 100%
rename from src/main/java/InterviewQuestions/BuildOrder.java
rename to src/main/java/interviewQuestions/BuildOrder.java
diff --git a/src/main/java/InterviewQuestions/ColorCombinations.java b/src/main/java/interviewQuestions/ColorCombinations.java
similarity index 100%
rename from src/main/java/InterviewQuestions/ColorCombinations.java
rename to src/main/java/interviewQuestions/ColorCombinations.java
diff --git a/src/main/java/InterviewQuestions/ConcatenatedWords.java b/src/main/java/interviewQuestions/ConcatenatedWords.java
similarity index 100%
rename from src/main/java/InterviewQuestions/ConcatenatedWords.java
rename to src/main/java/interviewQuestions/ConcatenatedWords.java
diff --git a/src/main/java/InterviewQuestions/ConcatenatedWordsII.java b/src/main/java/interviewQuestions/ConcatenatedWordsII.java
similarity index 99%
rename from src/main/java/InterviewQuestions/ConcatenatedWordsII.java
rename to src/main/java/interviewQuestions/ConcatenatedWordsII.java
index 9d964d0..1f17d27 100644
--- a/src/main/java/InterviewQuestions/ConcatenatedWordsII.java
+++ b/src/main/java/interviewQuestions/ConcatenatedWordsII.java
@@ -1,4 +1,4 @@
-package InterviewQuestions;
+package interviewQuestions;
 
 import java.io.BufferedReader;
 import java.io.BufferedWriter;
diff --git a/src/main/java/InterviewQuestions/FindLongestSuffixInTwoLists.java b/src/main/java/interviewQuestions/FindLongestSuffixInTwoLists.java
similarity index 100%
rename from src/main/java/InterviewQuestions/FindLongestSuffixInTwoLists.java
rename to src/main/java/interviewQuestions/FindLongestSuffixInTwoLists.java
diff --git a/src/main/java/InterviewQuestions/FindWordFromNumber.java b/src/main/java/interviewQuestions/FindWordFromNumber.java
similarity index 99%
rename from src/main/java/InterviewQuestions/FindWordFromNumber.java
rename to src/main/java/interviewQuestions/FindWordFromNumber.java
index 558468b..297c907 100644
--- a/src/main/java/InterviewQuestions/FindWordFromNumber.java
+++ b/src/main/java/interviewQuestions/FindWordFromNumber.java
@@ -1,4 +1,4 @@
-package InterviewQuestions;
+package interviewQuestions;
 
 /**With Cracking group on 11/23/2013, a very fruitful day.
 
diff --git a/src/main/java/InterviewQuestions/LongestConsecutivePathInAMatrix.java b/src/main/java/interviewQuestions/LongestConsecutivePathInAMatrix.java
similarity index 100%
rename from src/main/java/InterviewQuestions/LongestConsecutivePathInAMatrix.java
rename to src/main/java/interviewQuestions/LongestConsecutivePathInAMatrix.java
diff --git a/src/main/java/InterviewQuestions/MaximumSizeSubarraySumEqualsOrSmallerThanK.java b/src/main/java/interviewQuestions/MaximumSizeSubarraySumEqualsOrSmallerThanK.java
similarity index 96%
rename from src/main/java/InterviewQuestions/MaximumSizeSubarraySumEqualsOrSmallerThanK.java
rename to src/main/java/interviewQuestions/MaximumSizeSubarraySumEqualsOrSmallerThanK.java
index 33df3a1..6f2cc67 100644
--- a/src/main/java/InterviewQuestions/MaximumSizeSubarraySumEqualsOrSmallerThanK.java
+++ b/src/main/java/interviewQuestions/MaximumSizeSubarraySumEqualsOrSmallerThanK.java
@@ -1,4 +1,4 @@
-package InterviewQuestions;
+package interviewQuestions;
 
 import java.util.HashMap;
 import java.util.Map;
diff --git a/src/main/java/InterviewQuestions/MinFloors.java b/src/main/java/interviewQuestions/MinFloors.java
similarity index 98%
rename from src/main/java/InterviewQuestions/MinFloors.java
rename to src/main/java/interviewQuestions/MinFloors.java
index 3a3fe6d..a20e895 100644
--- a/src/main/java/InterviewQuestions/MinFloors.java
+++ b/src/main/java/interviewQuestions/MinFloors.java
@@ -1,4 +1,4 @@
-package InterviewQuestions;
+package interviewQuestions;
 
 import java.util.Arrays;
 import java.util.HashMap;
diff --git a/src/main/java/InterviewQuestions/SetValueInDependencyGraph.java b/src/main/java/interviewQuestions/SetValueInDependencyGraph.java
similarity index 100%
rename from src/main/java/InterviewQuestions/SetValueInDependencyGraph.java
rename to src/main/java/interviewQuestions/SetValueInDependencyGraph.java

From aab796bbdf2f021715ef71c7f6900de5702204e9 Mon Sep 17 00:00:00 2001
From: stevesun <stevesun@coupang.com>
Date: Sun, 16 Apr 2017 18:53:15 -0700
Subject: [PATCH 037/185] use java 8

---
 .travis.yml | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/.travis.yml b/.travis.yml
index f64f09a..981bc0c 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,3 +1,13 @@
 language: java
 
-script: mvn package
+sudo: required
+
+jdk:
+  - oraclejdk8
+
+install: true
+
+script:
+  - sudo apt-get update && sudo apt-get install oracle-java8-installer
+  - java -version
+  - mvn package
\ No newline at end of file

From bb93edb7dda2caae7a2ce1e4e593eb950d964e57 Mon Sep 17 00:00:00 2001
From: stevesun <stevesun@coupang.com>
Date: Sun, 16 Apr 2017 18:54:58 -0700
Subject: [PATCH 038/185] use java 8

---
 .travis.yml | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index 981bc0c..63f6fc7 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -2,12 +2,11 @@ language: java
 
 sudo: required
 
-jdk:
-  - oraclejdk8
+jdk: oraclejdk8
 
 install: true
 
 script:
-  - sudo apt-get update && sudo apt-get install oracle-java8-installer
-  - java -version
-  - mvn package
\ No newline at end of file
+  mvn package
+  sudo apt-get update && sudo apt-get install oracle-java8-installer
+  java -version
\ No newline at end of file

From b4e7b1159e9aff864ffeb3937b4d0dd0679bbc18 Mon Sep 17 00:00:00 2001
From: stevesun <stevesun@coupang.com>
Date: Sun, 16 Apr 2017 18:57:49 -0700
Subject: [PATCH 039/185] fix travis

---
 .travis.yml | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/.travis.yml b/.travis.yml
index 63f6fc7..e23bca3 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -8,5 +8,6 @@ install: true
 
 script:
   mvn package
-  sudo apt-get update && sudo apt-get install oracle-java8-installer
+  sudo apt-get update
+  sudo apt-get install oracle-java8-installer
   java -version
\ No newline at end of file

From 494b7f94b96690c623f1f41c14cc50be6ceb918f Mon Sep 17 00:00:00 2001
From: stevesun <stevesun@coupang.com>
Date: Sun, 16 Apr 2017 18:58:42 -0700
Subject: [PATCH 040/185] fix travis

---
 .travis.yml | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index e23bca3..650c469 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -8,6 +8,6 @@ install: true
 
 script:
   mvn package
-  sudo apt-get update
-  sudo apt-get install oracle-java8-installer
-  java -version
\ No newline at end of file
+#  sudo apt-get update
+#  sudo apt-get install oracle-java8-installer
+#  java -version
\ No newline at end of file

From 2fe4a5137d494301f09679dd8629c270c40e06d6 Mon Sep 17 00:00:00 2001
From: stevesun <stevesun@coupang.com>
Date: Sun, 16 Apr 2017 19:19:30 -0700
Subject: [PATCH 041/185] add :: example

---
 .../functionalInterfaces/FunctionalInterfacesDemo.java      | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/src/main/java/java8tutorials/functionalInterfaces/FunctionalInterfacesDemo.java b/src/main/java/java8tutorials/functionalInterfaces/FunctionalInterfacesDemo.java
index 70c2162..311083d 100644
--- a/src/main/java/java8tutorials/functionalInterfaces/FunctionalInterfacesDemo.java
+++ b/src/main/java/java8tutorials/functionalInterfaces/FunctionalInterfacesDemo.java
@@ -19,6 +19,12 @@ public static void main(String ... args) {
         Converter<String, Integer> converter = (from -> Integer.valueOf(from));
         Integer converted = converter.convert("123");
         System.out.println(converted);
+
+        //we can use :: keyword to simplify the above
+        //that is how to reference a static method
+        converter = Integer::valueOf;
+        converted = converter.convert("321");
+        System.out.println(converted);
     }
 
 }

From 4ee98eec6f9b9d6ff4b1e503de508918d57e9eba Mon Sep 17 00:00:00 2001
From: stevesun <stevesun@coupang.com>
Date: Mon, 14 Aug 2017 08:15:14 -0700
Subject: [PATCH 042/185] refactor

---
 src/main/java/sorting/InsertionSort.java |  9 ++-------
 src/main/java/sorting/QuickSort.java     | 12 ++++++------
 src/main/java/sorting/SortUtils.java     | 11 +++++++++++
 3 files changed, 19 insertions(+), 13 deletions(-)
 create mode 100644 src/main/java/sorting/SortUtils.java

diff --git a/src/main/java/sorting/InsertionSort.java b/src/main/java/sorting/InsertionSort.java
index 90041ea..31409a7 100644
--- a/src/main/java/sorting/InsertionSort.java
+++ b/src/main/java/sorting/InsertionSort.java
@@ -34,20 +34,15 @@ private void swap(int[] nums, int j, int i) {
 		nums[j] = temp;
 	}
 	
-	public static void print(int[] nums){
-		for(int i : nums) System.out.print( i + ", ");
-		System.out.println();
-	}
-	
 	public static void main(String... args){
 //		System.out.println(2 >> 4);
 //		System.out.println(Integer.toBinaryString(32));
 		int[] nums = generateRandomArray(10);
 		InsertionSort test = new InsertionSort();
-		test.print(nums);
+		SortUtils.print(nums);
 //		test.swap(nums, 2, 0);
 //		test.print(nums);
-		test.print(test.insertionSortAgain(nums));
+		SortUtils.print(test.insertionSortAgain(nums));
 //		test.print(test.insertionSort(nums));
 	}
 	
diff --git a/src/main/java/sorting/QuickSort.java b/src/main/java/sorting/QuickSort.java
index 4e8c314..2681ee9 100644
--- a/src/main/java/sorting/QuickSort.java
+++ b/src/main/java/sorting/QuickSort.java
@@ -9,16 +9,16 @@ public int[] quickSort(int[] nums){
 	private void quickSort(int[] nums, int low, int high) {
 		if(low < high){
 			System.out.println("low = " + low + " high = " + high);
-			InsertionSort.print(nums);
+			SortUtils.print(nums);
 			int pi = partition_last(nums, low, high);
 			System.out.println("pi = " + pi);
-			InsertionSort.print(nums);
+			SortUtils.print(nums);
 			quickSort(nums, low, pi-1);
 			System.out.println("from " + low + " to " + (pi - 1) + " is already sorted, we'll start to sort the right half from " + (pi+1) + " to " + high);
-			InsertionSort.print(nums);
+			SortUtils.print(nums);
 			quickSort(nums, pi+1, high);
 			System.out.println("Final sorted list is: ");
-			InsertionSort.print(nums);
+			SortUtils.print(nums);
 		}
 		
 	}
@@ -79,14 +79,14 @@ private int partition_first(int[] list, int first, int last) {
 	public static void main(String... args){
 		int[] nums = InsertionSort.generateRandomArray(17);
 //		int[] nums = new int[]{10, 7, 8, 9, 1, 5};
-		InsertionSort.print(nums);
+		SortUtils.print(nums);
 //		test.swap(nums, 2, 0);
 //		test.print(nums);
 		QuickSort test = new QuickSort();
 //		InsertionSort.print(test.quickSort(nums));
 //		InsertionSort.print(test.quickSort_20160628(nums));
 //		InsertionSort.print(test.quickSort_pivot_first_20160628(nums));
-		InsertionSort.print(test.quickSort_pivot_median_20160628(nums));
+		SortUtils.print(test.quickSort_pivot_median_20160628(nums));
 		
 		
 	}
diff --git a/src/main/java/sorting/SortUtils.java b/src/main/java/sorting/SortUtils.java
new file mode 100644
index 0000000..6572e2f
--- /dev/null
+++ b/src/main/java/sorting/SortUtils.java
@@ -0,0 +1,11 @@
+package sorting;
+
+/**
+ * Created by stevesun on 8/14/17.
+ */
+public class SortUtils {
+    public static void print(int[] nums){
+        for(int i : nums) System.out.print( i + ", ");
+        System.out.println();
+    }
+}

From d4bae4ac8afce50cd239926dc417d83baba252ed Mon Sep 17 00:00:00 2001
From: stevesun <stevesun@coupang.com>
Date: Wed, 30 Aug 2017 08:58:08 -0700
Subject: [PATCH 043/185] refactor QuickSort

---
 src/main/java/sorting/QuickSort.java | 91 ++++++++++++++++------------
 1 file changed, 51 insertions(+), 40 deletions(-)

diff --git a/src/main/java/sorting/QuickSort.java b/src/main/java/sorting/QuickSort.java
index 2681ee9..4b132c8 100644
--- a/src/main/java/sorting/QuickSort.java
+++ b/src/main/java/sorting/QuickSort.java
@@ -1,51 +1,61 @@
 package sorting;
 
 public class QuickSort {
-	public int[] quickSort(int[] nums){
-		quickSort(nums, 0, nums.length-1);
-		return nums;
-	}
 
-	private void quickSort(int[] nums, int low, int high) {
-		if(low < high){
-			System.out.println("low = " + low + " high = " + high);
-			SortUtils.print(nums);
-			int pi = partition_last(nums, low, high);
-			System.out.println("pi = " + pi);
-			SortUtils.print(nums);
-			quickSort(nums, low, pi-1);
-			System.out.println("from " + low + " to " + (pi - 1) + " is already sorted, we'll start to sort the right half from " + (pi+1) + " to " + high);
-			SortUtils.print(nums);
-			quickSort(nums, pi+1, high);
-			System.out.println("Final sorted list is: ");
-			SortUtils.print(nums);
+	public static class QuickSortPartitionLast {
+		public int[] quickSort(int[] nums) {
+			quickSort(nums, 0, nums.length - 1);
+			return nums;
 		}
-		
-	}
-	
-	private int partition_last(int[] nums, int low, int high) {
-		int pivot = nums[high];
-		int i = (low-1);
-		for(int j = low; j <= high-1; j++){
-			if(nums[j] <= pivot){
-				i++;
-				//swap nums[i] and nums[j]
-				int temp = nums[i];
-				nums[i] = nums[j];
-				nums[j] = temp;
+
+		private void quickSort(int[] nums, int low, int high) {
+			if (low < high) {
+				int pi = partitionLast(nums, low, high);
+				quickSort(nums, low, pi - 1);
+				quickSort(nums, pi + 1, high);
 			}
+
+		}
+
+		private int partitionLast(int[] nums, int low, int high) {
+			int pivot = nums[high];
+			int i = (low - 1);
+			for (int j = low; j <= high - 1; j++) {
+				if (nums[j] <= pivot) {
+					i++;
+					//swap nums[i] and nums[j]
+					int temp = nums[i];
+					nums[i] = nums[j];
+					nums[j] = temp;
+				}
+			}
+
+			//swap nums[i+1] and nums[high]
+			int temp = nums[i + 1];
+			nums[i + 1] = nums[high];
+			nums[high] = temp;
+
+			return i + 1;
 		}
-		
-		//swap nums[i+1] and nums[high]
-		int temp = nums[i+1];
-		nums[i+1] = nums[high];
-		nums[high] = temp;
-		
-		return i+1;
 	}
-	
-	// this method find the pivot and do the sorting
-		private int partition_first(int[] list, int first, int last) {
+
+	public static class QuickSortPartitionFirst {
+		public int[] quickSort(int[] nums) {
+			quickSort(nums, 0, nums.length - 1);
+			return nums;
+		}
+
+		private void quickSort(int[] nums, int low, int high) {
+			if (low < high) {
+				int pi = partitionFirst(nums, low, high);
+				quickSort(nums, low, pi - 1);
+				quickSort(nums, pi + 1, high);
+			}
+
+		}
+
+		// this method find the pivot and do the sorting
+		private int partitionFirst(int[] list, int first, int last) {
 			int pivot = list[first];
 			int low = first + 1; // searching forward from pivot'next element
 			int high = last;// searching from the end for backward
@@ -75,6 +85,7 @@ private int partition_first(int[] list, int first, int last) {
 				return first;
 			}
 		}
+	}
 	
 	public static void main(String... args){
 		int[] nums = InsertionSort.generateRandomArray(17);

From ace65b07c42754d5fce4ae971d9311cc0e1d183d Mon Sep 17 00:00:00 2001
From: stevesun <fishercoder@gmail.com>
Date: Sat, 14 Oct 2017 15:46:45 -0700
Subject: [PATCH 044/185] [N-0] refactor

---
 .../Beverage.java                                               | 2 +-
 .../CondimentDecorator.java                                     | 2 +-
 .../DecoratorPatternTestDrive.java                              | 2 +-
 .../Espresso.java                                               | 2 +-
 .../HouseBlend.java                                             | 2 +-
 .../Mocha.java                                                  | 2 +-
 .../{chapter_3_decorator_pattern => decorator_pattern}/Soy.java | 2 +-
 .../Whip.java                                                   | 2 +-
 .../CoreFamily.java                                             | 2 +-
 .../CoreFamilyImpl.java                                         | 2 +-
 .../ObserverPatternTestDrive.java                               | 2 +-
 .../Relative.java                                               | 2 +-
 .../RelativeImpl.java                                           | 2 +-
 .../CookBehavior.java                                           | 2 +-
 .../CookNoodlesBehavior.java                                    | 2 +-
 .../CookRiceFlour.java                                          | 2 +-
 .../LoveBehavior.java                                           | 2 +-
 .../LoveHusbandBehavior.java                                    | 2 +-
 .../ModelWife.java                                              | 2 +-
 .../RealWife.java                                               | 2 +-
 .../StrategtyPatternTestDrive.java                              | 2 +-
 .../{chapter_1_strategy_pattern => strategy_pattern}/Wife.java  | 2 +-
 22 files changed, 22 insertions(+), 22 deletions(-)
 rename src/main/java/designPatterns/{chapter_3_decorator_pattern => decorator_pattern}/Beverage.java (76%)
 rename src/main/java/designPatterns/{chapter_3_decorator_pattern => decorator_pattern}/CondimentDecorator.java (66%)
 rename src/main/java/designPatterns/{chapter_3_decorator_pattern => decorator_pattern}/DecoratorPatternTestDrive.java (93%)
 rename src/main/java/designPatterns/{chapter_3_decorator_pattern => decorator_pattern}/Espresso.java (74%)
 rename src/main/java/designPatterns/{chapter_3_decorator_pattern => decorator_pattern}/HouseBlend.java (76%)
 rename src/main/java/designPatterns/{chapter_3_decorator_pattern => decorator_pattern}/Mocha.java (85%)
 rename src/main/java/designPatterns/{chapter_3_decorator_pattern => decorator_pattern}/Soy.java (85%)
 rename src/main/java/designPatterns/{chapter_3_decorator_pattern => decorator_pattern}/Whip.java (85%)
 rename src/main/java/designPatterns/{chapter_2_observer_pattern => observer_pattern}/CoreFamily.java (85%)
 rename src/main/java/designPatterns/{chapter_2_observer_pattern => observer_pattern}/CoreFamilyImpl.java (96%)
 rename src/main/java/designPatterns/{chapter_2_observer_pattern => observer_pattern}/ObserverPatternTestDrive.java (95%)
 rename src/main/java/designPatterns/{chapter_2_observer_pattern => observer_pattern}/Relative.java (73%)
 rename src/main/java/designPatterns/{chapter_2_observer_pattern => observer_pattern}/RelativeImpl.java (95%)
 rename src/main/java/designPatterns/{chapter_1_strategy_pattern => strategy_pattern}/CookBehavior.java (52%)
 rename src/main/java/designPatterns/{chapter_1_strategy_pattern => strategy_pattern}/CookNoodlesBehavior.java (76%)
 rename src/main/java/designPatterns/{chapter_1_strategy_pattern => strategy_pattern}/CookRiceFlour.java (75%)
 rename src/main/java/designPatterns/{chapter_1_strategy_pattern => strategy_pattern}/LoveBehavior.java (54%)
 rename src/main/java/designPatterns/{chapter_1_strategy_pattern => strategy_pattern}/LoveHusbandBehavior.java (77%)
 rename src/main/java/designPatterns/{chapter_1_strategy_pattern => strategy_pattern}/ModelWife.java (74%)
 rename src/main/java/designPatterns/{chapter_1_strategy_pattern => strategy_pattern}/RealWife.java (85%)
 rename src/main/java/designPatterns/{chapter_1_strategy_pattern => strategy_pattern}/StrategtyPatternTestDrive.java (92%)
 rename src/main/java/designPatterns/{chapter_1_strategy_pattern => strategy_pattern}/Wife.java (89%)

diff --git a/src/main/java/designPatterns/chapter_3_decorator_pattern/Beverage.java b/src/main/java/designPatterns/decorator_pattern/Beverage.java
similarity index 76%
rename from src/main/java/designPatterns/chapter_3_decorator_pattern/Beverage.java
rename to src/main/java/designPatterns/decorator_pattern/Beverage.java
index 6202fef..e6ffd11 100644
--- a/src/main/java/designPatterns/chapter_3_decorator_pattern/Beverage.java
+++ b/src/main/java/designPatterns/decorator_pattern/Beverage.java
@@ -1,4 +1,4 @@
-package designPatterns.chapter_3_decorator_pattern;
+package designPatterns.decorator_pattern;
 
 public abstract class Beverage {
 	String description = "Unknown beverage";
diff --git a/src/main/java/designPatterns/chapter_3_decorator_pattern/CondimentDecorator.java b/src/main/java/designPatterns/decorator_pattern/CondimentDecorator.java
similarity index 66%
rename from src/main/java/designPatterns/chapter_3_decorator_pattern/CondimentDecorator.java
rename to src/main/java/designPatterns/decorator_pattern/CondimentDecorator.java
index 3fea6aa..d689ebe 100644
--- a/src/main/java/designPatterns/chapter_3_decorator_pattern/CondimentDecorator.java
+++ b/src/main/java/designPatterns/decorator_pattern/CondimentDecorator.java
@@ -1,4 +1,4 @@
-package designPatterns.chapter_3_decorator_pattern;
+package designPatterns.decorator_pattern;
 
 public abstract class CondimentDecorator extends Beverage {
 	public abstract String getDescription();
diff --git a/src/main/java/designPatterns/chapter_3_decorator_pattern/DecoratorPatternTestDrive.java b/src/main/java/designPatterns/decorator_pattern/DecoratorPatternTestDrive.java
similarity index 93%
rename from src/main/java/designPatterns/chapter_3_decorator_pattern/DecoratorPatternTestDrive.java
rename to src/main/java/designPatterns/decorator_pattern/DecoratorPatternTestDrive.java
index 936faea..b7f5055 100644
--- a/src/main/java/designPatterns/chapter_3_decorator_pattern/DecoratorPatternTestDrive.java
+++ b/src/main/java/designPatterns/decorator_pattern/DecoratorPatternTestDrive.java
@@ -1,4 +1,4 @@
-package designPatterns.chapter_3_decorator_pattern;
+package designPatterns.decorator_pattern;
 
 /**Classes should be open for extension and closed for modification.
  * 
diff --git a/src/main/java/designPatterns/chapter_3_decorator_pattern/Espresso.java b/src/main/java/designPatterns/decorator_pattern/Espresso.java
similarity index 74%
rename from src/main/java/designPatterns/chapter_3_decorator_pattern/Espresso.java
rename to src/main/java/designPatterns/decorator_pattern/Espresso.java
index 2b302e0..7890d11 100644
--- a/src/main/java/designPatterns/chapter_3_decorator_pattern/Espresso.java
+++ b/src/main/java/designPatterns/decorator_pattern/Espresso.java
@@ -1,4 +1,4 @@
-package designPatterns.chapter_3_decorator_pattern;
+package designPatterns.decorator_pattern;
 
 public class Espresso extends Beverage {
 
diff --git a/src/main/java/designPatterns/chapter_3_decorator_pattern/HouseBlend.java b/src/main/java/designPatterns/decorator_pattern/HouseBlend.java
similarity index 76%
rename from src/main/java/designPatterns/chapter_3_decorator_pattern/HouseBlend.java
rename to src/main/java/designPatterns/decorator_pattern/HouseBlend.java
index 5ae7f59..e3bdd6f 100644
--- a/src/main/java/designPatterns/chapter_3_decorator_pattern/HouseBlend.java
+++ b/src/main/java/designPatterns/decorator_pattern/HouseBlend.java
@@ -1,4 +1,4 @@
-package designPatterns.chapter_3_decorator_pattern;
+package designPatterns.decorator_pattern;
 
 public class HouseBlend extends Beverage {
 
diff --git a/src/main/java/designPatterns/chapter_3_decorator_pattern/Mocha.java b/src/main/java/designPatterns/decorator_pattern/Mocha.java
similarity index 85%
rename from src/main/java/designPatterns/chapter_3_decorator_pattern/Mocha.java
rename to src/main/java/designPatterns/decorator_pattern/Mocha.java
index f9a2e88..0cb906e 100644
--- a/src/main/java/designPatterns/chapter_3_decorator_pattern/Mocha.java
+++ b/src/main/java/designPatterns/decorator_pattern/Mocha.java
@@ -1,4 +1,4 @@
-package designPatterns.chapter_3_decorator_pattern;
+package designPatterns.decorator_pattern;
 
 public class Mocha extends CondimentDecorator {
 
diff --git a/src/main/java/designPatterns/chapter_3_decorator_pattern/Soy.java b/src/main/java/designPatterns/decorator_pattern/Soy.java
similarity index 85%
rename from src/main/java/designPatterns/chapter_3_decorator_pattern/Soy.java
rename to src/main/java/designPatterns/decorator_pattern/Soy.java
index 581e71b..bcaec73 100644
--- a/src/main/java/designPatterns/chapter_3_decorator_pattern/Soy.java
+++ b/src/main/java/designPatterns/decorator_pattern/Soy.java
@@ -1,4 +1,4 @@
-package designPatterns.chapter_3_decorator_pattern;
+package designPatterns.decorator_pattern;
 
 public class Soy extends CondimentDecorator {
 
diff --git a/src/main/java/designPatterns/chapter_3_decorator_pattern/Whip.java b/src/main/java/designPatterns/decorator_pattern/Whip.java
similarity index 85%
rename from src/main/java/designPatterns/chapter_3_decorator_pattern/Whip.java
rename to src/main/java/designPatterns/decorator_pattern/Whip.java
index 3882694..d74da32 100644
--- a/src/main/java/designPatterns/chapter_3_decorator_pattern/Whip.java
+++ b/src/main/java/designPatterns/decorator_pattern/Whip.java
@@ -1,4 +1,4 @@
-package designPatterns.chapter_3_decorator_pattern;
+package designPatterns.decorator_pattern;
 
 public class Whip extends CondimentDecorator {
 
diff --git a/src/main/java/designPatterns/chapter_2_observer_pattern/CoreFamily.java b/src/main/java/designPatterns/observer_pattern/CoreFamily.java
similarity index 85%
rename from src/main/java/designPatterns/chapter_2_observer_pattern/CoreFamily.java
rename to src/main/java/designPatterns/observer_pattern/CoreFamily.java
index 8b3091e..8a8036f 100644
--- a/src/main/java/designPatterns/chapter_2_observer_pattern/CoreFamily.java
+++ b/src/main/java/designPatterns/observer_pattern/CoreFamily.java
@@ -1,4 +1,4 @@
-package designPatterns.chapter_2_observer_pattern;
+package designPatterns.observer_pattern;
 
 public interface CoreFamily {
 	public void registerRelative(Relative relative);
diff --git a/src/main/java/designPatterns/chapter_2_observer_pattern/CoreFamilyImpl.java b/src/main/java/designPatterns/observer_pattern/CoreFamilyImpl.java
similarity index 96%
rename from src/main/java/designPatterns/chapter_2_observer_pattern/CoreFamilyImpl.java
rename to src/main/java/designPatterns/observer_pattern/CoreFamilyImpl.java
index 02c5605..9191883 100644
--- a/src/main/java/designPatterns/chapter_2_observer_pattern/CoreFamilyImpl.java
+++ b/src/main/java/designPatterns/observer_pattern/CoreFamilyImpl.java
@@ -1,4 +1,4 @@
-package designPatterns.chapter_2_observer_pattern;
+package designPatterns.observer_pattern;
 
 import java.util.ArrayList;
 import java.util.List;
diff --git a/src/main/java/designPatterns/chapter_2_observer_pattern/ObserverPatternTestDrive.java b/src/main/java/designPatterns/observer_pattern/ObserverPatternTestDrive.java
similarity index 95%
rename from src/main/java/designPatterns/chapter_2_observer_pattern/ObserverPatternTestDrive.java
rename to src/main/java/designPatterns/observer_pattern/ObserverPatternTestDrive.java
index 7ef9298..68bfa3c 100644
--- a/src/main/java/designPatterns/chapter_2_observer_pattern/ObserverPatternTestDrive.java
+++ b/src/main/java/designPatterns/observer_pattern/ObserverPatternTestDrive.java
@@ -1,4 +1,4 @@
-package designPatterns.chapter_2_observer_pattern;
+package designPatterns.observer_pattern;
 
 /**NOTE: I didn't really implement the Observer pattern from Head First book here.
  * Just implemented the introduction part here. Could continue if interests arise in the future. - 10/04/2015*/
diff --git a/src/main/java/designPatterns/chapter_2_observer_pattern/Relative.java b/src/main/java/designPatterns/observer_pattern/Relative.java
similarity index 73%
rename from src/main/java/designPatterns/chapter_2_observer_pattern/Relative.java
rename to src/main/java/designPatterns/observer_pattern/Relative.java
index 3e62633..9ace511 100644
--- a/src/main/java/designPatterns/chapter_2_observer_pattern/Relative.java
+++ b/src/main/java/designPatterns/observer_pattern/Relative.java
@@ -1,4 +1,4 @@
-package designPatterns.chapter_2_observer_pattern;
+package designPatterns.observer_pattern;
 
 public interface Relative {
 	public void update(String coreFamilyNames, int hikingTimes, int marriedMonths, String bibleReadingProgress);
diff --git a/src/main/java/designPatterns/chapter_2_observer_pattern/RelativeImpl.java b/src/main/java/designPatterns/observer_pattern/RelativeImpl.java
similarity index 95%
rename from src/main/java/designPatterns/chapter_2_observer_pattern/RelativeImpl.java
rename to src/main/java/designPatterns/observer_pattern/RelativeImpl.java
index 30fdba9..bf08bea 100644
--- a/src/main/java/designPatterns/chapter_2_observer_pattern/RelativeImpl.java
+++ b/src/main/java/designPatterns/observer_pattern/RelativeImpl.java
@@ -1,4 +1,4 @@
-package designPatterns.chapter_2_observer_pattern;
+package designPatterns.observer_pattern;
 
 public class RelativeImpl implements Relative {
 	
diff --git a/src/main/java/designPatterns/chapter_1_strategy_pattern/CookBehavior.java b/src/main/java/designPatterns/strategy_pattern/CookBehavior.java
similarity index 52%
rename from src/main/java/designPatterns/chapter_1_strategy_pattern/CookBehavior.java
rename to src/main/java/designPatterns/strategy_pattern/CookBehavior.java
index 6ab7449..ba8f055 100644
--- a/src/main/java/designPatterns/chapter_1_strategy_pattern/CookBehavior.java
+++ b/src/main/java/designPatterns/strategy_pattern/CookBehavior.java
@@ -1,4 +1,4 @@
-package designPatterns.chapter_1_strategy_pattern;
+package designPatterns.strategy_pattern;
 
 public interface CookBehavior {
 
diff --git a/src/main/java/designPatterns/chapter_1_strategy_pattern/CookNoodlesBehavior.java b/src/main/java/designPatterns/strategy_pattern/CookNoodlesBehavior.java
similarity index 76%
rename from src/main/java/designPatterns/chapter_1_strategy_pattern/CookNoodlesBehavior.java
rename to src/main/java/designPatterns/strategy_pattern/CookNoodlesBehavior.java
index ed5ed14..ee13147 100644
--- a/src/main/java/designPatterns/chapter_1_strategy_pattern/CookNoodlesBehavior.java
+++ b/src/main/java/designPatterns/strategy_pattern/CookNoodlesBehavior.java
@@ -1,4 +1,4 @@
-package designPatterns.chapter_1_strategy_pattern;
+package designPatterns.strategy_pattern;
 
 public class CookNoodlesBehavior implements CookBehavior {
 
diff --git a/src/main/java/designPatterns/chapter_1_strategy_pattern/CookRiceFlour.java b/src/main/java/designPatterns/strategy_pattern/CookRiceFlour.java
similarity index 75%
rename from src/main/java/designPatterns/chapter_1_strategy_pattern/CookRiceFlour.java
rename to src/main/java/designPatterns/strategy_pattern/CookRiceFlour.java
index 5b377de..2fb0245 100644
--- a/src/main/java/designPatterns/chapter_1_strategy_pattern/CookRiceFlour.java
+++ b/src/main/java/designPatterns/strategy_pattern/CookRiceFlour.java
@@ -1,4 +1,4 @@
-package designPatterns.chapter_1_strategy_pattern;
+package designPatterns.strategy_pattern;
 
 public class CookRiceFlour implements CookBehavior {
 
diff --git a/src/main/java/designPatterns/chapter_1_strategy_pattern/LoveBehavior.java b/src/main/java/designPatterns/strategy_pattern/LoveBehavior.java
similarity index 54%
rename from src/main/java/designPatterns/chapter_1_strategy_pattern/LoveBehavior.java
rename to src/main/java/designPatterns/strategy_pattern/LoveBehavior.java
index 1757741..725e165 100644
--- a/src/main/java/designPatterns/chapter_1_strategy_pattern/LoveBehavior.java
+++ b/src/main/java/designPatterns/strategy_pattern/LoveBehavior.java
@@ -1,4 +1,4 @@
-package designPatterns.chapter_1_strategy_pattern;
+package designPatterns.strategy_pattern;
 
 public interface LoveBehavior {
 
diff --git a/src/main/java/designPatterns/chapter_1_strategy_pattern/LoveHusbandBehavior.java b/src/main/java/designPatterns/strategy_pattern/LoveHusbandBehavior.java
similarity index 77%
rename from src/main/java/designPatterns/chapter_1_strategy_pattern/LoveHusbandBehavior.java
rename to src/main/java/designPatterns/strategy_pattern/LoveHusbandBehavior.java
index 814a9b7..6306686 100644
--- a/src/main/java/designPatterns/chapter_1_strategy_pattern/LoveHusbandBehavior.java
+++ b/src/main/java/designPatterns/strategy_pattern/LoveHusbandBehavior.java
@@ -1,4 +1,4 @@
-package designPatterns.chapter_1_strategy_pattern;
+package designPatterns.strategy_pattern;
 
 public class LoveHusbandBehavior implements LoveBehavior {
 
diff --git a/src/main/java/designPatterns/chapter_1_strategy_pattern/ModelWife.java b/src/main/java/designPatterns/strategy_pattern/ModelWife.java
similarity index 74%
rename from src/main/java/designPatterns/chapter_1_strategy_pattern/ModelWife.java
rename to src/main/java/designPatterns/strategy_pattern/ModelWife.java
index 7e97c9e..20404a7 100644
--- a/src/main/java/designPatterns/chapter_1_strategy_pattern/ModelWife.java
+++ b/src/main/java/designPatterns/strategy_pattern/ModelWife.java
@@ -1,4 +1,4 @@
-package designPatterns.chapter_1_strategy_pattern;
+package designPatterns.strategy_pattern;
 
 public class ModelWife extends Wife {
 
diff --git a/src/main/java/designPatterns/chapter_1_strategy_pattern/RealWife.java b/src/main/java/designPatterns/strategy_pattern/RealWife.java
similarity index 85%
rename from src/main/java/designPatterns/chapter_1_strategy_pattern/RealWife.java
rename to src/main/java/designPatterns/strategy_pattern/RealWife.java
index 3bb6299..e569c9b 100644
--- a/src/main/java/designPatterns/chapter_1_strategy_pattern/RealWife.java
+++ b/src/main/java/designPatterns/strategy_pattern/RealWife.java
@@ -1,4 +1,4 @@
-package designPatterns.chapter_1_strategy_pattern;
+package designPatterns.strategy_pattern;
 
 public class RealWife extends Wife {
 
diff --git a/src/main/java/designPatterns/chapter_1_strategy_pattern/StrategtyPatternTestDrive.java b/src/main/java/designPatterns/strategy_pattern/StrategtyPatternTestDrive.java
similarity index 92%
rename from src/main/java/designPatterns/chapter_1_strategy_pattern/StrategtyPatternTestDrive.java
rename to src/main/java/designPatterns/strategy_pattern/StrategtyPatternTestDrive.java
index f7689bc..ed4d6e6 100644
--- a/src/main/java/designPatterns/chapter_1_strategy_pattern/StrategtyPatternTestDrive.java
+++ b/src/main/java/designPatterns/strategy_pattern/StrategtyPatternTestDrive.java
@@ -1,4 +1,4 @@
-package designPatterns.chapter_1_strategy_pattern;
+package designPatterns.strategy_pattern;
 
 /**
  * The Strategy Pattern defines a family of algorithms, encapsulates each one, and makes them interchangeable.
diff --git a/src/main/java/designPatterns/chapter_1_strategy_pattern/Wife.java b/src/main/java/designPatterns/strategy_pattern/Wife.java
similarity index 89%
rename from src/main/java/designPatterns/chapter_1_strategy_pattern/Wife.java
rename to src/main/java/designPatterns/strategy_pattern/Wife.java
index a499278..6409bdc 100644
--- a/src/main/java/designPatterns/chapter_1_strategy_pattern/Wife.java
+++ b/src/main/java/designPatterns/strategy_pattern/Wife.java
@@ -1,4 +1,4 @@
-package designPatterns.chapter_1_strategy_pattern;
+package designPatterns.strategy_pattern;
 
 public abstract class Wife {
 

From 0bcbc8212d8448dfe8c653eb4b8688cd47194eda Mon Sep 17 00:00:00 2001
From: stevesun <fishercoder@gmail.com>
Date: Sat, 14 Oct 2017 15:51:58 -0700
Subject: [PATCH 045/185] [N-0] minor refactor

---
 src/main/java/designPatterns/strategy_pattern/RealWife.java    | 3 ++-
 .../strategy_pattern/StrategtyPatternTestDrive.java            | 3 ++-
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/src/main/java/designPatterns/strategy_pattern/RealWife.java b/src/main/java/designPatterns/strategy_pattern/RealWife.java
index e569c9b..7569e27 100644
--- a/src/main/java/designPatterns/strategy_pattern/RealWife.java
+++ b/src/main/java/designPatterns/strategy_pattern/RealWife.java
@@ -3,7 +3,8 @@
 public class RealWife extends Wife {
 
 	public RealWife() {
-		System.out.println("I'm the real wife - Sophie Yan! I'm Sophie Yan, the wife of Steve Sun, and I like cooking for my husband and family. ");
+		System.out.println("I'm the real wife - Sophie Yan! I'm Sophie Yan, " +
+				"the wife of Steve Sun, and I like cooking for my husband and family. ");
 		this.cookBehavior = new CookRiceFlour();
 		this.loveBehavior = new LoveHusbandBehavior();
 	}
diff --git a/src/main/java/designPatterns/strategy_pattern/StrategtyPatternTestDrive.java b/src/main/java/designPatterns/strategy_pattern/StrategtyPatternTestDrive.java
index ed4d6e6..914847a 100644
--- a/src/main/java/designPatterns/strategy_pattern/StrategtyPatternTestDrive.java
+++ b/src/main/java/designPatterns/strategy_pattern/StrategtyPatternTestDrive.java
@@ -7,7 +7,8 @@
 /**Design principle:
  * Favor composition over inheritance.
  * 
- * Not only does it let you encapsulate a family of algorithms into their own set of classes, but it also lets you change behavior at runtime.*/
+ * Not only does it let you encapsulate a family of algorithms into their own set of classes,
+ * but it also lets you change behavior at runtime.*/
 public class StrategtyPatternTestDrive {
 
 	public static void main(String[] args) {

From 520c19f6d86f27833184fd8c4b74cfa40620859e Mon Sep 17 00:00:00 2001
From: stevesun <fishercoder@gmail.com>
Date: Sat, 14 Oct 2017 15:56:39 -0700
Subject: [PATCH 046/185] [N-0] add main for missing patterns

---
 .../adapter_and_facade_pattern/TestDrive.java         | 11 +++++++++++
 .../designPatterns/command_pattern/TestDrive.java     | 11 +++++++++++
 .../designPatterns/compound_pattern/TestDrive.java    | 11 +++++++++++
 .../iterator_and_composite_pattern/TestDrive.java     | 11 +++++++++++
 .../java/designPatterns/proxy_pattern/TestDrive.java  | 11 +++++++++++
 .../designPatterns/singleton_pattern/TestDrive.java   | 11 +++++++++++
 .../java/designPatterns/state_pattern/TestDrive.java  | 11 +++++++++++
 .../template_method_pattern/TestDrive.java            | 11 +++++++++++
 8 files changed, 88 insertions(+)
 create mode 100644 src/main/java/designPatterns/adapter_and_facade_pattern/TestDrive.java
 create mode 100644 src/main/java/designPatterns/command_pattern/TestDrive.java
 create mode 100644 src/main/java/designPatterns/compound_pattern/TestDrive.java
 create mode 100644 src/main/java/designPatterns/iterator_and_composite_pattern/TestDrive.java
 create mode 100644 src/main/java/designPatterns/proxy_pattern/TestDrive.java
 create mode 100644 src/main/java/designPatterns/singleton_pattern/TestDrive.java
 create mode 100644 src/main/java/designPatterns/state_pattern/TestDrive.java
 create mode 100644 src/main/java/designPatterns/template_method_pattern/TestDrive.java

diff --git a/src/main/java/designPatterns/adapter_and_facade_pattern/TestDrive.java b/src/main/java/designPatterns/adapter_and_facade_pattern/TestDrive.java
new file mode 100644
index 0000000..b9bc057
--- /dev/null
+++ b/src/main/java/designPatterns/adapter_and_facade_pattern/TestDrive.java
@@ -0,0 +1,11 @@
+package designPatterns.adapter_and_facade_pattern;
+
+public class TestDrive {
+	
+	public static void main(String... args){
+		System.out.println("Program started.");
+
+		System.out.println("Program ended.");
+	}
+
+}
diff --git a/src/main/java/designPatterns/command_pattern/TestDrive.java b/src/main/java/designPatterns/command_pattern/TestDrive.java
new file mode 100644
index 0000000..c0917f4
--- /dev/null
+++ b/src/main/java/designPatterns/command_pattern/TestDrive.java
@@ -0,0 +1,11 @@
+package designPatterns.command_pattern;
+
+public class TestDrive {
+	
+	public static void main(String... args){
+		System.out.println("Program started.");
+
+		System.out.println("Program ended.");
+	}
+
+}
diff --git a/src/main/java/designPatterns/compound_pattern/TestDrive.java b/src/main/java/designPatterns/compound_pattern/TestDrive.java
new file mode 100644
index 0000000..3b12daf
--- /dev/null
+++ b/src/main/java/designPatterns/compound_pattern/TestDrive.java
@@ -0,0 +1,11 @@
+package designPatterns.compound_pattern;
+
+public class TestDrive {
+	
+	public static void main(String... args){
+		System.out.println("Program started.");
+
+		System.out.println("Program ended.");
+	}
+
+}
diff --git a/src/main/java/designPatterns/iterator_and_composite_pattern/TestDrive.java b/src/main/java/designPatterns/iterator_and_composite_pattern/TestDrive.java
new file mode 100644
index 0000000..3ef3aaf
--- /dev/null
+++ b/src/main/java/designPatterns/iterator_and_composite_pattern/TestDrive.java
@@ -0,0 +1,11 @@
+package designPatterns.iterator_and_composite_pattern;
+
+public class TestDrive {
+	
+	public static void main(String... args){
+		System.out.println("Program started.");
+
+		System.out.println("Program ended.");
+	}
+
+}
diff --git a/src/main/java/designPatterns/proxy_pattern/TestDrive.java b/src/main/java/designPatterns/proxy_pattern/TestDrive.java
new file mode 100644
index 0000000..b833fee
--- /dev/null
+++ b/src/main/java/designPatterns/proxy_pattern/TestDrive.java
@@ -0,0 +1,11 @@
+package designPatterns.proxy_pattern;
+
+public class TestDrive {
+	
+	public static void main(String... args){
+		System.out.println("Program started.");
+
+		System.out.println("Program ended.");
+	}
+
+}
diff --git a/src/main/java/designPatterns/singleton_pattern/TestDrive.java b/src/main/java/designPatterns/singleton_pattern/TestDrive.java
new file mode 100644
index 0000000..638ccc6
--- /dev/null
+++ b/src/main/java/designPatterns/singleton_pattern/TestDrive.java
@@ -0,0 +1,11 @@
+package designPatterns.singleton_pattern;
+
+public class TestDrive {
+	
+	public static void main(String... args){
+		System.out.println("Program started.");
+
+		System.out.println("Program ended.");
+	}
+
+}
diff --git a/src/main/java/designPatterns/state_pattern/TestDrive.java b/src/main/java/designPatterns/state_pattern/TestDrive.java
new file mode 100644
index 0000000..25d88cc
--- /dev/null
+++ b/src/main/java/designPatterns/state_pattern/TestDrive.java
@@ -0,0 +1,11 @@
+package designPatterns.state_pattern;
+
+public class TestDrive {
+	
+	public static void main(String... args){
+		System.out.println("Program started.");
+
+		System.out.println("Program ended.");
+	}
+
+}
diff --git a/src/main/java/designPatterns/template_method_pattern/TestDrive.java b/src/main/java/designPatterns/template_method_pattern/TestDrive.java
new file mode 100644
index 0000000..0d3605c
--- /dev/null
+++ b/src/main/java/designPatterns/template_method_pattern/TestDrive.java
@@ -0,0 +1,11 @@
+package designPatterns.template_method_pattern;
+
+public class TestDrive {
+	
+	public static void main(String... args){
+		System.out.println("Program started.");
+
+		System.out.println("Program ended.");
+	}
+
+}

From 44936af85caea42e0426761fb312d90718ad059a Mon Sep 17 00:00:00 2001
From: stevesun <fishercoder@gmail.com>
Date: Sat, 14 Oct 2017 16:14:46 -0700
Subject: [PATCH 047/185] [N-0] add singleton pattern

---
 .../singleton_pattern/TestDrive.java          |  3 +-
 .../ThreadSafeSingleton.java                  | 33 +++++++++++++++++++
 2 files changed, 35 insertions(+), 1 deletion(-)
 create mode 100644 src/main/java/designPatterns/singleton_pattern/ThreadSafeSingleton.java

diff --git a/src/main/java/designPatterns/singleton_pattern/TestDrive.java b/src/main/java/designPatterns/singleton_pattern/TestDrive.java
index 638ccc6..8e0387c 100644
--- a/src/main/java/designPatterns/singleton_pattern/TestDrive.java
+++ b/src/main/java/designPatterns/singleton_pattern/TestDrive.java
@@ -4,7 +4,8 @@ public class TestDrive {
 	
 	public static void main(String... args){
 		System.out.println("Program started.");
-
+		ThreadSafeSingleton threadSafeSingleton = ThreadSafeSingleton.getInstance();
+		threadSafeSingleton.work();
 		System.out.println("Program ended.");
 	}
 
diff --git a/src/main/java/designPatterns/singleton_pattern/ThreadSafeSingleton.java b/src/main/java/designPatterns/singleton_pattern/ThreadSafeSingleton.java
new file mode 100644
index 0000000..272fc4d
--- /dev/null
+++ b/src/main/java/designPatterns/singleton_pattern/ThreadSafeSingleton.java
@@ -0,0 +1,33 @@
+package designPatterns.singleton_pattern;
+
+/**
+ * Created by stevesun on 10/14/17.
+ */
+public class ThreadSafeSingleton {
+
+    private static ThreadSafeSingleton instance;
+
+    public static ThreadSafeSingleton getInstance() {
+        /**
+         * Double checked locking principle
+         *
+         * This is the most optimal approach in singleton pattern:
+         * https://www.journaldev.com/1377/java-singleton-design-pattern-best-practices-examples
+         * 1. It uses lazy initialization (saves resources, such as database connections.)
+         * 2. It's thread safe, but also minimizes performance penalty (minimizes the smallest code snippet possible,
+         * not synchronizing the whole method.)
+         * */
+        if (instance == null) {
+            synchronized (ThreadSafeSingleton.class) {
+                if (instance == null) {
+                    instance = new ThreadSafeSingleton();
+                }
+            }
+        }
+        return instance;
+    }
+
+    public static void work() {
+        System.out.println("One instance is here!!!");
+    }
+}

From 5370e71390d85d1e3b74673287631c1b534dd058 Mon Sep 17 00:00:00 2001
From: Steve Sun <stevesun@squareup.com>
Date: Thu, 21 Dec 2017 15:16:51 -0800
Subject: [PATCH 048/185] add a simple AWS SES example

---
 pom.xml                                      | 22 +++---
 src/main/java/amazonses/AmazonSESSample.java | 71 ++++++++++++++++++++
 2 files changed, 79 insertions(+), 14 deletions(-)
 create mode 100644 src/main/java/amazonses/AmazonSESSample.java

diff --git a/pom.xml b/pom.xml
index 72ce814..54c6535 100644
--- a/pom.xml
+++ b/pom.xml
@@ -80,18 +80,6 @@
             <version>4.1.6.RELEASE</version>
         </dependency>
 
-        <dependency>
-            <groupId>com.fasterxml.jackson.core</groupId>
-            <artifactId>jackson-annotations</artifactId>
-            <version>2.6.0</version>
-        </dependency>
-
-        <dependency>
-            <groupId>com.fasterxml.jackson.core</groupId>
-            <artifactId>jackson-databind</artifactId>
-            <version>2.4.1.3</version>
-        </dependency>
-
         <dependency>
             <groupId>org.codehaus.jackson</groupId>
             <artifactId>jackson-core-asl</artifactId>
@@ -118,7 +106,13 @@
             <version>1.8.1</version>
         </dependency>
 
+      <dependency>
+        <groupId>com.amazonaws</groupId>
+        <artifactId>aws-java-sdk-ses</artifactId>
+        <version>1.11.253</version>
+      </dependency>
+
     </dependencies>
 
-    
-</project>
\ No newline at end of file
+
+</project>
diff --git a/src/main/java/amazonses/AmazonSESSample.java b/src/main/java/amazonses/AmazonSESSample.java
new file mode 100644
index 0000000..a9be62a
--- /dev/null
+++ b/src/main/java/amazonses/AmazonSESSample.java
@@ -0,0 +1,71 @@
+package amazonses;
+
+import com.amazonaws.auth.BasicAWSCredentials;
+import com.amazonaws.regions.Regions;
+import com.amazonaws.services.simpleemail.AmazonSimpleEmailService;
+import com.amazonaws.services.simpleemail.AmazonSimpleEmailServiceClient;
+import com.amazonaws.services.simpleemail.model.Body;
+import com.amazonaws.services.simpleemail.model.Content;
+import com.amazonaws.services.simpleemail.model.Destination;
+import com.amazonaws.services.simpleemail.model.Message;
+import com.amazonaws.services.simpleemail.model.SendEmailRequest;
+import java.io.IOException;
+
+public class AmazonSESSample {
+  // Replace sender@example.com with your "From" address.
+  // This address must be verified with Amazon SES.
+  static final String FROM = "fishercoder@gmail.com";
+
+  // Replace recipient@example.com with a "To" address. If your account
+  // is still in the sandbox, this address must be verified.
+  static final String TO = "stevejsun@gmail.com";
+
+  // The configuration set to use for this email. If you do not want to use a
+  // configuration set, comment the following variable and the
+  // .withConfigurationSetName(CONFIGSET); argument below.
+  //static final String CONFIGSET = "ConfigSet";
+
+  // The subject line for the email.
+  static final String SUBJECT = "Amazon SES test (AWS SDK for Java)";
+
+  // The HTML body for the email.
+  static final String HTMLBODY = "<h1>Amazon SES test (AWS SDK for Java)</h1>"
+      + "<p>This email was sent with <a href='https://aws.amazon.com/ses/'>"
+      + "Amazon SES</a> using the <a href='https://aws.amazon.com/sdk-for-java/'>"
+      + "AWS SDK for Java</a>";
+
+  // The email body for recipients with non-HTML email clients.
+  static final String TEXTBODY = "This email was sent through Amazon SES "
+      + "using the AWS SDK for Java.";
+
+  public static void main(String[] args) throws IOException {
+
+    try {
+      BasicAWSCredentials credentials = new BasicAWSCredentials("ACCESS_KEY", "SECRET_KEY");
+      AmazonSimpleEmailService client =
+          new AmazonSimpleEmailServiceClient(credentials).withRegion(Regions.US_WEST_2);
+          //AmazonSimpleEmailServiceClientBuilder.standard().withRegion(Regions.US_WEST_2).build();
+      SendEmailRequest request = new SendEmailRequest()
+          .withDestination(
+              new Destination().withToAddresses(TO))
+          .withMessage(new Message()
+              .withBody(new Body()
+                  .withHtml(new Content()
+                      .withCharset("UTF-8").withData(HTMLBODY))
+                  .withText(new Content()
+                      .withCharset("UTF-8").withData(TEXTBODY)))
+              .withSubject(new Content()
+                  .withCharset("UTF-8").withData(SUBJECT)))
+          .withSource(FROM)
+          // Comment or remove the next line if you are not using a
+          // configuration set
+          //.withConfigurationSetName(CONFIGSET)
+      ;
+      client.sendEmail(request);
+      System.out.println("Email sent!");
+    } catch (Exception ex) {
+      System.out.println("The email was not sent. Error message: "
+          + ex.getMessage());
+    }
+  }
+}

From 3b43043ef89ed889d22b93b01a15a13f64454520 Mon Sep 17 00:00:00 2001
From: Steve Sun <fishercoder@gmail.com>
Date: Thu, 21 Dec 2017 15:18:23 -0800
Subject: [PATCH 049/185] minor edit

---
 src/main/java/amazonses/AmazonSESSample.java | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/main/java/amazonses/AmazonSESSample.java b/src/main/java/amazonses/AmazonSESSample.java
index a9be62a..9337e86 100644
--- a/src/main/java/amazonses/AmazonSESSample.java
+++ b/src/main/java/amazonses/AmazonSESSample.java
@@ -41,6 +41,7 @@ public class AmazonSESSample {
   public static void main(String[] args) throws IOException {
 
     try {
+
       BasicAWSCredentials credentials = new BasicAWSCredentials("ACCESS_KEY", "SECRET_KEY");
       AmazonSimpleEmailService client =
           new AmazonSimpleEmailServiceClient(credentials).withRegion(Regions.US_WEST_2);

From 361e36f098acc8fd36a911038e2d4d38b8f13818 Mon Sep 17 00:00:00 2001
From: Steve Sun <fishercoder@gmail.com>
Date: Tue, 9 Jan 2018 17:14:51 -0800
Subject: [PATCH 050/185] add a random java8 example

---
 .../Random1.java                               | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)
 create mode 100644 src/main/java/java8_for_the_really_impatient/Random1.java

diff --git a/src/main/java/java8_for_the_really_impatient/Random1.java b/src/main/java/java8_for_the_really_impatient/Random1.java
new file mode 100644
index 0000000..44c863b
--- /dev/null
+++ b/src/main/java/java8_for_the_really_impatient/Random1.java
@@ -0,0 +1,18 @@
+package java8_for_the_really_impatient;
+
+import java.util.Arrays;
+import java.util.stream.Stream;
+
+public class Random1 {
+
+  public static void main(String... args) {
+    String[] arr1 = {"abc", "bcd", "cdef", "defgh"};
+    String[] arr2 = {"af", "fg", "gh"};
+    Stream<String> stream1 = Stream.of(arr1);
+    Stream<String> stream2 = Stream.of(arr2);
+
+    Stream<String> stream3 = Stream.concat(stream1.filter(x -> x.length() < 4), stream2);
+    String[] arr = stream3.toArray(String[]::new);
+    System.out.println(Arrays.toString(arr));
+  }
+}

From b31037bce0f8252685afcb43fd0b5726201ba5be Mon Sep 17 00:00:00 2001
From: Steve Sun <fishercoder@gmail.com>
Date: Tue, 16 Jan 2018 17:23:00 -0800
Subject: [PATCH 051/185] add one solution

---
 .../Chapter3.java                             |  52 ++++++++++++++++++
 .../Random1.java                              |  18 ------
 src/main/resources/queen-mary.png             | Bin 0 -> 265908 bytes
 3 files changed, 52 insertions(+), 18 deletions(-)
 create mode 100644 src/main/java/java8_for_the_really_impatient/Chapter3.java
 delete mode 100644 src/main/java/java8_for_the_really_impatient/Random1.java
 create mode 100644 src/main/resources/queen-mary.png

diff --git a/src/main/java/java8_for_the_really_impatient/Chapter3.java b/src/main/java/java8_for_the_really_impatient/Chapter3.java
new file mode 100644
index 0000000..85e4ac0
--- /dev/null
+++ b/src/main/java/java8_for_the_really_impatient/Chapter3.java
@@ -0,0 +1,52 @@
+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 <T> Image transform(Image in, BiFunction<Color, T, Color> 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), 1.5
+    );
+    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/java8_for_the_really_impatient/Random1.java b/src/main/java/java8_for_the_really_impatient/Random1.java
deleted file mode 100644
index 44c863b..0000000
--- a/src/main/java/java8_for_the_really_impatient/Random1.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package java8_for_the_really_impatient;
-
-import java.util.Arrays;
-import java.util.stream.Stream;
-
-public class Random1 {
-
-  public static void main(String... args) {
-    String[] arr1 = {"abc", "bcd", "cdef", "defgh"};
-    String[] arr2 = {"af", "fg", "gh"};
-    Stream<String> stream1 = Stream.of(arr1);
-    Stream<String> stream2 = Stream.of(arr2);
-
-    Stream<String> stream3 = Stream.concat(stream1.filter(x -> x.length() < 4), stream2);
-    String[] arr = stream3.toArray(String[]::new);
-    System.out.println(Arrays.toString(arr));
-  }
-}
diff --git a/src/main/resources/queen-mary.png b/src/main/resources/queen-mary.png
new file mode 100644
index 0000000000000000000000000000000000000000..defe6e4bfe8280a478c21b6dafa7ccd9234264e9
GIT binary patch

From 7be0fe010f53b838270e3b9a4a5e4bc189a3ffd5 Mon Sep 17 00:00:00 2001
From: Steve Sun <fishercoder@gmail.com>
Date: Thu, 18 Jan 2018 07:34:31 -0800
Subject: [PATCH 052/185] fix build

---
 src/main/java/java8_for_the_really_impatient/Chapter3.java | 1 -
 1 file changed, 1 deletion(-)

diff --git a/src/main/java/java8_for_the_really_impatient/Chapter3.java b/src/main/java/java8_for_the_really_impatient/Chapter3.java
index 85e4ac0..f96c9e6 100644
--- a/src/main/java/java8_for_the_really_impatient/Chapter3.java
+++ b/src/main/java/java8_for_the_really_impatient/Chapter3.java
@@ -48,5 +48,4 @@ public static void main(String... args) {
 
   /** 3.5 Composition: saves the storage of an intermediate stage. */
 
-
 }

From 460f87e585e0d52f59e9991c08c17fa1c99cce13 Mon Sep 17 00:00:00 2001
From: Steve Sun <fishercoder@gmail.com>
Date: Tue, 23 Jan 2018 16:34:27 -0800
Subject: [PATCH 053/185] minor changfe

---
 src/main/java/java8_for_the_really_impatient/Chapter3.java | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/main/java/java8_for_the_really_impatient/Chapter3.java b/src/main/java/java8_for_the_really_impatient/Chapter3.java
index f96c9e6..b196363 100644
--- a/src/main/java/java8_for_the_really_impatient/Chapter3.java
+++ b/src/main/java/java8_for_the_really_impatient/Chapter3.java
@@ -34,7 +34,7 @@ public static <T> Image transform(Image in, BiFunction<Color, T, Color> f, T arg
   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), 1.5
+        (c, factor) -> c.deriveColor(0, 1, factor, 1), 0.05
     );
     stage.setScene(new Scene(new HBox(new ImageView(image), new ImageView(newImage))));
     stage.show();

From fb35c963caa49bffcc28b3ca297d757c10298b02 Mon Sep 17 00:00:00 2001
From: Fisher Coder <fishercoder@gmail.com>
Date: Thu, 6 Sep 2018 18:50:05 -0700
Subject: [PATCH 054/185] 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 <fishercoder@gmail.com>
Date: Mon, 15 Oct 2018 07:26:59 -0700
Subject: [PATCH 055/185] 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 @@
         <version>1.11.253</version>
       </dependency>
 
+        <dependency>
+            <groupId>com.google.inject</groupId>
+            <artifactId>guice</artifactId>
+            <version>3.0</version>
+        </dependency>
+
     </dependencies>
 
 
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 <fishercoder@gmail.com>
Date: Mon, 15 Oct 2018 07:27:29 -0700
Subject: [PATCH 056/185] 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 <fishercoder@gmail.com>
Date: Mon, 26 Nov 2018 12:26:43 -0800
Subject: [PATCH 057/185] 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<Integer> 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 <sunstev@amazon.com>
Date: Sat, 7 Sep 2019 18:27:49 -0700
Subject: [PATCH 058/185] 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 <fishercoder@gmail.com>
Date: Sat, 7 Sep 2019 18:33:45 -0700
Subject: [PATCH 059/185] 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 <fishercoder@gmail.com>
Date: Sat, 7 Sep 2019 18:37:03 -0700
Subject: [PATCH 060/185] 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 <fishercoder@gmail.com>
Date: Sat, 7 Sep 2019 18:48:20 -0700
Subject: [PATCH 061/185] 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 <fishercoder@gmail.com>
Date: Sat, 7 Sep 2019 18:57:18 -0700
Subject: [PATCH 062/185] 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:
+     * <p>
+     * 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 <fishercoder@gmail.com>
Date: Sun, 8 Sep 2019 09:36:47 -0700
Subject: [PATCH 063/185] 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 <fishercoder@gmail.com>
Date: Sun, 8 Sep 2019 12:33:54 -0700
Subject: [PATCH 064/185] 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 <fishercoder@gmail.com>
Date: Sun, 8 Sep 2019 12:48:54 -0700
Subject: [PATCH 065/185] 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<SpellChecker> {
+    @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 <fishercoder@gmail.com>
Date: Sun, 8 Sep 2019 12:53:14 -0700
Subject: [PATCH 066/185] 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 <fishercoder@gmail.com>
Date: Sun, 8 Sep 2019 13:06:36 -0700
Subject: [PATCH 067/185] 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 <fishercoder@gmail.com>
Date: Sun, 8 Sep 2019 13:14:52 -0700
Subject: [PATCH 068/185] 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 <fishercoder@gmail.com>
Date: Sun, 8 Sep 2019 13:19:28 -0700
Subject: [PATCH 069/185] 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 <fishercoder@gmail.com>
Date: Wed, 11 Sep 2019 07:02:13 -0700
Subject: [PATCH 070/185] 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 <fishercoder@gmail.com>
Date: Mon, 23 Sep 2019 09:31:11 -0700
Subject: [PATCH 071/185] 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<String> incomingSetOne, Set<String> incomingSetTwo, String incomingString) {
+        Set<String> 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<String> 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<String> setOne;
+        private Set<String> setTwo;
+        private int setOneCount;
+        private int setTwoCount;
+
+        public Set<String> getSetOne() {
+            return setOne;
+        }
+
+        public void setSetOne(Set<String> setOne) {
+            this.setOne = setOne;
+        }
+
+        public void setSetOneCount(int count) {
+            this.setOneCount = count;
+        }
+
+        public Set<String> getSetTwo() {
+            return setTwo;
+        }
+
+        public void setSetTwo(Set<String> setTwo) {
+            this.setTwo = setTwo;
+        }
+
+        public void setSetTwoCount(int count) {
+            this.setTwoCount = count;
+        }
+    }
+
+}

From 5129e74da12acf045274389d84217217efde614c Mon Sep 17 00:00:00 2001
From: Fisher Coder <fishercoder@gmail.com>
Date: Mon, 23 Sep 2019 09:31:57 -0700
Subject: [PATCH 072/185] 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 <fishercoder@gmail.com>
Date: Mon, 18 Nov 2019 08:21:49 -0800
Subject: [PATCH 073/185] 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 @@
             <version>3.0</version>
         </dependency>
 
+        <!-- https://mvnrepository.com/artifact/com.google.collections/google-collections -->
+        <dependency>
+            <groupId>com.google.collections</groupId>
+            <artifactId>google-collections</artifactId>
+            <version>1.0</version>
+        </dependency>
+
+        <!-- https://mvnrepository.com/artifact/com.google.inject/guice -->
+        <dependency>
+            <groupId>com.google.inject</groupId>
+            <artifactId>guice</artifactId>
+            <version>LATEST</version>
+        </dependency>
+
+
     </dependencies>
 
 
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<String>() {
+                            @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<String>() {
+                            @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.<Dependencyof(Dependency.get(Key.get(Injector.class))),
+//                binding.getDependencies());
+//        PrivateElements privateElements = binding.getPrivateElements();
+//        assertEquals(ImmutableSet.<Keyof(Key.get(String.class, named("b"))),
+//                privateElements.getExposedKeys());
+//        assertContains(privateElements.getExposedSource(Key.get(String.class, named("b"))).toString(),
+//                PrivateModuleTest.class.getName(), getDeclaringSourcePart(getClass()));
+//        Injector privateInjector = privateElements.getInjector();
+//        assertEquals("private", privateInjector.getInstance(Key.get(String.class, Names.named("a"))));
+    }
+
+    public void testParentBindsSomethingInPrivate() {
+        try {
+            Guice.createInjector(new FailingModule());
+            fail();
+        } catch(CreationException expected) {
+            assertEquals(1, expected.getErrorMessages().size());
+//            assertContains(expected.toString(),
+//                    "Unable to create binding for java.util.List.",
+//                    "It was already configured on one or more child injectors or private modules",
+//                    "bound at " + FailingPrivateModule.class.getName() + ".configure(",
+//                    asModuleChain(FailingModule.class, ManyPrivateModules.class, FailingPrivateModule.class),
+//                    "bound at " + SecondFailingPrivateModule.class.getName() + ".configure(",
+//                    asModuleChain(
+//                            FailingModule.class, ManyPrivateModules.class, SecondFailingPrivateModule.class),
+//                    "If it was in a PrivateModule, did you forget to expose the binding?",
+//                    "at " + FailingModule.class.getName() + ".configure(");
+        }
+    }
+
+    public void testParentBindingToPrivateLinkedJitBinding() {
+        Injector injector = Guice.createInjector(new ManyPrivateModules());
+        try {
+            injector.getBinding(Key.get(Types.providerOf(List.class)));
+            fail();
+        } catch(ConfigurationException expected) {
+            assertEquals(1, expected.getErrorMessages().size());
+//            assertContains(expected.toString(),
+//                    "Unable to create binding for com.google.inject.Provider<java.util.List>.",
+//                    "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<java.util.List>");
+        }
+    }
+
+    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<List> 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<List> 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<Worker> 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<Worker> 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<Worker> 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 <fishercoder@gmail.com>
Date: Mon, 18 Nov 2019 08:56:39 -0800
Subject: [PATCH 074/185] 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 <fishercoder@gmail.com>
Date: Mon, 18 Nov 2019 09:23:24 -0800
Subject: [PATCH 075/185] 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 @@
         <dependency>
             <groupId>org.projectlombok</groupId>
             <artifactId>lombok</artifactId>
-            <version>1.16.12</version>
+            <version>1.18.2</version>
             <scope>provided</scope>
         </dependency>
 

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 076/185] 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] <support@github.com>
---
 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 @@
         <dependency>
             <groupId>org.apache.logging.log4j</groupId>
             <artifactId>log4j-core</artifactId>
-            <version>2.7</version>
+            <version>2.13.2</version>
         </dependency>
 
         <dependency>

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 077/185] 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] <support@github.com>
---
 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 @@
         <dependency>
             <groupId>junit</groupId>
             <artifactId>junit</artifactId>
-            <version>4.11</version>
+            <version>4.13.1</version>
         </dependency>
 
         <!-- spring-context which provides core functionality -->

From 3154ae30d2827c1d39309c510dc5bee42633a2f4 Mon Sep 17 00:00:00 2001
From: Steve Sun <sunstev@amazon.com>
Date: Mon, 17 May 2021 11:47:53 -0700
Subject: [PATCH 078/185] 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 <fishercoder@gmail.com>
Date: Tue, 18 May 2021 09:49:45 -0700
Subject: [PATCH 079/185] 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 @@
         <version>1.11.253</version>
       </dependency>
 
+
+        <dependency>
+            <groupId>org.apache.spark</groupId>
+            <artifactId>spark-core_2.12</artifactId>
+            <version>3.1.1</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.spark</groupId>
+            <artifactId>spark-sql_2.12</artifactId>
+            <version>3.0.1</version>
+            <scope>provided</scope>
+        </dependency>
+
         <dependency>
             <groupId>com.google.inject</groupId>
             <artifactId>guice</artifactId>
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 <T> Image transform(Image in, BiFunction<Color, T, Color> 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"
+     * <p>
+     * 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 <inputFile> <outputFile>");
+            System.exit(1);
+        }
+
+        SparkSession spark = SparkSession
+                .builder()
+                .appName("SparkJob")
+                .getOrCreate();
+
+        JavaRDD<String> textFile = spark.read().textFile(args[0]).toJavaRDD();
+
+        JavaPairRDD<String, Integer> 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 <fishercoder@gmail.com>
Date: Tue, 18 May 2021 09:50:45 -0700
Subject: [PATCH 080/185] 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 <fishercoder@gmail.com>
Date: Tue, 18 May 2021 10:24:29 -0700
Subject: [PATCH 081/185] 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 @@
             <groupId>org.apache.spark</groupId>
             <artifactId>spark-sql_2.12</artifactId>
             <version>3.0.1</version>
-            <scope>provided</scope>
         </dependency>
 
         <dependency>
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"
-     * <p>
-     * 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 <inputFile> <outputFile>");
             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 <fishercoder@gmail.com>
Date: Tue, 18 May 2021 10:25:00 -0700
Subject: [PATCH 082/185] 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<String> textFile = spark.read().textFile(args[0]).toJavaRDD();

From 6c5a27ec5085e3135e5b0320dbf466a61a392b5a Mon Sep 17 00:00:00 2001
From: Fisher Coder <fishercoder@gmail.com>
Date: Tue, 18 May 2021 10:35:36 -0700
Subject: [PATCH 083/185] 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<String> textFile = spark.read().textFile(args[0]).toJavaRDD();
-
-        JavaPairRDD<String, Integer> 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<String> textFile = spark.read().textFile(args[0]).toJavaRDD();
+            System.out.println("Finished reading this textFile: " + args[0]);
+
+            JavaPairRDD<String, Integer> 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 <fishercoder@gmail.com>
Date: Tue, 18 May 2021 11:23:30 -0700
Subject: [PATCH 084/185] 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<Integer> list = new ArrayList<>(n);
+        for (int i = 0; i < n; i++) {
+            list.add(i);
+        }
+        System.out.println("Got list.size() is: " + list.size());
+
+        JavaRDD<Integer> dataSet = jsc.parallelize(list, slices);
+        System.out.println("dataSet.count() is: " + dataSet.count());
+
+        int count = dataSet.map(new Function<Integer, Integer>() {
+            @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<Integer, Integer, Integer>() {
+            @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 <fishercoder@gmail.com>
Date: Tue, 18 May 2021 14:46:53 -0700
Subject: [PATCH 085/185] 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 <fishercoder@gmail.com>
Date: Tue, 18 May 2021 15:18:01 -0700
Subject: [PATCH 086/185] 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 <fishercoder@gmail.com>
Date: Tue, 18 May 2021 15:43:51 -0700
Subject: [PATCH 087/185] 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 <fishercoder@gmail.com>
Date: Tue, 18 May 2021 15:44:14 -0700
Subject: [PATCH 088/185] 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 @@
             <version>LATEST</version>
         </dependency>
 
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-simple</artifactId>
+            <version>1.7.30</version>
+        </dependency>
 
     </dependencies>
 

From 9da1addd0396b75e6df83e7e08ce62beb46dda58 Mon Sep 17 00:00:00 2001
From: Fisher Coder <fishercoder@gmail.com>
Date: Tue, 18 May 2021 16:28:31 -0700
Subject: [PATCH 089/185] 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<Row> parquetFileDF = spark.read().parquet(args[0]);
+            JavaRDD<Row> 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 <fishercoder@gmail.com>
Date: Fri, 16 Jul 2021 10:39:27 -0700
Subject: [PATCH 090/185] 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 <fishercoder@gmail.com>
Date: Sat, 17 Jul 2021 16:43:42 -0700
Subject: [PATCH 091/185] 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 <fishercoder@gmail.com>
Date: Sat, 17 Jul 2021 16:47:29 -0700
Subject: [PATCH 092/185] 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 <sunstev@amazon.com>
Date: Sun, 1 Aug 2021 08:40:27 -0700
Subject: [PATCH 093/185] 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<Integer> threadLocal = new ThreadLocal<Integer>();
+		private ThreadLocal<Integer> threadLocal = new ThreadLocal<>();
 
 		@Override
 		public void run() {

From e3d1353dc75602f46a9db8fa173dc3bd202143d4 Mon Sep 17 00:00:00 2001
From: Fisher Coder <fishercoder@gmail.com>
Date: Sun, 1 Aug 2021 08:43:16 -0700
Subject: [PATCH 094/185] 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.
- * 
+ * <p>
  * 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:
- * 
+ * <p>
  * private ThreadLocal myThreadLocal = new ThreadLocal<String>() {
- * @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<Integer> 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<Integer> 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 <fishercoder@gmail.com>
Date: Fri, 6 Aug 2021 00:56:49 -0700
Subject: [PATCH 095/185] 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<Person> shareholders;
+
+    public DistributeProceedsServiceImpl(List<Person> shareholders) {
+        this.shareholders = shareholders;
+    }
+
+    public DistributionResponse distributeProceeds(Double proceed) {
+        Double totalClassBFunds = 0.0;
+        int totalClassBUnits = 0;
+        int totalUnits = 0;
+        for (Person person : shareholders) {
+            Map<Role, Integer> 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<Role, Integer> 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<Role, Double> 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<Role, Integer> 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<Role, Double> assumedRolesAndProceeds = person.getAssumedRolesAndProceeds();
+                    assumedRolesAndProceeds.put(role, assumedRolesAndProceeds.getOrDefault(role, 0.0) + classProceeds);
+                    person.setAssumedRolesAndProceeds(assumedRolesAndProceeds);
+                }
+            }
+        }
+
+        List<PayOutAndShareClass> 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<PayoutAndPerson> 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<Person> 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<PayoutAndPerson> payoutAndPersonList = response.payoutByPerson.payoutAndPersonList;
+        System.out.println(payoutAndPersonList.toString());
+        List<PayOutAndShareClass> payOutAndShareClassList = response.payoutByShareclass.payOutAndShareClassList;
+        System.out.println(payOutAndShareClassList.toString());
+        System.out.println("Finished running the program.");
+    }
+
+    private List<Person> initShareholders() {
+        Person alex = new Person("Alex");
+        Map<Role, Integer> alexRoles = alex.getAssumedRolesToShareCount();
+        alexRoles.put(new GeneralPartner(250l), 10);
+        alex.setAssumedRoles(alexRoles);
+
+        Person becky = new Person("Becky");
+        Map<Role, Integer> beckyRoles = becky.getAssumedRolesToShareCount();
+        beckyRoles.put(new GeneralPartner(250l), 10);
+        beckyRoles.put(new ManagingPartner(), 5);
+        becky.setAssumedRoles(beckyRoles);
+
+        Person david = new Person("David");
+        Map<Role, Integer> 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<PayoutAndPerson> payoutAndPersonList;
+
+    public PayoutByPerson(List<PayoutAndPerson> 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<PayOutAndShareClass> payOutAndShareClassList;
+
+    public PayoutByShareclass(List<PayOutAndShareClass> 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<Role, Integer> assumedRolesAndShareCount;
+    private Map<Role, Double> assumedRolesAndProceeds;
+
+    public void setAssumedRolesAndProceeds(Map<Role, Double> assumedRolesAndProceeds) {
+        this.assumedRolesAndProceeds = assumedRolesAndProceeds;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public Map<Role, Double> getAssumedRolesAndProceeds() {
+        return this.assumedRolesAndProceeds;
+    }
+
+    public void setAssumedRoles(Map<Role, Integer> assumedRoles) {
+        this.assumedRolesAndShareCount = assumedRoles;
+    }
+
+    public Map<Role, Integer> 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 096/185] 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] <support@github.com>
---
 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 @@
         <dependency>
             <groupId>org.apache.logging.log4j</groupId>
             <artifactId>log4j-api</artifactId>
-            <version>2.7</version>
+            <version>2.16.0</version>
         </dependency>
         <dependency>
             <groupId>org.apache.logging.log4j</groupId>

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 097/185] 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] <support@github.com>
---
 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 @@
         <dependency>
             <groupId>org.apache.logging.log4j</groupId>
             <artifactId>log4j-core</artifactId>
-            <version>2.13.2</version>
+            <version>2.16.0</version>
         </dependency>
 
         <dependency>

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 098/185] 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] <support@github.com>
---
 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 @@
         <dependency>
             <groupId>org.apache.logging.log4j</groupId>
             <artifactId>log4j-api</artifactId>
-            <version>2.16.0</version>
+            <version>2.17.0</version>
         </dependency>
         <dependency>
             <groupId>org.apache.logging.log4j</groupId>

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 099/185] 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] <support@github.com>
---
 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 @@
         <dependency>
             <groupId>org.apache.logging.log4j</groupId>
             <artifactId>log4j-core</artifactId>
-            <version>2.16.0</version>
+            <version>2.17.0</version>
         </dependency>
 
         <dependency>

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 100/185] 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] <support@github.com>
---
 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 @@
         <dependency>
             <groupId>org.apache.logging.log4j</groupId>
             <artifactId>log4j-core</artifactId>
-            <version>2.17.0</version>
+            <version>2.17.1</version>
         </dependency>
 
         <dependency>

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 101/185] 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] <support@github.com>
---
 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 @@
         <dependency>
             <groupId>org.apache.logging.log4j</groupId>
             <artifactId>log4j-api</artifactId>
-            <version>2.17.0</version>
+            <version>2.17.1</version>
         </dependency>
         <dependency>
             <groupId>org.apache.logging.log4j</groupId>

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 102/185] 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] <support@github.com>
---
 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 @@
         <dependency>
             <groupId>org.springframework</groupId>
             <artifactId>spring-webmvc</artifactId>
-            <version>4.1.6.RELEASE</version>
+            <version>5.3.18</version>
         </dependency>
 
         <!-- The spring-web module provides basic web-oriented integration features

From 27562d65bcc23969ed8c1730ac796e55958575b0 Mon Sep 17 00:00:00 2001
From: Fisher <fishercoder@gmail.com>
Date: Sun, 3 Jul 2022 14:12:59 -0700
Subject: [PATCH 103/185] remove unnecessary public

---
 .../java/java_async_method_example/async/method/SyncClient.java | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

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
index 88ab87b..97418ad 100644
--- a/src/main/java/java_async_method_example/async/method/SyncClient.java
+++ b/src/main/java/java_async_method_example/async/method/SyncClient.java
@@ -2,5 +2,5 @@
 
 public interface SyncClient {
 	// for synchronous
-	public void executeSynchronous(final String userId);
+	void executeSynchronous(final String userId);
 }

From 20f7700d63b1124b896930804b4bafa5a840d48f Mon Sep 17 00:00:00 2001
From: Fisher <fishercoder@gmail.com>
Date: Sun, 3 Jul 2022 14:23:12 -0700
Subject: [PATCH 104/185] enable binding

---
 src/main/java/guice/AppInjector.java | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/main/java/guice/AppInjector.java b/src/main/java/guice/AppInjector.java
index fa9b01b..296ccfe 100644
--- a/src/main/java/guice/AppInjector.java
+++ b/src/main/java/guice/AppInjector.java
@@ -10,9 +10,9 @@
 public class AppInjector extends AbstractModule {
   @Override protected void configure() {
     //bind the service to implementation class
-    //bind(MessageService.class).to(EmailService.class);
+//    bind(MessageService.class).to(EmailService.class);
 
     //bind MessageService to Facebook Message implementation
-    //bind(MessageService.class).to(FacebookService.class);
+    bind(MessageService.class).to(FacebookService.class);
   }
 }

From 72854505a91f25e3115df9485d66e17a9c592fec Mon Sep 17 00:00:00 2001
From: Fisher <fishercoder@gmail.com>
Date: Tue, 9 Aug 2022 07:27:41 -0700
Subject: [PATCH 105/185] change balance to be 100

---
 src/main/java/multithread/HusbandAndWifeJob.java | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/main/java/multithread/HusbandAndWifeJob.java b/src/main/java/multithread/HusbandAndWifeJob.java
index 44e8dab..0609591 100644
--- a/src/main/java/multithread/HusbandAndWifeJob.java
+++ b/src/main/java/multithread/HusbandAndWifeJob.java
@@ -56,7 +56,7 @@ public static void main(String[] args) {
 }
 
 class BankAccount {
-    private int balance = 100000;
+    private int balance = 100;
 
     public int getBalance() {
         return balance;

From 70fce64ebe2790cbbef168a692b4425ef4f1ab33 Mon Sep 17 00:00:00 2001
From: Fisher <fishercoder@gmail.com>
Date: Tue, 9 Aug 2022 07:40:36 -0700
Subject: [PATCH 106/185] comment out sleep logic

---
 .../java/multithread/HusbandAndWifeJob.java   | 20 +++++++++++--------
 1 file changed, 12 insertions(+), 8 deletions(-)

diff --git a/src/main/java/multithread/HusbandAndWifeJob.java b/src/main/java/multithread/HusbandAndWifeJob.java
index 0609591..bd949c5 100644
--- a/src/main/java/multithread/HusbandAndWifeJob.java
+++ b/src/main/java/multithread/HusbandAndWifeJob.java
@@ -8,7 +8,8 @@ public class HusbandAndWifeJob implements Runnable {
      * @see java.lang.Runnable#run()
      */
     @Override
-    public void run() {
+    public void run() {ite
+            
         for (int i = 0; i < 10; i++) {
             makeWithdrawl(10);
             if (bankAccount.getBalance() < 0) {
@@ -25,13 +26,16 @@ public void run() {
     private synchronized void makeWithdrawl(int amount) {
         if (bankAccount.getBalance() >= amount) {
             System.out.println(Thread.currentThread().getName() + " is about to withdraw: " + amount);
-            try {
-                System.out.println(Thread.currentThread().getName() + " is going to sleep.");
-                Thread.sleep(1000);
-            } catch (InterruptedException e) {
-                e.printStackTrace();
-            }
-            System.out.println(Thread.currentThread().getName() + " woke up.");
+
+//            this sleep block is trying to slow down the work and let you visualize what and how events occur: two threads will call makeWithdrawl() method randomly based on how the scheduler schedules it,wec you can comment it out
+//            try {
+//                System.out.println(Thread.currentThread().getName() + " is going to sleep.");
+//                Thread.sleep(1000);
+//            } catch (InterruptedException e) {
+//                e.printStackTrace();
+//            }
+//            System.out.println(Thread.currentThread().getName() + " woke up.");
+
             bankAccount.withdraw(amount);
             System.out.println(Thread.currentThread().getName() + " finished withdrawl: " + amount + "\t now the balance is: " + bankAccount.getBalance());
         } else {

From c9883a8d69e874ca41783c277f58e6323a9dbf44 Mon Sep 17 00:00:00 2001
From: Fisher <fishercoder@gmail.com>
Date: Tue, 9 Aug 2022 07:41:00 -0700
Subject: [PATCH 107/185] remove typos

---
 src/main/java/multithread/HusbandAndWifeJob.java | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/main/java/multithread/HusbandAndWifeJob.java b/src/main/java/multithread/HusbandAndWifeJob.java
index bd949c5..5d06722 100644
--- a/src/main/java/multithread/HusbandAndWifeJob.java
+++ b/src/main/java/multithread/HusbandAndWifeJob.java
@@ -8,8 +8,8 @@ public class HusbandAndWifeJob implements Runnable {
      * @see java.lang.Runnable#run()
      */
     @Override
-    public void run() {ite
-            
+    public void run() {
+
         for (int i = 0; i < 10; i++) {
             makeWithdrawl(10);
             if (bankAccount.getBalance() < 0) {

From f7cc37bb8ec6820e8df3174bd746d0eb15bb41fa Mon Sep 17 00:00:00 2001
From: Fisher <fishercoder@gmail.com>
Date: Tue, 9 Aug 2022 08:03:33 -0700
Subject: [PATCH 108/185] refactor threading example

---
 src/main/java/multithread/ThreadIsCool.java | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/src/main/java/multithread/ThreadIsCool.java b/src/main/java/multithread/ThreadIsCool.java
index f3d97b8..f062404 100644
--- a/src/main/java/multithread/ThreadIsCool.java
+++ b/src/main/java/multithread/ThreadIsCool.java
@@ -10,14 +10,14 @@ public static void main(String [] args){
 		Thread thread1 = new Thread(threadIsCool);
 		Thread thread2 = new Thread(threadIsCool);
 		Thread thread3 = new Thread(threadIsCool);
-		thread1.setName("abc");
-		thread2.setName("def");
-		thread3.setName("ghi");
+		thread1.setName("Thread Andrew");
+		thread2.setName("Thread James");
+		thread3.setName("Thread Steve");
 		System.out.println("Now the three threads kick off:");
 		
 		thread1.start();
 		try {
-		    /* Start second thread(def) only when first thread(abc) is dead*/
+		    /* Wait for this thread to die before other invocations*/
             thread1.join();
         } catch (InterruptedException e) {
             e.printStackTrace();
@@ -25,6 +25,7 @@ public static void main(String [] args){
 		
 		thread2.start();
 		try {
+			/* Wait for this thread to die before other invocations*/
             thread2.join();
         } catch (InterruptedException e) {
             e.printStackTrace();
@@ -32,6 +33,7 @@ public static void main(String [] args){
 		
 		thread3.start();
 		try {
+			/* Wait for this thread to die before other invocations*/
             thread3.join();
         } catch (InterruptedException e) {
             e.printStackTrace();
@@ -41,7 +43,7 @@ public static void main(String [] args){
 	
 	@Override
 	public void run(){
-		for(int i = 0; i < 5; i++){
+		for(int i = 0; i < 10; i++){
 			String threadName = Thread.currentThread().getName();
 			System.out.println(threadName + " is running!");
 		}
@@ -51,6 +53,7 @@ public void run(){
         } catch (InterruptedException e) {
             e.printStackTrace();
         }
+		System.out.println(Thread.currentThread().getName() + " run finished.");
 	}
 	
 }

From 0927a13742d5453463bc8f08f02085b3522d74f6 Mon Sep 17 00:00:00 2001
From: Fisher <fishercoder@gmail.com>
Date: Tue, 9 Aug 2022 08:29:31 -0700
Subject: [PATCH 109/185] refactor threading example

---
 .../java/multithread/ThreadLocalExample.java  | 19 ++++++++++---------
 1 file changed, 10 insertions(+), 9 deletions(-)

diff --git a/src/main/java/multithread/ThreadLocalExample.java b/src/main/java/multithread/ThreadLocalExample.java
index ea31a38..1a4c1b7 100644
--- a/src/main/java/multithread/ThreadLocalExample.java
+++ b/src/main/java/multithread/ThreadLocalExample.java
@@ -38,15 +38,16 @@ public void run() {
             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.");
-        }
+    }
+
+    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 c5eb4d0cd3ed50c1b87a4a8904c1deb1b2544452 Mon Sep 17 00:00:00 2001
From: Fisher <fishercoder@gmail.com>
Date: Tue, 9 Aug 2022 08:50:21 -0700
Subject: [PATCH 110/185] add thread.join()

---
 src/main/java/multithread/Worker.java | 50 ++++++++++++++++-----------
 1 file changed, 29 insertions(+), 21 deletions(-)

diff --git a/src/main/java/multithread/Worker.java b/src/main/java/multithread/Worker.java
index 3797c4c..3e23e31 100644
--- a/src/main/java/multithread/Worker.java
+++ b/src/main/java/multithread/Worker.java
@@ -10,27 +10,50 @@
 public class Worker implements Runnable {
     public boolean running = false;
 
+    @Override
+    public void run() {
+        this.running = true;
+        System.out.println("Thread " + Thread.currentThread().getName() + " is running.");
+
+        try {
+            //this pauses this spawned thread to sleep for 5 seconds.
+            System.out.println("Thread " + Thread.currentThread().getName() + " sleeps for 3 seconds");
+            Thread.sleep(3000);
+        } catch (InterruptedException e) {
+            //an InterruptedException should never be swallowed
+            Thread.currentThread().interrupt();
+        }
+        this.running = false;
+        System.out.println("Thread " + Thread.currentThread().getName() + " is no longer running.");
+    }
+
+
     public static void main(String... args) throws InterruptedException {
         Worker mainThreadWorker = new Worker();
         List<Thread> workers = new ArrayList<>();
 
-        System.out.println("Main thread is running with thread ID: " + Thread.currentThread().getId());
+        System.out.println("Main thread is running with thread ID: " + Thread.currentThread().getName());
 
         Date start = new Date();
 
         //let's start 10 workers
-        for (int i = 0; i < 10; i++){
+        for (int i = 0; i < 10; i++) {
             System.out.println("i = " + i);
             Thread thread = new Thread(mainThreadWorker);
+            thread.setName(i + "");
             workers.add(thread);
             thread.start();
+
+            //with this join() method, all 10 threads will be invoked in sequence, without it, all 10 threads will run in parallel.
+            //thread.join();
         }
+        System.out.println("There's a total of " + workers.size() + " threads.");
 
         //now we need to force the MAIN thread to wait until all Worker threads end, so we could calculate the duration
-        for (Thread worker : workers){
-            System.out.println("Checking thread " + worker.currentThread().getId() + " now.");
+        for (Thread worker : workers) {
+            System.out.println("Checking thread " + worker.currentThread().getName() + " now.");
             System.out.println("worker.isAlive() = " + worker.isAlive());
-            while (worker.isAlive()){
+            while (worker.isAlive()) {
                 Thread.sleep(1000);
             }
         }
@@ -39,21 +62,6 @@ public static void main(String... args) throws InterruptedException {
 
         Long duration = end.getTime() - start.getTime();
 
-        System.out.println("This whole process took " + duration/1000 + " seconds.");
-    }
-
-    @Override
-    public void run() {
-        this.running = true;
-        System.out.println("Thread " + Thread.currentThread().getId() + " is running.");
-
-        try {
-            //this pauses this spawned thread to sleep for 5 seconds.
-            Thread.sleep(5000);
-        } catch (InterruptedException e) {
-            //an InterruptedException should never be swallowed
-            Thread.currentThread().interrupt();
-        }
-        this.running = false;
+        System.out.println("This whole process took " + duration / 1000 + " seconds.");
     }
 }

From 8ac40a5b629f2fa62ef64fe447a02631ad6130a6 Mon Sep 17 00:00:00 2001
From: Fisher <fishercoder@gmail.com>
Date: Tue, 9 Aug 2022 10:58:36 -0700
Subject: [PATCH 111/185] add wait and notify example

---
 .../java/multithread/WaitNotifyExample.java   | 56 +++++++++++++++++++
 1 file changed, 56 insertions(+)
 create mode 100644 src/main/java/multithread/WaitNotifyExample.java

diff --git a/src/main/java/multithread/WaitNotifyExample.java b/src/main/java/multithread/WaitNotifyExample.java
new file mode 100644
index 0000000..c6b24ed
--- /dev/null
+++ b/src/main/java/multithread/WaitNotifyExample.java
@@ -0,0 +1,56 @@
+package multithread;
+
+public class WaitNotifyExample {
+    private String packet;
+
+    // True if receiver should wait
+    // False if sender should wait
+    private boolean transfer = true;
+
+    public synchronized String receive() {
+        System.out.println("In receive method now, transfer: " + transfer);
+        while (transfer) {
+            try {
+                System.out.println("waiting to receive now.");
+                wait();
+            } catch (InterruptedException e) {
+                Thread.currentThread().interrupt();
+                System.out.println("Thread Interrupted");
+            }
+        }
+        transfer = true;
+
+        String returnPacket = packet;
+        System.out.println("In receive method, notifyAll now.");
+        notifyAll();
+        System.out.println("In receive method now, returnPacket: " + returnPacket);
+        return returnPacket;
+    }
+
+    public synchronized void send(String packet) {
+        System.out.println("In send method now, transfer: " + transfer);
+        while (!transfer) {
+            try {
+                System.out.println("waiting to send now.");
+                wait();
+            } catch (InterruptedException e) {
+                Thread.currentThread().interrupt();
+                System.out.println("Thread Interrupted");
+            }
+        }
+        transfer = false;
+
+        this.packet = packet;
+        System.out.println("In send method, notifyAll now.");
+        notifyAll();
+        System.out.println("In send method now, packet: " + packet);
+    }
+
+    public static void main(String... args) {
+        System.out.println("Hello world...");
+        WaitNotifyExample waitNotifyExample = new WaitNotifyExample();
+        waitNotifyExample.send("This is a nice test packet..");
+        waitNotifyExample.receive();
+        System.out.println("Program finished...");
+    }
+}

From 4cdb2a900d1457f14d19dedcc7ee39c730826712 Mon Sep 17 00:00:00 2001
From: Fisher Coder <fishercoder@gmail.com>
Date: Sun, 18 Dec 2022 12:09:58 -0800
Subject: [PATCH 112/185] remove unused class

---
 src/main/java/sorting/BucketSort.java | 7 -------
 1 file changed, 7 deletions(-)
 delete mode 100644 src/main/java/sorting/BucketSort.java

diff --git a/src/main/java/sorting/BucketSort.java b/src/main/java/sorting/BucketSort.java
deleted file mode 100644
index 00cac8c..0000000
--- a/src/main/java/sorting/BucketSort.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package sorting;
-
-/**
- * Created by stevesun on 2/18/17.
- */
-public class BucketSort {
-}

From 4fef3e80ca5e0eaaf39789d1f333f94b8ec88a46 Mon Sep 17 00:00:00 2001
From: Fisher Coder <fishercoder@gmail.com>
Date: Sun, 18 Dec 2022 15:40:51 -0800
Subject: [PATCH 113/185] add a simple B2SdkExample class

---
 pom.xml                                       | 13 ++++++++
 .../java/b2SdkExamples/B2SdkExamples.java     | 32 +++++++++++++++++++
 2 files changed, 45 insertions(+)
 create mode 100644 src/main/java/b2SdkExamples/B2SdkExamples.java

diff --git a/pom.xml b/pom.xml
index 2fcdca3..1df0269 100644
--- a/pom.xml
+++ b/pom.xml
@@ -151,6 +151,19 @@
             <version>1.7.30</version>
         </dependency>
 
+        <dependency>
+            <groupId>com.backblaze.b2</groupId>
+            <artifactId>b2-sdk-core</artifactId>
+            <version>6.1.1</version>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.backblaze.b2</groupId>
+            <artifactId>b2-sdk-httpclient</artifactId>
+            <version>6.1.1</version>
+            <scope>compile</scope>
+        </dependency>
+
     </dependencies>
 
 
diff --git a/src/main/java/b2SdkExamples/B2SdkExamples.java b/src/main/java/b2SdkExamples/B2SdkExamples.java
new file mode 100644
index 0000000..25f51af
--- /dev/null
+++ b/src/main/java/b2SdkExamples/B2SdkExamples.java
@@ -0,0 +1,32 @@
+package b2SdkExamples;
+
+import com.backblaze.b2.client.B2StorageClient;
+import com.backblaze.b2.client.B2StorageClientFactory;
+import com.backblaze.b2.client.exceptions.B2Exception;
+import com.backblaze.b2.client.structures.B2Bucket;
+import com.backblaze.b2.client.structures.B2ListBucketsResponse;
+
+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 {
+        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
+        B2StorageClient client = B2StorageClientFactory.createDefaultFactory().create(APPLICATION_KEY_ID, APPLICATION_KEY, USER_AGENT);
+        B2ListBucketsResponse b2ListBucketsResponse = client.listBuckets();
+        List<B2Bucket> 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());
+        }
+        System.out.println("Finished running in main method.");
+    }
+}

From 0fdb95586edb1b26b3dfb9f8e0ea736c0a3ff8dc Mon Sep 17 00:00:00 2001
From: Fisher Coder <fishercoder@gmail.com>
Date: Sun, 18 Dec 2022 15:41:32 -0800
Subject: [PATCH 114/185] add a simple B2Json test

---
 src/test/b2SdkExamples/B2JsonTest.java | 57 ++++++++++++++++++++++++++
 1 file changed, 57 insertions(+)
 create mode 100644 src/test/b2SdkExamples/B2JsonTest.java

diff --git a/src/test/b2SdkExamples/B2JsonTest.java b/src/test/b2SdkExamples/B2JsonTest.java
new file mode 100644
index 0000000..ccab0a8
--- /dev/null
+++ b/src/test/b2SdkExamples/B2JsonTest.java
@@ -0,0 +1,57 @@
+package b2SdkExamples;
+
+import com.backblaze.b2.json.B2Json;
+import com.backblaze.b2.json.B2JsonException;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Reference: https://github.com/Backblaze/b2-sdk-java/blob/0ecd68df94691cbba5a6af363246b7193aead234/core/src/test/java/com/backblaze/b2/json/B2JsonTest.java
+ */
+public class B2JsonTest {
+    private static final class Container {
+
+        @B2Json.required
+        public final int a;
+
+        @B2Json.optional
+        public final String b;
+
+        @B2Json.ignored
+        public int c;
+
+        @B2Json.constructor(params = "a, b")
+        public Container(int a, String b) {
+            this.a = a;
+            this.b = b;
+            this.c = 5;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (!(o instanceof Container)) {
+                return false;
+            }
+            Container other = (Container) o;
+            return a == other.a && (b == null ? other.b == null : b.equals(other.b));
+        }
+    }
+
+    private static final B2Json b2Json = B2Json.get();
+
+    @Test
+    public void testObject() throws B2JsonException {
+        String json =
+                "{\n" +
+                        "  \"a\": 41,\n" +
+                        "  \"b\": \"hello\"\n" +
+                        "}";
+        Container obj = new Container(41, "hello");
+        assertEquals(json, b2Json.toJson(obj));
+        System.out.println("obj is: " + obj);
+        System.out.println("json is: " + json);
+        assertEquals(obj, b2Json.fromJson(json, Container.class));
+    }
+
+}

From 5bb66ab49ae4c52603ba8e9ccd1a0770af43b90d Mon Sep 17 00:00:00 2001
From: Fisher Coder <fishercoder@gmail.com>
Date: Mon, 19 Dec 2022 09:04:17 -0800
Subject: [PATCH 115/185] update tests

---
 src/test/b2SdkExamples/B2JsonTest.java | 145 +++++++++++++++++++++++++
 1 file changed, 145 insertions(+)

diff --git a/src/test/b2SdkExamples/B2JsonTest.java b/src/test/b2SdkExamples/B2JsonTest.java
index ccab0a8..76bc1b5 100644
--- a/src/test/b2SdkExamples/B2JsonTest.java
+++ b/src/test/b2SdkExamples/B2JsonTest.java
@@ -2,14 +2,42 @@
 
 import com.backblaze.b2.json.B2Json;
 import com.backblaze.b2.json.B2JsonException;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
 import org.junit.Test;
 
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
 import static org.junit.Assert.assertEquals;
 
 /**
  * Reference: https://github.com/Backblaze/b2-sdk-java/blob/0ecd68df94691cbba5a6af363246b7193aead234/core/src/test/java/com/backblaze/b2/json/B2JsonTest.java
  */
 public class B2JsonTest {
+
+    private static final LocalDateTime LOCAL_DATE_TIME = LocalDateTime.of(2022, 12, 18, 16, 21);
+    private static final LocalDate LOCAL_DATE = LocalDate.of(2022, 12, 18);
+
+    private static final String JSON_STRING_1 = "{\n" +
+//            "  \"localDate\": \"20221218\",\n" +
+//            "  \"localDateTime\": \"d20221218_m162100\",\n" +
+            "  \"message\": \"message\",\n" +
+            "  \"str\": 123,\n" +
+            "  \"reason\": \"A TEST STRING FOR REASON\"\n" +
+            "}";
+
+    private static final String JSON_STRING_2 = "{\n" +
+            "  \"aMessage\": \"aMessage\",\n" +
+            "  \"bMessage\": \"bMessage\",\n" +
+            "  \"message\": \"message\",\n" +
+            "  \"pMessage\": \"pMessage\",\n" +
+            "  \"reason\": \"A TEST STRING FOR REASON\",\n" +
+            "  \"str\": 123,\n" +
+            "  \"zMessage\": \"zMessage\"\n" +
+            "}";
+    private static final String REASON_STR = "A TEST STRING FOR REASON";
+
     private static final class Container {
 
         @B2Json.required
@@ -39,6 +67,103 @@ public boolean equals(Object o) {
     }
 
     private static final B2Json b2Json = B2Json.get();
+    private static final Gson gson = (new GsonBuilder())
+            .disableHtmlEscaping()
+            .setPrettyPrinting().create();
+
+    private static class TestRequest {
+        @B2Json.optional(omitNull = true)
+        public final Integer str;
+
+        @B2Json.optional(omitNull = true)
+        public final String message;
+
+        @B2Json.optional(omitNull = true)
+        public final String aMessage;
+
+        @B2Json.optional(omitNull = true)
+        public final String bMessage;
+
+        @B2Json.optional(omitNull = true)
+        public final String pMessage;
+
+        @B2Json.optional(omitNull = true)
+        public final String zMessage;
+
+        @B2Json.optional(omitNull = true)
+        public final LocalDateTime localDateTime;
+
+        @B2Json.optional(omitNull = true)
+        public final LocalDate localDate;
+
+        @B2Json.optional(omitNull = true)
+        public final String reason;
+
+        @B2Json.constructor(params = "" +
+                "str," +
+                "message," +
+                "aMessage," +
+                "bMessage," +
+                "pMessage," +
+                "zMessage," +
+                "localDateTime," +
+                "localDate," +
+                "reason"
+        )
+        public TestRequest(Integer str, String message, String aMessage, String bMessage, String pMessage, String zMessage, LocalDateTime localDateTime, LocalDate localDate, String reason) {
+            this.str = str;
+            this.message = message;
+            this.aMessage = aMessage;
+            this.bMessage = bMessage;
+            this.pMessage = pMessage;
+            this.zMessage = zMessage;
+            this.localDateTime = localDateTime;
+            this.localDate = localDate;
+            this.reason = reason;
+        }
+    }
+
+    private static class TestResponse {
+        @B2Json.optional(omitNull = true)
+        public final String str;
+
+        @B2Json.optional(omitNull = true)
+        public final String message;
+
+        @B2Json.optional(omitNull = true)
+        public final String reason;
+
+        @B2Json.optional(omitNull = true)
+        public final Boolean succeeded;
+
+        @B2Json.optional(omitNull = true)
+        public final Integer status;
+
+        @B2Json.optional(omitNull = true)
+        public final LocalDateTime localDateTime;
+
+        @B2Json.optional(omitNull = true)
+        public final LocalDate localDate;
+
+        @B2Json.constructor(params = "" +
+                "str," +
+                "message," +
+                "reason," +
+                "succeeded," +
+                "status," +
+                "localDateTime," +
+                "localDate"
+        )
+        public TestResponse(String str, String message, String reason, boolean succeeded, int status, LocalDateTime localDateTime, LocalDate localDate) {
+            this.str = str;
+            this.message = message;
+            this.reason = reason;
+            this.succeeded = succeeded;
+            this.status = status;
+            this.localDateTime = localDateTime;
+            this.localDate = localDate;
+        }
+    }
 
     @Test
     public void testObject() throws B2JsonException {
@@ -54,4 +179,24 @@ public void testObject() throws B2JsonException {
         assertEquals(obj, b2Json.fromJson(json, Container.class));
     }
 
+    @Test
+    public void testRequestUsingB2Json() throws B2JsonException {
+        //B2Json always reorders the fields in the object in alphabetical order
+        TestRequest obj = new TestRequest(123, "message", "aMessage", "bMessage", "pMessage", "zMessage", null, null, REASON_STR);
+        assertEquals(JSON_STRING_2, b2Json.toJson(obj));
+        System.out.println("obj is: " + obj);
+        System.out.println("json is: " + JSON_STRING_2);
+//        assertEquals(obj, b2Json.fromJson(JSON_STRING_2, TestRequest.class));
+    }
+
+    @Test
+    public void testRequestUsingGson() {
+        //GSON deserializes object fields in their given order in the constructor
+        TestRequest obj = new TestRequest(123, "message", "aMessage", "bMessage", "pMessage", "zMessage", null, null, REASON_STR);
+//        assertEquals(JSON_STRING_2, gson.toJson(obj));
+        System.out.println("obj is: " + obj);
+        System.out.println("json is: " + JSON_STRING_2);
+//        assertEquals(obj, gson.fromJson(JSON_STRING_2, TestRequest.class));
+    }
+
 }

From ba157aaf609498e81b16bb425de224778f0aa812 Mon Sep 17 00:00:00 2001
From: Fisher Coder <fishercoder@gmail.com>
Date: Wed, 21 Dec 2022 14:20:28 -0800
Subject: [PATCH 116/185] use SkyScreamer library to compare json objects
 ignoring fields ordering

---
 pom.xml                                |  7 ++++++
 src/test/b2SdkExamples/B2JsonTest.java | 32 +++++++++++++++++++-------
 2 files changed, 31 insertions(+), 8 deletions(-)

diff --git a/pom.xml b/pom.xml
index 1df0269..04b5456 100644
--- a/pom.xml
+++ b/pom.xml
@@ -164,6 +164,13 @@
             <scope>compile</scope>
         </dependency>
 
+        <dependency>
+            <groupId>org.skyscreamer</groupId>
+            <artifactId>jsonassert</artifactId>
+            <version>1.5.1</version>
+            <scope>test</scope>
+        </dependency>
+
     </dependencies>
 
 
diff --git a/src/test/b2SdkExamples/B2JsonTest.java b/src/test/b2SdkExamples/B2JsonTest.java
index 76bc1b5..8196b9a 100644
--- a/src/test/b2SdkExamples/B2JsonTest.java
+++ b/src/test/b2SdkExamples/B2JsonTest.java
@@ -4,7 +4,9 @@
 import com.backblaze.b2.json.B2JsonException;
 import com.google.gson.Gson;
 import com.google.gson.GsonBuilder;
+import org.json.JSONException;
 import org.junit.Test;
+import org.skyscreamer.jsonassert.JSONAssert;
 
 import java.time.LocalDate;
 import java.time.LocalDateTime;
@@ -180,23 +182,37 @@ public void testObject() throws B2JsonException {
     }
 
     @Test
-    public void testRequestUsingB2Json() throws B2JsonException {
+    public void testRequestUsingB2Json() throws B2JsonException, JSONException {
         //B2Json always reorders the fields in the object in alphabetical order
         TestRequest obj = new TestRequest(123, "message", "aMessage", "bMessage", "pMessage", "zMessage", null, null, REASON_STR);
-        assertEquals(JSON_STRING_2, b2Json.toJson(obj));
         System.out.println("obj is: " + obj);
-        System.out.println("json is: " + JSON_STRING_2);
-//        assertEquals(obj, b2Json.fromJson(JSON_STRING_2, TestRequest.class));
+        String expected = "{\n" +
+                "  \"aMessage\": \"aMessage\",\n" +
+                "  \"bMessage\": \"bMessage\",\n" +
+                "  \"message\": \"message\",\n" +
+                "  \"pMessage\": \"pMessage\",\n" +
+                "  \"reason\": \"A TEST STRING FOR REASON\",\n" +
+                "  \"str\": 123,\n" +
+                "  \"zMessage\": \"zMessage\"\n" +
+                "}";
+        JSONAssert.assertEquals(expected, b2Json.toJson(obj), true);
     }
 
     @Test
-    public void testRequestUsingGson() {
+    public void testRequestUsingGson() throws JSONException {
         //GSON deserializes object fields in their given order in the constructor
         TestRequest obj = new TestRequest(123, "message", "aMessage", "bMessage", "pMessage", "zMessage", null, null, REASON_STR);
-//        assertEquals(JSON_STRING_2, gson.toJson(obj));
         System.out.println("obj is: " + obj);
-        System.out.println("json is: " + JSON_STRING_2);
-//        assertEquals(obj, gson.fromJson(JSON_STRING_2, TestRequest.class));
+        String expected = "{\n" +
+                "  \"aMessage\": \"aMessage\",\n" +
+                "  \"bMessage\": \"bMessage\",\n" +
+                "  \"message\": \"message\",\n" +
+                "  \"pMessage\": \"pMessage\",\n" +
+                "  \"reason\": \"A TEST STRING FOR REASON\",\n" +
+                "  \"str\": 123,\n" +
+                "  \"zMessage\": \"zMessage\"\n" +
+                "}";
+        JSONAssert.assertEquals(expected, gson.toJson(obj), false);
     }
 
 }

From b3100af9e2c44bce7ab5d65cb66df07e373efd46 Mon Sep 17 00:00:00 2001
From: Fisher Coder <fishercoder@gmail.com>
Date: Fri, 13 Jan 2023 15:14:58 -0800
Subject: [PATCH 117/185] add test for @B2Json.optionalWithDefault annotation

---
 src/test/b2SdkExamples/B2JsonTest.java | 68 +++++++++++++++++++++-----
 1 file changed, 55 insertions(+), 13 deletions(-)

diff --git a/src/test/b2SdkExamples/B2JsonTest.java b/src/test/b2SdkExamples/B2JsonTest.java
index 8196b9a..6b55dee 100644
--- a/src/test/b2SdkExamples/B2JsonTest.java
+++ b/src/test/b2SdkExamples/B2JsonTest.java
@@ -10,6 +10,7 @@
 
 import java.time.LocalDate;
 import java.time.LocalDateTime;
+import java.util.Objects;
 
 import static org.junit.Assert.assertEquals;
 
@@ -51,20 +52,29 @@ private static final class Container {
         @B2Json.ignored
         public int c;
 
-        @B2Json.constructor(params = "a, b")
-        public Container(int a, String b) {
+        @B2Json.optionalWithDefault(defaultValue = "0")
+        public int d;
+
+        @B2Json.constructor(params = "a, b, d")
+        public Container(int a, String b, int d) {
             this.a = a;
             this.b = b;
             this.c = 5;
+            this.d = d;
         }
 
         @Override
         public boolean equals(Object o) {
-            if (!(o instanceof Container)) {
-                return false;
-            }
-            Container other = (Container) o;
-            return a == other.a && (b == null ? other.b == null : b.equals(other.b));
+            System.out.println("Entered overridden equals() method to check now...");
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+            Container container = (Container) o;
+            return a == container.a && d == container.d && Objects.equals(b, container.b);
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(a, b, c, d);
         }
     }
 
@@ -169,18 +179,50 @@ public TestResponse(String str, String message, String reason, boolean succeeded
 
     @Test
     public void testObject() throws B2JsonException {
-        String json =
-                "{\n" +
-                        "  \"a\": 41,\n" +
-                        "  \"b\": \"hello\"\n" +
-                        "}";
-        Container obj = new Container(41, "hello");
+        String json = "{\n" +
+                "  \"a\": 41,\n" +
+                "  \"b\": \"hello\",\n" +
+                "  \"d\": 15\n" +
+                "}";
+        Container obj = new Container(41, "hello", 15);
         assertEquals(json, b2Json.toJson(obj));
         System.out.println("obj is: " + obj);
         System.out.println("json is: " + json);
         assertEquals(obj, b2Json.fromJson(json, Container.class));
     }
 
+    @Test
+    public void testObjectUsingDefaultValue() throws B2JsonException {
+        //in this json string, there's no field d which is an optional field with a default value
+        String json = "{\n" +
+                "  \"a\": 2023,\n" +
+                "  \"b\": \"hello\"\n" +
+                "}";
+        System.out.println("json is: " + json);
+        Container fromB2Json = b2Json.fromJson(json, Container.class);
+        System.out.println("b2Json.fromJson(json, Container.class) is: " + fromB2Json);
+        Container fromGson = gson.fromJson(json, Container.class);
+        System.out.println("gson.fromJson(json) is: " + fromGson);
+        System.out.println("about to check the equality between Gson and B2Json results..");
+        assertEquals(fromGson, fromB2Json);
+        String fromB2JsonString = b2Json.toJson(fromB2Json);
+        String fromGsonString = gson.toJson(fromB2Json);
+        String expectedFromGson = "{\n" +
+                "  \"a\": 2023,\n" +
+                "  \"b\": \"hello\",\n" +
+                "  \"c\": 5,\n" +
+                "  \"d\": 0\n" +
+                "}";
+        assertEquals(expectedFromGson, fromGsonString);
+        //there's no field c as it's annotated by B2Json.ignored
+        String expectedFromB2Json = "{\n" +
+                "  \"a\": 2023,\n" +
+                "  \"b\": \"hello\",\n" +
+                "  \"d\": 0\n" +
+                "}";
+        assertEquals(expectedFromB2Json, fromB2JsonString);
+    }
+
     @Test
     public void testRequestUsingB2Json() throws B2JsonException, JSONException {
         //B2Json always reorders the fields in the object in alphabetical order

From 7c5c5fce85772c21006574a19b3c4ad36710e5cf Mon Sep 17 00:00:00 2001
From: Fisher Coder <fishercoder@gmail.com>
Date: Fri, 31 Mar 2023 11:11:24 -0700
Subject: [PATCH 118/185] remove unnecessary constructor params annotations

---
 src/test/b2SdkExamples/B2JsonTest.java | 12 +-----------
 1 file changed, 1 insertion(+), 11 deletions(-)

diff --git a/src/test/b2SdkExamples/B2JsonTest.java b/src/test/b2SdkExamples/B2JsonTest.java
index 6b55dee..baba77e 100644
--- a/src/test/b2SdkExamples/B2JsonTest.java
+++ b/src/test/b2SdkExamples/B2JsonTest.java
@@ -111,17 +111,7 @@ private static class TestRequest {
         @B2Json.optional(omitNull = true)
         public final String reason;
 
-        @B2Json.constructor(params = "" +
-                "str," +
-                "message," +
-                "aMessage," +
-                "bMessage," +
-                "pMessage," +
-                "zMessage," +
-                "localDateTime," +
-                "localDate," +
-                "reason"
-        )
+        @B2Json.constructor
         public TestRequest(Integer str, String message, String aMessage, String bMessage, String pMessage, String zMessage, LocalDateTime localDateTime, LocalDate localDate, String reason) {
             this.str = str;
             this.message = message;

From aa027203e3dd78efceb0eccff1afc78a592f002d Mon Sep 17 00:00:00 2001
From: Fisher Coder <fishercoder@gmail.com>
Date: Fri, 31 Mar 2023 11:12:26 -0700
Subject: [PATCH 119/185] undo remove unnecessary constructor params
 annotations

---
 src/test/b2SdkExamples/B2JsonTest.java | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/src/test/b2SdkExamples/B2JsonTest.java b/src/test/b2SdkExamples/B2JsonTest.java
index baba77e..6b55dee 100644
--- a/src/test/b2SdkExamples/B2JsonTest.java
+++ b/src/test/b2SdkExamples/B2JsonTest.java
@@ -111,7 +111,17 @@ private static class TestRequest {
         @B2Json.optional(omitNull = true)
         public final String reason;
 
-        @B2Json.constructor
+        @B2Json.constructor(params = "" +
+                "str," +
+                "message," +
+                "aMessage," +
+                "bMessage," +
+                "pMessage," +
+                "zMessage," +
+                "localDateTime," +
+                "localDate," +
+                "reason"
+        )
         public TestRequest(Integer str, String message, String aMessage, String bMessage, String pMessage, String zMessage, LocalDateTime localDateTime, LocalDate localDate, String reason) {
             this.str = str;
             this.message = message;

From 68d78651bc146ab34db040badaca6dd2107a80bf Mon Sep 17 00:00:00 2001
From: Fisher Coder <fishercoder@gmail.com>
Date: Tue, 25 Apr 2023 18:09:23 -0700
Subject: [PATCH 120/185] add a test

---
 pom.xml                                |   4 +-
 src/test/b2SdkExamples/B2JsonTest.java | 110 ++++++++++++++++++++++++-
 2 files changed, 109 insertions(+), 5 deletions(-)

diff --git a/pom.xml b/pom.xml
index 04b5456..19ea5be 100644
--- a/pom.xml
+++ b/pom.xml
@@ -8,8 +8,8 @@
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-compiler-plugin</artifactId>
                 <configuration>
-                    <source>1.8</source>
-                    <target>1.8</target>
+                    <source>9</source>
+                    <target>9</target>
                 </configuration>
             </plugin>
         </plugins>
diff --git a/src/test/b2SdkExamples/B2JsonTest.java b/src/test/b2SdkExamples/B2JsonTest.java
index 6b55dee..7b71a5c 100644
--- a/src/test/b2SdkExamples/B2JsonTest.java
+++ b/src/test/b2SdkExamples/B2JsonTest.java
@@ -5,12 +5,14 @@
 import com.google.gson.Gson;
 import com.google.gson.GsonBuilder;
 import org.json.JSONException;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.skyscreamer.jsonassert.JSONAssert;
 
+import java.math.BigDecimal;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
-import java.util.Objects;
+import java.util.*;
 
 import static org.junit.Assert.assertEquals;
 
@@ -157,6 +159,15 @@ private static class TestResponse {
         @B2Json.optional(omitNull = true)
         public final LocalDate localDate;
 
+        @B2Json.required
+        public final Map<Integer, Map<String, BigDecimal>> revenueMap;
+
+        @B2Json.required
+        public final Map<String, Long> simpleMap;
+
+        @B2Json.required
+        public final Set<String> categories;
+
         @B2Json.constructor(params = "" +
                 "str," +
                 "message," +
@@ -164,9 +175,15 @@ private static class TestResponse {
                 "succeeded," +
                 "status," +
                 "localDateTime," +
-                "localDate"
+                "localDate," +
+                "revenueMap," +
+                "simpleMap," +
+                "categories"
         )
-        public TestResponse(String str, String message, String reason, boolean succeeded, int status, LocalDateTime localDateTime, LocalDate localDate) {
+        public TestResponse(String str, String message, String reason, boolean succeeded, int status, LocalDateTime localDateTime, LocalDate localDate,
+                            Map<Integer, Map<String, BigDecimal>> revenueMap,
+                            Map<String, Long> simpleMap,
+                            Set<String> categories) {
             this.str = str;
             this.message = message;
             this.reason = reason;
@@ -174,9 +191,96 @@ public TestResponse(String str, String message, String reason, boolean succeeded
             this.status = status;
             this.localDateTime = localDateTime;
             this.localDate = localDate;
+            this.simpleMap = simpleMap;
+            this.revenueMap = revenueMap;
+            this.categories = categories;
         }
     }
 
+//    @Test
+//    public void testResponseUsingB2Json() throws B2JsonException, JSONException {
+//        Map<String, Map<String, BigDecimal>> revenueMap = new TreeMap<>();
+//        Map<String, Long> simpleMap = new TreeMap<>();
+//        TestResponse obj = new TestResponse("str",
+//                "message",
+//                "reason",
+//                true,
+//                200,
+//                LocalDateTime.of(2023, 03, 31, 12, 21),
+//                LocalDate.of(2023, 03, 31),
+//                revenueMap,
+//                simpleMap,
+//                Set.of("test"));
+//        System.out.println("obj is: " + obj);
+//        String expected = "{\n" +
+//                "  \"categories\": [\n" +
+//                "    \"test\"\n" +
+//                "  ],\n" +
+//                "  \"localDate\": \"20230331\",\n" +
+//                "  \"localDateTime\": \"d20230331_m122100\",\n" +
+//                "  \"message\": \"message\",\n" +
+//                "  \"reason\": \"reason\",\n" +
+//                "  \"revenueMap\": {},\n" +
+//                "  \"simpleMap\": {},\n" +
+//                "  \"status\": 200,\n" +
+//                "  \"str\": \"str\",\n" +
+//                "  \"succeeded\": true\n" +
+//                "}";
+//        System.out.println("b2Json.toJson(obj): " + b2Json.toJson(obj));
+//        JSONAssert.assertEquals(expected, b2Json.toJson(obj), true);
+//    }
+
+    @Test
+    @Ignore
+    public void testResponseUsingGson() throws JSONException {
+        Map<Integer, Map<String, BigDecimal>> revenueMap = new TreeMap<>();
+        revenueMap.put(123, new HashMap<>());
+        Map<String, Long> simpleMap = new TreeMap<>();
+        TestResponse obj = new TestResponse("str",
+                "message",
+                "reason",
+                true,
+                200,
+                LocalDateTime.of(2023, 03, 31, 12, 21),
+                LocalDate.of(2023, 03, 31),
+                revenueMap,
+                simpleMap,
+                Set.of("test"));
+        System.out.println("obj is: " + obj);
+        String expected = "{\n" +
+                "  \"str\": \"str\",\n" +
+                "  \"message\": \"message\",\n" +
+                "  \"reason\": \"reason\",\n" +
+                "  \"succeeded\": true,\n" +
+                "  \"status\": 200,\n" +
+                "  \"localDateTime\": {\n" +
+                "    \"date\": {\n" +
+                "      \"year\": 2023,\n" +
+                "      \"month\": 3,\n" +
+                "      \"day\": 31\n" +
+                "    },\n" +
+                "    \"time\": {\n" +
+                "      \"hour\": 12,\n" +
+                "      \"minute\": 21,\n" +
+                "      \"second\": 0,\n" +
+                "      \"nano\": 0\n" +
+                "    }\n" +
+                "  },\n" +
+                "  \"localDate\": {\n" +
+                "    \"year\": 2023,\n" +
+                "    \"month\": 3,\n" +
+                "    \"day\": 31\n" +
+                "  },\n" +
+                "  \"revenueMap\": {},\n" +
+                "  \"simpleMap\": {},\n" +
+                "  \"categories\": [\n" +
+                "    \"test\"\n" +
+                "  ]\n" +
+                "}";
+        System.out.println("b2Json.toJson(obj): " + gson.toJson(obj));
+        JSONAssert.assertEquals(expected, gson.toJson(obj), true);
+    }
+
     @Test
     public void testObject() throws B2JsonException {
         String json = "{\n" +

From a356feaf12a96c7bb17e6f571bcb913a0702b0d3 Mon Sep 17 00:00:00 2001
From: Fisher Coder <fishercoder@gmail.com>
Date: Tue, 25 Apr 2023 18:30:12 -0700
Subject: [PATCH 121/185] add two tests for B2Json exceptions

---
 src/test/b2SdkExamples/B2JsonTest.java | 42 ++++++++++++++++++++++++++
 1 file changed, 42 insertions(+)

diff --git a/src/test/b2SdkExamples/B2JsonTest.java b/src/test/b2SdkExamples/B2JsonTest.java
index 7b71a5c..3eb9fea 100644
--- a/src/test/b2SdkExamples/B2JsonTest.java
+++ b/src/test/b2SdkExamples/B2JsonTest.java
@@ -4,6 +4,7 @@
 import com.backblaze.b2.json.B2JsonException;
 import com.google.gson.Gson;
 import com.google.gson.GsonBuilder;
+import org.json.JSONArray;
 import org.json.JSONException;
 import org.junit.Ignore;
 import org.junit.Test;
@@ -15,6 +16,7 @@
 import java.util.*;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThrows;
 
 /**
  * Reference: https://github.com/Backblaze/b2-sdk-java/blob/0ecd68df94691cbba5a6af363246b7193aead234/core/src/test/java/com/backblaze/b2/json/B2JsonTest.java
@@ -361,4 +363,44 @@ public void testRequestUsingGson() throws JSONException {
         JSONAssert.assertEquals(expected, gson.toJson(obj), false);
     }
 
+    @Test
+    public void testRequest2UsingB2Json() {
+        /**
+         * the field zip is declared as an Integer, but we are passing in a string, in this case
+         * it throws com.backblaze.b2.json.B2JsonException: Bad number
+         * */
+        String request2Json = "{\n" + "\"zip\": \"95148\"\n" + "}";
+        assertThrows(B2JsonException.class, () -> b2Json.fromJson(request2Json, TestRequest2.class));
+    }
+
+    private static class TestRequest2 {
+        @B2Json.optional(omitNull = true)
+        public final Integer zip;
+
+        @B2Json.constructor(params = "zip")
+        public TestRequest2(Integer zip) {
+            this.zip = zip;
+        }
+    }
+
+    @Test
+    public void testRequest3UsingB2Json() {
+        /**
+         * the field zip is declared as a String, but we are passing in an Integer
+         * in this case, it throws: com.backblaze.b2.json.B2JsonException: string does not start with quote
+         * */
+        String request2Json = "{\n" + "\"zip\": 95148\n" + "}";
+        assertThrows(B2JsonException.class, () -> b2Json.fromJson(request2Json, TestRequest3.class));
+    }
+
+    private static class TestRequest3 {
+        @B2Json.optional(omitNull = true)
+        public final String zip;
+
+        @B2Json.constructor(params = "zip")
+        public TestRequest3(String zip) {
+            this.zip = zip;
+        }
+    }
+
 }

From 2b0a8643a7601260abc919b2e3bacdd2a25293da Mon Sep 17 00:00:00 2001
From: Fisher Coder <fishercoder@gmail.com>
Date: Sat, 29 Apr 2023 17:55:08 -0700
Subject: [PATCH 122/185] add LocalDateTime examples

---
 .../randomExamples/DateVsLocalDateTime.java   | 23 +++++++++++++++++++
 1 file changed, 23 insertions(+)
 create mode 100644 src/main/java/randomExamples/DateVsLocalDateTime.java

diff --git a/src/main/java/randomExamples/DateVsLocalDateTime.java b/src/main/java/randomExamples/DateVsLocalDateTime.java
new file mode 100644
index 0000000..3354dc8
--- /dev/null
+++ b/src/main/java/randomExamples/DateVsLocalDateTime.java
@@ -0,0 +1,23 @@
+package randomExamples;
+
+import java.time.LocalDateTime;
+import java.util.Date;
+
+public class DateVsLocalDateTime {
+    public static void main(String... args) throws InterruptedException {
+        Date startDate = new Date();
+        LocalDateTime startLocalDateTime = LocalDateTime.now();
+        System.out.println("date is: " + startDate);
+        System.out.println("localDateTime is: " + startLocalDateTime);
+        Thread.sleep(1000);
+        Date endDate = new Date();
+        LocalDateTime endLocalDateTime = LocalDateTime.now();
+        System.out.println("date is: " + endDate);
+        System.out.println("localDateTime is: " + endLocalDateTime);
+
+        long duration1 = ((endDate.getTime() - startDate.getTime()) / 1000);
+        long duration2 = (endLocalDateTime.getSecond() - startLocalDateTime.getSecond());
+        System.out.println("duration1 is: " + duration1);
+        System.out.println("duration2 is: " + duration2);
+    }
+}

From 5eb9e1148c7fbbd73dcf4ef66700b2dd52674ad8 Mon Sep 17 00:00:00 2001
From: Fisher Coder <fishercoder@gmail.com>
Date: Sat, 29 Apr 2023 18:03:35 -0700
Subject: [PATCH 123/185] fix B2Json tests

---
 src/test/b2SdkExamples/B2JsonTest.java | 82 +++++++++++++-------------
 1 file changed, 40 insertions(+), 42 deletions(-)

diff --git a/src/test/b2SdkExamples/B2JsonTest.java b/src/test/b2SdkExamples/B2JsonTest.java
index 3eb9fea..a4837ce 100644
--- a/src/test/b2SdkExamples/B2JsonTest.java
+++ b/src/test/b2SdkExamples/B2JsonTest.java
@@ -4,9 +4,7 @@
 import com.backblaze.b2.json.B2JsonException;
 import com.google.gson.Gson;
 import com.google.gson.GsonBuilder;
-import org.json.JSONArray;
 import org.json.JSONException;
-import org.junit.Ignore;
 import org.junit.Test;
 import org.skyscreamer.jsonassert.JSONAssert;
 
@@ -162,7 +160,7 @@ private static class TestResponse {
         public final LocalDate localDate;
 
         @B2Json.required
-        public final Map<Integer, Map<String, BigDecimal>> revenueMap;
+        public final Map<String, Map<String, BigDecimal>> revenueMap;
 
         @B2Json.required
         public final Map<String, Long> simpleMap;
@@ -183,7 +181,7 @@ private static class TestResponse {
                 "categories"
         )
         public TestResponse(String str, String message, String reason, boolean succeeded, int status, LocalDateTime localDateTime, LocalDate localDate,
-                            Map<Integer, Map<String, BigDecimal>> revenueMap,
+                            Map<String, Map<String, BigDecimal>> revenueMap,
                             Map<String, Long> simpleMap,
                             Set<String> categories) {
             this.str = str;
@@ -199,44 +197,44 @@ public TestResponse(String str, String message, String reason, boolean succeeded
         }
     }
 
-//    @Test
-//    public void testResponseUsingB2Json() throws B2JsonException, JSONException {
-//        Map<String, Map<String, BigDecimal>> revenueMap = new TreeMap<>();
-//        Map<String, Long> simpleMap = new TreeMap<>();
-//        TestResponse obj = new TestResponse("str",
-//                "message",
-//                "reason",
-//                true,
-//                200,
-//                LocalDateTime.of(2023, 03, 31, 12, 21),
-//                LocalDate.of(2023, 03, 31),
-//                revenueMap,
-//                simpleMap,
-//                Set.of("test"));
-//        System.out.println("obj is: " + obj);
-//        String expected = "{\n" +
-//                "  \"categories\": [\n" +
-//                "    \"test\"\n" +
-//                "  ],\n" +
-//                "  \"localDate\": \"20230331\",\n" +
-//                "  \"localDateTime\": \"d20230331_m122100\",\n" +
-//                "  \"message\": \"message\",\n" +
-//                "  \"reason\": \"reason\",\n" +
-//                "  \"revenueMap\": {},\n" +
-//                "  \"simpleMap\": {},\n" +
-//                "  \"status\": 200,\n" +
-//                "  \"str\": \"str\",\n" +
-//                "  \"succeeded\": true\n" +
-//                "}";
-//        System.out.println("b2Json.toJson(obj): " + b2Json.toJson(obj));
-//        JSONAssert.assertEquals(expected, b2Json.toJson(obj), true);
-//    }
+    @Test
+    public void testResponseUsingB2Json() throws B2JsonException, JSONException {
+        Map<String, Map<String, BigDecimal>> revenueMap = new TreeMap<>();
+        Map<String, Long> simpleMap = new TreeMap<>();
+        TestResponse obj = new TestResponse("str",
+                "message",
+                "reason",
+                true,
+                200,
+                LocalDateTime.of(2023, 03, 31, 12, 21),
+                LocalDate.of(2023, 03, 31),
+                revenueMap,
+                simpleMap,
+                Set.of("test1", "test2"));
+        System.out.println("obj is: " + obj);
+        String expected = "{\n" +
+                "  \"categories\": [\n" +
+                "    \"test1\",\n" +
+                "    \"test2\"\n" +
+                "  ],\n" +
+                "  \"localDate\": \"20230331\",\n" +
+                "  \"localDateTime\": \"d20230331_m122100\",\n" +
+                "  \"message\": \"message\",\n" +
+                "  \"reason\": \"reason\",\n" +
+                "  \"revenueMap\": {},\n" +
+                "  \"simpleMap\": {},\n" +
+                "  \"status\": 200,\n" +
+                "  \"str\": \"str\",\n" +
+                "  \"succeeded\": true\n" +
+                "}";
+        System.out.println("b2Json.toJson(obj): " + b2Json.toJson(obj));
+        JSONAssert.assertEquals(expected, b2Json.toJson(obj), true);
+    }
 
     @Test
-    @Ignore
     public void testResponseUsingGson() throws JSONException {
-        Map<Integer, Map<String, BigDecimal>> revenueMap = new TreeMap<>();
-        revenueMap.put(123, new HashMap<>());
+        Map<String, Map<String, BigDecimal>> revenueMap = new TreeMap<>();
+        revenueMap.put("123", new HashMap<>());
         Map<String, Long> simpleMap = new TreeMap<>();
         TestResponse obj = new TestResponse("str",
                 "message",
@@ -248,7 +246,6 @@ public void testResponseUsingGson() throws JSONException {
                 revenueMap,
                 simpleMap,
                 Set.of("test"));
-        System.out.println("obj is: " + obj);
         String expected = "{\n" +
                 "  \"str\": \"str\",\n" +
                 "  \"message\": \"message\",\n" +
@@ -273,13 +270,14 @@ public void testResponseUsingGson() throws JSONException {
                 "    \"month\": 3,\n" +
                 "    \"day\": 31\n" +
                 "  },\n" +
-                "  \"revenueMap\": {},\n" +
+                "  \"revenueMap\": {\n" +
+                "    \"123\": {}\n" +
+                "  },\n" +
                 "  \"simpleMap\": {},\n" +
                 "  \"categories\": [\n" +
                 "    \"test\"\n" +
                 "  ]\n" +
                 "}";
-        System.out.println("b2Json.toJson(obj): " + gson.toJson(obj));
         JSONAssert.assertEquals(expected, gson.toJson(obj), true);
     }
 

From cbc3f7e9975d94996bf7c277e33cc6fd83357b59 Mon Sep 17 00:00:00 2001
From: Fisher Coder <fishercoder@gmail.com>
Date: Tue, 16 May 2023 11:22:46 -0700
Subject: [PATCH 124/185] add more tests

---
 .gitignore                             |  1 +
 src/test/b2SdkExamples/B2JsonTest.java | 48 +++++++++++++++++++++++---
 2 files changed, 45 insertions(+), 4 deletions(-)

diff --git a/.gitignore b/.gitignore
index 1df76d8..596720d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,4 +4,5 @@
 *.class
 out/
 target/
+.DS_Store
 
diff --git a/src/test/b2SdkExamples/B2JsonTest.java b/src/test/b2SdkExamples/B2JsonTest.java
index a4837ce..b8e645b 100644
--- a/src/test/b2SdkExamples/B2JsonTest.java
+++ b/src/test/b2SdkExamples/B2JsonTest.java
@@ -214,8 +214,8 @@ public void testResponseUsingB2Json() throws B2JsonException, JSONException {
         System.out.println("obj is: " + obj);
         String expected = "{\n" +
                 "  \"categories\": [\n" +
-                "    \"test1\",\n" +
-                "    \"test2\"\n" +
+                "    \"test2\",\n" +
+                "    \"test1\"\n" +
                 "  ],\n" +
                 "  \"localDate\": \"20230331\",\n" +
                 "  \"localDateTime\": \"d20230331_m122100\",\n" +
@@ -310,11 +310,11 @@ public void testObjectUsingDefaultValue() throws B2JsonException {
         System.out.println("about to check the equality between Gson and B2Json results..");
         assertEquals(fromGson, fromB2Json);
         String fromB2JsonString = b2Json.toJson(fromB2Json);
-        String fromGsonString = gson.toJson(fromB2Json);
+        String fromGsonString = gson.toJson(fromGson);
         String expectedFromGson = "{\n" +
                 "  \"a\": 2023,\n" +
                 "  \"b\": \"hello\",\n" +
-                "  \"c\": 5,\n" +
+                "  \"c\": 0,\n" +
                 "  \"d\": 0\n" +
                 "}";
         assertEquals(expectedFromGson, fromGsonString);
@@ -401,4 +401,44 @@ public TestRequest3(String zip) {
         }
     }
 
+    @Test
+    public void testGsonFailure() {
+        // there's an unknown field called e in this json string, in this case, GSON library will just ignore it
+        String json = "{\n" +
+                "  \"a\": 2023,\n" +
+                "  \"b\": \"hello\",\n" +
+                "  \"e\": \"hello\"\n" +
+                "}";
+        System.out.println("json is: " + json);
+        Container fromGson = gson.fromJson(json, Container.class);
+        System.out.println("gson.fromJson(json) is: " + fromGson);
+        System.out.println("about to check the equality between Gson and B2Json results..");
+        String fromGsonString = gson.toJson(fromGson);
+        String expectedFromGson = "{\n" +
+                "  \"a\": 2023,\n" +
+                "  \"b\": \"hello\",\n" +
+                "  \"c\": 0,\n" +
+                "  \"d\": 0\n" +
+                "}";
+        assertEquals(expectedFromGson, fromGsonString);
+
+        // in this json, the field named a is missing
+        json = "{\n" +
+                "  \"b\": \"hello\",\n" +
+                "  \"e\": \"hello\"\n" +
+                "}";
+        System.out.println("2nd time, json is: " + json);
+        fromGson = gson.fromJson(json, Container.class);
+        System.out.println("2nd time, gson.fromJson(json) is: " + fromGson);
+        System.out.println("about to check the equality between Gson and B2Json results..");
+        fromGsonString = gson.toJson(fromGson);
+        System.out.println("2nd time, fromGsonString is: " + fromGsonString);
+        expectedFromGson = "{\n" +
+                "  \"a\": 0,\n" +
+                "  \"b\": \"hello\",\n" +
+                "  \"c\": 0,\n" +
+                "  \"d\": 0\n" +
+                "}";
+        assertEquals(expectedFromGson, fromGsonString);
+    }
 }

From 11d49deb597482d065545ae0fef083c628712994 Mon Sep 17 00:00:00 2001
From: Fisher Coder <fishercoder@gmail.com>
Date: Thu, 18 May 2023 11:24:35 -0700
Subject: [PATCH 125/185] add LocalDateTime examples

---
 src/main/java/dateTimezone/Main.java | 14 ++++++++++++++
 1 file changed, 14 insertions(+)
 create mode 100644 src/main/java/dateTimezone/Main.java

diff --git a/src/main/java/dateTimezone/Main.java b/src/main/java/dateTimezone/Main.java
new file mode 100644
index 0000000..49fe49d
--- /dev/null
+++ b/src/main/java/dateTimezone/Main.java
@@ -0,0 +1,14 @@
+package dateTimezone;
+
+import java.time.LocalDateTime;
+import java.time.ZoneOffset;
+
+public class Main {
+
+    public static void main(String... args) {
+        LocalDateTime currentTime = LocalDateTime.now();
+        System.out.println("currentTime is: " + currentTime);
+        LocalDateTime utcTime = LocalDateTime.now(ZoneOffset.UTC);
+        System.out.println("utcTime is: " + utcTime);
+    }
+}

From b323db53bd693890d5f76ef7949198b2a0d05336 Mon Sep 17 00:00:00 2001
From: Fisher Coder <fishercoder@gmail.com>
Date: Thu, 18 May 2023 16:16:59 -0700
Subject: [PATCH 126/185] add LocalDateTime conversion to UTC example

---
 src/main/java/dateTimezone/Main.java | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/src/main/java/dateTimezone/Main.java b/src/main/java/dateTimezone/Main.java
index 49fe49d..ad7ecdd 100644
--- a/src/main/java/dateTimezone/Main.java
+++ b/src/main/java/dateTimezone/Main.java
@@ -1,6 +1,7 @@
 package dateTimezone;
 
 import java.time.LocalDateTime;
+import java.time.ZoneId;
 import java.time.ZoneOffset;
 
 public class Main {
@@ -10,5 +11,8 @@ public static void main(String... args) {
         System.out.println("currentTime is: " + currentTime);
         LocalDateTime utcTime = LocalDateTime.now(ZoneOffset.UTC);
         System.out.println("utcTime is: " + utcTime);
+        //use below method to convert a LocalDateTime object to its UTC version
+        LocalDateTime utcTimeConverted = currentTime.atZone(ZoneId.systemDefault()).withZoneSameInstant(ZoneOffset.UTC).toLocalDateTime(); // UTC
+        System.out.println("utcTimeConverted is: " + utcTimeConverted);
     }
 }

From 1b8a0c70ac81526cef43176b7bdd5a5eaf045133 Mon Sep 17 00:00:00 2001
From: Fisher Coder <fishercoder@gmail.com>
Date: Fri, 19 May 2023 10:04:11 -0700
Subject: [PATCH 127/185] group relevant examples into the same package

---
 .../{randomExamples => dateTimezone}/DateVsLocalDateTime.java   | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
 rename src/main/java/{randomExamples => dateTimezone}/DateVsLocalDateTime.java (97%)

diff --git a/src/main/java/randomExamples/DateVsLocalDateTime.java b/src/main/java/dateTimezone/DateVsLocalDateTime.java
similarity index 97%
rename from src/main/java/randomExamples/DateVsLocalDateTime.java
rename to src/main/java/dateTimezone/DateVsLocalDateTime.java
index 3354dc8..6490e2c 100644
--- a/src/main/java/randomExamples/DateVsLocalDateTime.java
+++ b/src/main/java/dateTimezone/DateVsLocalDateTime.java
@@ -1,4 +1,4 @@
-package randomExamples;
+package dateTimezone;
 
 import java.time.LocalDateTime;
 import java.util.Date;

From 4c07f0698f279e272b9f019add625834daae8cfe Mon Sep 17 00:00:00 2001
From: Fisher Coder <fishercoder@gmail.com>
Date: Fri, 19 May 2023 10:11:31 -0700
Subject: [PATCH 128/185] a simple program to profile

---
 src/main/java/profiler/Main.java | 15 +++++++++++++++
 1 file changed, 15 insertions(+)
 create mode 100644 src/main/java/profiler/Main.java

diff --git a/src/main/java/profiler/Main.java b/src/main/java/profiler/Main.java
new file mode 100644
index 0000000..be6179d
--- /dev/null
+++ b/src/main/java/profiler/Main.java
@@ -0,0 +1,15 @@
+package profiler;
+
+public class Main {
+    public static void main(final String[] args) {
+        long x = 0;
+        for (int i = 0; i < 1000000; i++) {
+            x += calculate(i);
+        }
+        System.out.println("x = " + x);
+    }
+
+    private static long calculate(final int i) {
+        return (long) i * (long) i;
+    }
+}

From fbe20d0425cf0311cafaa0c81b7f36b221303b34 Mon Sep 17 00:00:00 2001
From: Fisher Coder <fishercoder@gmail.com>
Date: Wed, 31 May 2023 14:15:03 -0700
Subject: [PATCH 129/185] add comment for a simple test function

---
 src/main/java/profiler/Main.java | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/src/main/java/profiler/Main.java b/src/main/java/profiler/Main.java
index be6179d..3884b74 100644
--- a/src/main/java/profiler/Main.java
+++ b/src/main/java/profiler/Main.java
@@ -1,6 +1,14 @@
 package profiler;
 
 public class Main {
+    /**
+     * From this post: https://stackoverflow.com/a/9415368/4117496
+     * To run this: go to terminal and use this command:
+     * java -server -XX:+UnlockDiagnosticVMOptions '-XX:CompileCommand=print,*Main.main' src/main/java/profiler/Main.java
+     * but it produces this error:
+     * Could not load hsdis-aarch64.dylib; library not loadable; PrintAssembly is disabled
+     * I didn't dig further after this.
+     * */
     public static void main(final String[] args) {
         long x = 0;
         for (int i = 0; i < 1000000; i++) {

From 16f3b25bcffe72d5b1a9e3b260d55b179cdcb9c4 Mon Sep 17 00:00:00 2001
From: Fisher Coder <fishercoder@gmail.com>
Date: Thu, 1 Jun 2023 18:57:16 -0700
Subject: [PATCH 130/185] use Junit5 in some tests

---
 pom.xml                                       | 13 ++++++++++++
 .../PrivateModuleTest.java                    | 20 +++----------------
 src/test/b2SdkExamples/B2JsonTest.java        |  6 +++---
 3 files changed, 19 insertions(+), 20 deletions(-)

diff --git a/pom.xml b/pom.xml
index 19ea5be..d4c8467 100644
--- a/pom.xml
+++ b/pom.xml
@@ -47,6 +47,13 @@
             <version>4.13.1</version>
         </dependency>
 
+        <dependency>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter-engine</artifactId>
+            <version>5.9.1</version>
+            <scope>test</scope>
+        </dependency>
+
         <!-- spring-context which provides core functionality -->
         <dependency>
             <groupId>org.springframework</groupId>
@@ -170,6 +177,12 @@
             <version>1.5.1</version>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>org.testng</groupId>
+            <artifactId>testng</artifactId>
+            <version>RELEASE</version>
+            <scope>test</scope>
+        </dependency>
 
     </dependencies>
 
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 <fishercoder@gmail.com>
Date: Sat, 3 Jun 2023 15:23:48 -0700
Subject: [PATCH 131/185] 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 @@
         <dependency>
             <groupId>org.junit.jupiter</groupId>
             <artifactId>junit-jupiter-engine</artifactId>
-            <version>5.9.1</version>
-            <scope>test</scope>
+            <version>5.9.2</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter-params</artifactId>
+            <version>5.9.0</version>
         </dependency>
 
         <!-- spring-context which provides core functionality -->
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<Arguments> 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 <fishercoder@gmail.com>
Date: Sun, 4 Jun 2023 09:31:25 -0700
Subject: [PATCH 132/185] 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 <fishercoder@gmail.com>
Date: Sat, 29 Jul 2023 13:37:47 -0700
Subject: [PATCH 133/185] 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<B2Bucket> 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 <fishercoder@gmail.com>
Date: Sun, 30 Jul 2023 16:21:34 -0700
Subject: [PATCH 134/185] 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<B2Bucket> 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<B2Bucket> 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 <fishercoder@gmail.com>
Date: Sun, 6 Aug 2023 16:51:56 -0700
Subject: [PATCH 135/185] 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 <fishercoder@gmail.com>
Date: Fri, 18 Aug 2023 18:37:13 -0700
Subject: [PATCH 136/185] 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<Future<String>> list = new ArrayList<Future<String>>();
+		List<Future<String>> list = new ArrayList<>();
 		
 		Callable<String> callable = new Task(userId);
 		

From 5a7cc87e57231ad71857b699e978e462d76c88e8 Mon Sep 17 00:00:00 2001
From: Fisher Coder <fishercoder@gmail.com>
Date: Sat, 19 Aug 2023 20:22:47 -0700
Subject: [PATCH 137/185] 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<Future<String>> list = new ArrayList<Future<String>>();
-		
-		Callable<String> callable = new Task(userId);
-		
-		for(int i = 0; i < 10; i++) {
-			Future<String> future = executor.submit(callable);
-			list.add(future);
-		}
-		
-		for(Future<String> 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<Future<String>> list = new ArrayList<>();
-		
-		Callable<String> callable = new Task(userId);
-		
-		for(int i = 0; i < 10; i++) {
-			Future<String> future = executor.submit(callable);
-			list.add(future);
-		}
-		
-		for(Future<String> 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<String> {
-
-	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<Future<String>> list = new ArrayList<Future<String>>();
+		List<Future<String>> list = new ArrayList<>();
 		
 		Callable<String> callable = new MyCallable();
 		

From 0a5b06a3cd6c1017ffd2b76a740d718a30c480ed Mon Sep 17 00:00:00 2001
From: Fisher Coder <fishercoder@gmail.com>
Date: Sun, 20 Aug 2023 14:31:58 -0700
Subject: [PATCH 138/185] 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<Future> 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 <fishercoder@gmail.com>
Date: Sun, 20 Aug 2023 18:10:47 -0700
Subject: [PATCH 139/185] 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<String> completableFuture = calculateAsync();
+        String result = completableFuture.get();
+        assertEquals("Hello", result);
+    }
+
+    private static Future<String> calculateAsync() {
+        CompletableFuture<String> 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 <fishercoder@gmail.com>
Date: Sun, 20 Aug 2023 18:18:18 -0700
Subject: [PATCH 140/185] 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<Future<String>> futureList = new ArrayList<>();
+        for (int i = 1; i <= NUMBER_OF_COMPUTATION_JOBS; i++) {
+            Future<String> completableFuture = workerPool.executeAsync(i);
+            futureList.add(completableFuture);
+        }
+        for (Future<String> 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<String> 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 <fishercoder@gmail.com>
Date: Sun, 20 Aug 2023 20:58:26 -0700
Subject: [PATCH 141/185] 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<String, Integer> 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<Integer, Integer> addFunction = a -> a + 3;
+        System.out.println(addFunction.apply(1));
+
+        Function<Integer, Integer> 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<Integer, Integer> 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<Integer, Integer> 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<String, String> stringFunction = Function.identity();
+        System.out.println(stringFunction.apply("Alive is Awesome"));
+
+        // Using Integer as input for Function.identity()
+        Function<Integer, Integer> integerFunctionUsingFunctionIdentity = Function.identity();
+        System.out.println(integerFunctionUsingFunctionIdentity.apply(8));
+
+        // Using lambda expression and String as input
+        Function<String, String> stringFunctionUsingLambda = t -> t;
+        System.out.println(stringFunctionUsingLambda.apply("Be in present"));
+
+        // Using lambda expression and Integer as input
+        Function<Integer, Integer> integerFunctionUsingLambda = t -> t;
+        System.out.println(integerFunctionUsingLambda.apply(4));
+
+        Function<Integer, Integer> func1 = Function.identity();
+        Function<Integer, Integer> func2 = Function.identity();
+        Function<Integer, Integer> func3 = Function.identity();
+
+        Function<Integer, Integer> intFunc1 = t -> t;
+        Function<Integer, Integer> intFunc2 = t -> t;
+        Function<Integer, Integer> 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 <fishercoder@gmail.com>
Date: Sun, 20 Aug 2023 20:59:54 -0700
Subject: [PATCH 142/185] 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 <fishercoder@gmail.com>
Date: Sun, 20 Aug 2023 21:37:35 -0700
Subject: [PATCH 143/185] 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<String, String> 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<String, String> 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<String, String> 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<String, String> 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 <fishercoder@gmail.com>
Date: Fri, 25 Aug 2023 07:22:20 -0700
Subject: [PATCH 144/185] 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 <fishercoder@gmail.com>
Date: Sun, 27 Aug 2023 16:02:58 -0700
Subject: [PATCH 145/185] 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 @@
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-compiler-plugin</artifactId>
                 <configuration>
-                    <source>9</source>
-                    <target>9</target>
+                    <source>16</source>
+                    <target>16</target>
                 </configuration>
             </plugin>
         </plugins>

From e06b0a9bb86aa18a804c9cb905b26834267f6095 Mon Sep 17 00:00:00 2001
From: Fisher Coder <fishercoder@gmail.com>
Date: Tue, 12 Sep 2023 09:06:41 -0700
Subject: [PATCH 146/185] 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 <fishercoder@gmail.com>
Date: Tue, 12 Sep 2023 09:12:46 -0700
Subject: [PATCH 147/185] 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<Long> 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<Long> 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 <fishercoder@gmail.com>
Date: Tue, 12 Sep 2023 15:18:11 -0700
Subject: [PATCH 148/185] 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<Long> events, long nanos, long interval) {
         events.add(nanos);
@@ -24,6 +24,7 @@ public static int update(Deque<Long> 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 <fishercoder@gmail.com>
Date: Sun, 15 Oct 2023 08:36:09 -0700
Subject: [PATCH 149/185] [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 <fishercoder@gmail.com>
Date: Mon, 16 Oct 2023 17:01:12 -0700
Subject: [PATCH 150/185] 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 <fishercoder@gmail.com>
Date: Fri, 17 Nov 2023 21:15:00 -0800
Subject: [PATCH 151/185] 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<B2Bucket> 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 <fishercoder@gmail.com>
Date: Fri, 17 Nov 2023 21:17:31 -0800
Subject: [PATCH 152/185] 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 <fishercoder@gmail.com>
Date: Tue, 23 Jan 2024 11:24:57 -0800
Subject: [PATCH 153/185] 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 <fishercoder@gmail.com>
Date: Fri, 26 Jan 2024 16:06:16 -0800
Subject: [PATCH 154/185] 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 <fishercoder@gmail.com>
Date: Mon, 29 Jan 2024 18:22:10 -0800
Subject: [PATCH 155/185] 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<String, Integer> 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 <fishercoder@gmail.com>
Date: Sat, 3 Feb 2024 11:03:24 -0800
Subject: [PATCH 156/185] 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<Person> 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<Person> 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 <fishercoder@gmail.com>
Date: Sat, 3 Feb 2024 11:23:49 -0800
Subject: [PATCH 157/185] 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<String> 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<String> calculateAsync() {
         CompletableFuture<String> 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<Future<String>> futureList = new ArrayList<>();
         for (int i = 1; i <= NUMBER_OF_COMPUTATION_JOBS; i++) {
             Future<String> completableFuture = workerPool.executeAsync(i);
+            System.out.println("i = " + i + " and completableFuture.isDone() is: " + completableFuture.isDone());
             futureList.add(completableFuture);
         }
         for (Future<String> 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 <fishercoder@gmail.com>
Date: Sat, 3 Feb 2024 11:58:38 -0800
Subject: [PATCH 158/185] 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<CalcResult> {
+        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<CalcResult> 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<CalcResult> 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 <fishercoder@gmail.com>
Date: Sun, 4 Feb 2024 11:06:16 -0800
Subject: [PATCH 159/185] 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 <fishercoder@gmail.com>
Date: Sun, 4 Feb 2024 13:21:51 -0800
Subject: [PATCH 160/185] 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 <fishercoder@gmail.com>
Date: Sun, 4 Feb 2024 16:00:46 -0800
Subject: [PATCH 161/185] 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 <fishercoder@gmail.com>
Date: Sun, 4 Feb 2024 16:12:33 -0800
Subject: [PATCH 162/185] 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 <fishercoder@gmail.com>
Date: Sun, 4 Feb 2024 16:55:35 -0800
Subject: [PATCH 163/185] 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<Person> 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 <fishercoder@gmail.com>
Date: Sun, 4 Feb 2024 20:40:17 -0800
Subject: [PATCH 164/185] 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 <fishercoder@gmail.com>
Date: Sun, 4 Feb 2024 20:40:33 -0800
Subject: [PATCH 165/185] 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 <fishercoder@gmail.com>
Date: Mon, 5 Feb 2024 08:30:06 -0800
Subject: [PATCH 166/185] 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<K,V> 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<String, String> 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 <fishercoder@gmail.com>
Date: Mon, 5 Feb 2024 08:31:17 -0800
Subject: [PATCH 167/185] 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 <fishercoder@gmail.com>
Date: Mon, 5 Feb 2024 08:32:38 -0800
Subject: [PATCH 168/185] 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<String, String> map = new HashMap<>();
+        Map<String, String> 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 <fishercoder@gmail.com>
Date: Mon, 5 Feb 2024 08:35:14 -0800
Subject: [PATCH 169/185] 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 <fishercoder@gmail.com>
Date: Mon, 5 Feb 2024 08:41:28 -0800
Subject: [PATCH 170/185] 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<String> 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 <fishercoder@gmail.com>
Date: Mon, 5 Feb 2024 08:59:33 -0800
Subject: [PATCH 171/185] 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<Integer> 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<Integer> 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 <fishercoder@gmail.com>
Date: Sat, 24 Feb 2024 13:33:25 -0800
Subject: [PATCH 172/185] 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 <fishercoder@gmail.com>
Date: Thu, 20 Jun 2024 21:14:28 -0700
Subject: [PATCH 173/185] 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<Integer> 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<String> consumer1 = ConsumerInterfaceExample::printMessage;
+        consumer1.accept("John");   // Calling Consumer method
+        // Referring method to Integer type Consumer interface
+        Consumer<Integer> consumer2 = ConsumerInterfaceExample::printValue;
+        consumer2.accept(12);   // Calling Consumer method
+
+        // Creating a list and adding values
+        List<Integer> list = new ArrayList<>();
+        list.add(10);
+        list.add(20);
+        list.add(30);
+        list.add(40);
+        // Referring method to String type Consumer interface
+        Consumer<List<Integer>> 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<String> 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 <fishercoder@gmail.com>
Date: Thu, 4 Jul 2024 12:06:22 -0700
Subject: [PATCH 174/185] 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 <fishercoder@gmail.com>
Date: Sun, 7 Jul 2024 10:22:05 -0700
Subject: [PATCH 175/185] 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: <a href="https://stackoverflow.com/a/28624160/4117496">StackOverflow</a>
+     */
+
+    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 <fishercoder@gmail.com>
Date: Sun, 7 Jul 2024 12:13:43 -0700
Subject: [PATCH 176/185] 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 @@
             <scope>test</scope>
         </dependency>
 
+        <dependency>
+            <groupId>org.springframework.security</groupId>
+            <artifactId>spring-security-crypto</artifactId>
+            <version>6.3.1</version>
+        </dependency>
+
     </dependencies>
 
 
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 <fishercoder@gmail.com>
Date: Mon, 9 Sep 2024 08:24:46 -0700
Subject: [PATCH 177/185] [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 <fishercoder@gmail.com>
Date: Mon, 9 Sep 2024 08:48:51 -0700
Subject: [PATCH 178/185] [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 <fishercoder@gmail.com>
Date: Mon, 9 Sep 2024 15:18:50 -0700
Subject: [PATCH 179/185] [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<String> baseSet = readAllFieldNames(BASE_FILE);
+        Set<String> updateFileSet = readAllFieldNames(UPDATE_FILE);
+        Set<String> baseSetCopy = new HashSet<>(baseSet);
+        baseSetCopy.removeAll(updateFileSet);
+        System.out.println("baseSetCopy size after removing updateFileSet is: " + baseSetCopy.size());
+
+        Set<String> 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<String> 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<String> readLinesMatchingSet(String filePath, Set<String> 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<String> 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<String> 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<String> 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 <fishercoder@gmail.com>
Date: Sat, 12 Oct 2024 15:13:58 -0700
Subject: [PATCH 180/185] [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 @@
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-compiler-plugin</artifactId>
                 <configuration>
-                    <source>16</source>
-                    <target>16</target>
+                    <source>17</source>
+                    <target>17</target>
                 </configuration>
             </plugin>
         </plugins>
@@ -37,7 +37,7 @@
         <dependency>
             <groupId>org.projectlombok</groupId>
             <artifactId>lombok</artifactId>
-            <version>1.18.2</version>
+            <version>1.18.20</version>
             <scope>provided</scope>
         </dependency>
 

From bd5486acd709e40e1ef4100b85f755e507f257c4 Mon Sep 17 00:00:00 2001
From: Fisher Coder <fishercoder@gmail.com>
Date: Sat, 12 Oct 2024 15:17:19 -0700
Subject: [PATCH 181/185] [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<Arguments> 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<Arguments> 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 <fishercoder@gmail.com>
Date: Fri, 18 Oct 2024 11:56:29 -0700
Subject: [PATCH 182/185] [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<Arguments> 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 <fishercoder@gmail.com>
Date: Sun, 20 Oct 2024 09:51:25 -0700
Subject: [PATCH 183/185] [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 <fishercoder@gmail.com>
Date: Thu, 19 Dec 2024 19:27:42 -0800
Subject: [PATCH 184/185] [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 @@
     <version>1.0-SNAPSHOT</version>
 
     <dependencies>
+        <dependency>
+            <groupId>com.opencsv</groupId>
+            <artifactId>opencsv</artifactId>
+            <version>5.9</version>
+        </dependency>
 
         <dependency>
             <groupId>org.apache.logging.log4j</groupId>
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 <fishercoder@gmail.com>
Date: Thu, 19 Dec 2024 19:28:59 -0800
Subject: [PATCH 185/185] [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
