From 201780e3d611eee7d5adef37e25af85c40c69cfb Mon Sep 17 00:00:00 2001 From: Steve Sun 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 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] 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 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 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 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 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 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 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 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 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 fourLetterWord = new HashMap(); + fourLetterWord.put(5678, "jmpu"); + fourLetterWord.put(8432, "thea"); + fourLetterWord.put(7843, "ruif"); + fourLetterWord.put(8432, "vida"); + + HashMap 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 which is used to store all possible valid words that this + * number can represent. Because one number can represent a couple different words.*/ + HashMap> threeLetterWord = new HashMap(); + HashMap> fourLetterWord = new HashMap(); + HashMap> 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 allString = new ArrayList(); + allString = threeLetterWord.get(_3LetterWordNum); + allString.add(dict[i]); + threeLetterWord.put(_3LetterWordNum, allString); + } + else{ + ArrayList allString = new ArrayList(); + 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 allString = new ArrayList(); + allString = fourLetterWord.get(_4LetterWordNum); + allString.add(dict[i]); + fourLetterWord.put(_4LetterWordNum, allString); + } + else{ + ArrayList allString = new ArrayList(); + 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 allString = new ArrayList(); + allString = sevenLetterWord.get(_7LetterWordNum); + allString.add(dict[i]); + sevenLetterWord.put(_7LetterWordNum, allString); + } + else{ + ArrayList allString = new ArrayList(); + 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 temp3word = new ArrayList(); + 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 temp4word = new ArrayList(); + 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 temp7word = new ArrayList(); + 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 temp3word = new ArrayList(); + ArrayList temp4word = new ArrayList(); + 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 temp4word = new ArrayList(); + ArrayList temp3word = new ArrayList(); + + 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 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 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 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 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 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 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 fourLetterWord = new HashMap(); + fourLetterWord.put(5678, "jmpu"); + fourLetterWord.put(8432, "thea"); + fourLetterWord.put(7843, "ruif"); + fourLetterWord.put(8432, "vida"); + + HashMap 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 which is used to store all possible valid words that this + * number can represent. Because one number can represent a couple different words.*/ + HashMap> threeLetterWord = new HashMap(); + HashMap> fourLetterWord = new HashMap(); + HashMap> 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 allString = new ArrayList(); + allString = threeLetterWord.get(_3LetterWordNum); + allString.add(dict[i]); + threeLetterWord.put(_3LetterWordNum, allString); + } + else{ + ArrayList allString = new ArrayList(); + 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 allString = new ArrayList(); + allString = fourLetterWord.get(_4LetterWordNum); + allString.add(dict[i]); + fourLetterWord.put(_4LetterWordNum, allString); + } + else{ + ArrayList allString = new ArrayList(); + 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 allString = new ArrayList(); + allString = sevenLetterWord.get(_7LetterWordNum); + allString.add(dict[i]); + sevenLetterWord.put(_7LetterWordNum, allString); + } + else{ + ArrayList allString = new ArrayList(); + 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 temp3word = new ArrayList(); + 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 temp4word = new ArrayList(); + 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 temp7word = new ArrayList(); + 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 temp3word = new ArrayList(); + ArrayList temp4word = new ArrayList(); + 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 temp4word = new ArrayList(); + ArrayList temp3word = new ArrayList(); + + 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 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 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 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 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 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 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 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 @@ + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.8 + 1.8 + + + + + + 4.0.0 + + com.fishercoder + RandomJava + 1.0-SNAPSHOT + + + + + org.apache.logging.log4j + log4j-api + 2.7 + + + org.apache.logging.log4j + log4j-core + 2.7 + + + + org.projectlombok + lombok + 1.16.12 + provided + + + + junit + junit + 4.11 + + + + + org.springframework + spring-context + 4.1.6.RELEASE + + + + + org.springframework + spring-aop + 4.1.6.RELEASE + + + + + org.springframework + spring-webmvc + 4.1.6.RELEASE + + + + + org.springframework + spring-web + 4.1.6.RELEASE + + + + com.fasterxml.jackson.core + jackson-annotations + 2.6.0 + + + + com.fasterxml.jackson.core + jackson-databind + 2.4.1.3 + + + + org.codehaus.jackson + jackson-core-asl + 1.9.13 + compile + + + + org.codehaus.jackson + jackson-mapper-asl + 1.9.13 + compile + + + + javax.mail + mail + 1.5.0-b01 + + + + + + \ 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 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 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 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 @@ 1.5.0-b01 + + org.apache.avro + avro + 1.8.1 + + 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 datumWriter = new GenericDatumWriter(schema); + DataFileWriter dataFileWriter = new DataFileWriter(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 datumReader = new GenericDatumReader(schema); + DataFileReader dataFileReader = new DataFileReader(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 literal 218 zcmeZI%3@>^ODrqO*DFrWNX<=L#Z;|SQdy9yWTjM;nw(#hqNJmgmzWFUyXF?;T wb8?hoYh!B}7A#7ZS#!%JJuS$0-PDc?QY>;D!I@==QA}LkMVZAJ7EI_00I)kslmGw# literal 0 HcmV?d00001 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 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 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 @@ org.apache.maven.plugins maven-compiler-plugin - 1.8 - 1.8 + 1.7 + 1.7 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 delta 56 ycmcb`c#CnuN<*1N0XyPCP2~=x>;E&DEOMAdjw3j;EHR3S%eyGEIKzSoT>$`F=@jz- delta 56 ycmcb`c#CnuO2Y+QSafSsGx&i=_=@!=j From ef67f1dbc71deb563a8145b570b5c9602d1420fc Mon Sep 17 00:00:00 2001 From: Steve Sun 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 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 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 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 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 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 @@ org.apache.maven.plugins maven-compiler-plugin - 1.7 - 1.7 + 1.8 + 1.8 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 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 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() { + @Override + public int compare(Person o1, Person o2) { + return o1.age - o2.age; + } + }); + + print(names, "After sorting: "); + } + + private static void print(List 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 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 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 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 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 { + 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 @@ 4.1.6.RELEASE - - com.fasterxml.jackson.core - jackson-annotations - 2.6.0 - - - - com.fasterxml.jackson.core - jackson-databind - 2.4.1.3 - - org.codehaus.jackson jackson-core-asl @@ -118,7 +106,13 @@ 1.8.1 + + com.amazonaws + aws-java-sdk-ses + 1.11.253 + + - - \ No newline at end of file + + 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 = "

Amazon SES test (AWS SDK for Java)

" + + "

This email was sent with " + + "Amazon SES using the " + + "AWS SDK for Java"; + + // 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 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 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 stream1 = Stream.of(arr1); + Stream stream2 = Stream.of(arr2); + + Stream 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 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 Image transform(Image in, BiFunction f, T arg) { + int width = (int) in.getWidth(); + int height = (int) in.getHeight(); + WritableImage out = new WritableImage(width, height); + for (int x = 0; x < width; x++) { + for (int y = 0; y < height; y++) { + out.getPixelWriter().setColor(x, y, + f.apply(in.getPixelReader().getColor(x, y), arg)); + } + } + return out; + } + + @Override + public void start(Stage stage) throws Exception { + Image image = new Image("queen-mary.png"); + Image newImage = transform(image, + (c, factor) -> c.deriveColor(0, 1, factor, 1), 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 stream1 = Stream.of(arr1); - Stream stream2 = Stream.of(arr2); - - Stream 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 literal 265908 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ΞG%8Rjm$+iVw3sSwCZqmI$n&q9_4W1dkOmWjk?3D-^1o)V-a=h&{M9F z3qv|AQC*fh(0H;9N*;;1@y{x4vTneiig3C@|B5GS*VZ^P#@UAkwlbDeRhlkM>D(#A z;{q;CM1d4>g14)fk<^>t0n09+RV#A0z7=f`Q(`DD@HULl5fUZ(FRVGFdXBq>@;tb! zSRx-hC8tthEyE!zxyc|N^|?~TKtN)RP41rj14>0fv$K-T1>+DAB67xcuA4L3{a;x; zZ8Z(Q>qjTtvGs~(m!Vyg+-#ghAEHA^mMO}g!JFVv`gok_;luc0tv_ohJa)IRYQT6= z?HyhI5`4Tn7lEUg&$B}Ht>yD4K{jhDs*E`fRqTU#sLCrnD!|Zc97btrWU2j2Ux1TGysDIQf2w=F{MA=4{rcUX z{`hz_21kxGqpC0`Um4?qGT2<1^NMronp#^RYOLj+X@U>(`QV8t=*7zSdie1|eC*Pz zKKtU+ckdoQ|MYRalHsRxVnUrA3X+YZ4bRKNNkMf=iKLN)mzNLkKRMJC@u-vJdg@U; z;sw0E>N4hF4rn8y>?5>M==DSE`Q6iRzQNOb0-R>eYhNEeeq<_37=^fY31<8l7V*8^ z_itNZIsCNU00M#I>~%AiOjCz3`x2(HZSx-0{iQ-Qd1nZOJ$Ca{@{DT@Q^q;rQ&mbg z!VG}HSy4Ld4rV5vMH&qOI7v0~t!%ImT07J(`$y|n9ri{AZuGW1N&GG^HFG-{466i1 ziDup?08&3;d1zAcl0e)JZ}2>>RyC@l=JXVhkuP{2F_xGU(m?VSW`7la=i11D4bMMInot$RJ^a?Byif1Mu@(C z;axp z>Xe6x`!au9&ZAB&cH`i2^6Ond=3R~|f!)U`VevOYm}$d-dZ?k3WOxVv*Bh$Ec~l() zqrIGTOpGpF*SpU@`QmSW{SW`?pEaF?)hA(khI0xe#*OJ(#o?5uroqc5e(TRQ)I6-v zuYq2p4f9p?umC)jvhMGRisY-WKmGKxPyYD(Z}&m)tzJ*woHkLSG61+#ExGyF4v=GI*zXw<`W=G@O=TQ4;f z%5h9Hvg0y!MU+N+>jQ`ipd_7x;zP5VOuy6!( z$881wm>P@%teXI}iwPmX>~-=Tamd4ZSO>TyCc&-i8vm`#O#ow|YYkEqL;iaGJ6J5C zXn_;>ORvluT(HL>qJ^w2YZ-UVX3qy$|9`6fY)O_ZIT8e!<*1pt-zE0Q$V}|0swwK3 zqIsK#`TcpDr=}t5uCA^I3P>a}a*5@xzL@C|;dx*=dZUs+05TT8?&hlJi16BPj~_5r zY*?eC&&pOA(t&8v28gbxkjqw=;;LmSL~mfrh0-ba9lh0qk5QKeB(*9;bA4e#BJYoRwZ zONSzT(PXdI;oQ1LdsYzTP)oFH`3;*21_!WmxYu4D(_+1-5Me6T+~Uj6KL6nl ze|UQTfEcsFX_vA36-7l@JRDWI8;^)iv31@D9F1mhSVROPFp!1H(CFm;CZ?>92FbB& zKX2QY-+lGdpMR=7#X%Lfz#@;Zd{5SbMqdK`giL2WQieC9z=-SfHTT-icg?XIFhwU% z-MzTmHGPdD*oN;Tm%ci6GKBr%X)qEIacYZx1ykAusH#&r1#FBKd7$J)y%qVDJ!ELv zeLC%>b!VPI*e7u}4$^rA3WCG-Ly}%J4hbiK=mL`JlO&hIu>@f_(rsgl^ib4@Wv7CV zgSId<7T$p>TucW0!0O?gMx9$8?IUf3RAzd+C)mWemkxg+JJWhDWWz)L@~q+iW0t7= zTe3ms({4g>3K*hB*n5Ei%t|enzcC3zuEE2E+?W)Z62O7#{*fh!X#(D6U(ljqmeX2r zFqaO5P>WXkiV7^o+UOFF@3$vv!*;O-Kr9x3ec&FY4~>k2;6QUWu~roH`EEH+Ms@YO zprW?r)mte;td3+et#ahG_3vQO%NQ-bvWL41S*>wOMDbHVRtSvfCS*S<2 z8(eB=iwcZFcExy@`~aL0)aEuA;;^-`fAM#CX`ns(?n=#NpxZ>7#XQdDZDT31&YDpoE3z7bY# zVe-$lC3d4#+hpi=nfUTIzk2xi{QU47VLN%xApXP+ZWsVO)c#GcV_}OPzCe-ly6?Hi zu;H%NRuw`hwzzwFxm}<8jU#9*zc+_<;gFfQ-FBXaVmrOMS0=Iy=;ZTl9D6abXhr3sMV_I z%@ZP<=xsB=GSRLkny|DuV~I1X;UpX>LKQ*lu9u|2zs*D5({@Zx$08Kv19chEt5%(q zcbQnnPmR@?)9MyE8rAJ6wxczOqwY1{*h1lI@>j#O06GMLz*rlZgT@i99<~qMAZr^{ zY__q=t!Xl378;Lw2$wfYikYy4LY0v6U5 z=tw6|M1DA;6do2mjX7?GtN=!J$iwJkom)#_dW8;X_;&I+zk)>kpCCfrbK7DVBD;&l zl?jD$NTtnHA&O(^xGcfyb<7`NNCvBqWuUlT9km}HWu9jJ)U8GF#y>0s2sDq$S;jZ} ztI+;90V-uI$g0^oR{}8@uvc{T%5wEKHEhIyHgT|(bu+g1FBhcBq-G&u`BEaNlpT8XE?T0`97=iZr9hHj`MjTsqEPso#=Vs4;9r)77Lo4vZ#T(7j8dz`A z(+{$}q+9R9;wS&MpUznCvwv{oJS+|QiC|Hk6YpwveySb8a-M2Ajt@k`r;5WQq6-~d zSt+gT{zWCrn)elzvi_-cv9-dzPZG3=6eVKvQ<-L`qymtcHUp~bEMrGX0ac?@W7s>5 z&js~UA-6#FYiq{5FErKWX|4x-!xRjswl+0P>vBw2`2JgMh8ig6zuRqKy=3%8u3)1?(0eK3Z(ROc=)u>g;OZV|Y>B(J(M>qq<- zIyAp^#?kPQe|DEcF1Esqq2(m)ibU9EmsST?gUWs0w$`BK+U>7#=p(Xs>P_0%b7$`u zfbZYv1Up|wtQu^uW5d(O`yxQXRF`P2)F025Ot8XKW}#B;#_No)m|BRKrl=X>V5;o_ z)#B6&#t9>&@W>dcZ4WXrX1I-&h+<{!#fX~oAO6E%U!QMp{_;~0Rc`TZH=Or<0vwc3 z(+}a=vPnfS!9+qi+%Cr!@s~8(6l|Q#CU>)uQDjBUdU=2M#h0&t|4;v3Io09xSk{aV z5}>l}<*`)A%MEzo38o{S9zWi{yldX9;nzV$SVp~_!H`qIRyVvwQNDf28k~8()xK}r zz*;PTffy*{oJ;%C-XKr3X)K{*o;<-?PuaV0yGB^en;(kE#yz#71+0Qtej1j+*tCXn zIYBxCJXkH?@Ltjh zL896vwboL1bY>hFa|2N2W4n*H=uCxJ(C}CpyRBZgjLy&);q(fhvI8;b3}+w|z~;Cw zkKf%VRm14|C-kdxtO<9I0b^okk)NIgsW^Z5ePYdmdD(ukC(dd&UmKzTI?* z=?lmV;X0bsjIQda!O|hCb*$hLd6hfDKdp>StM~81U)Ya|q_n7|Iji<=cVuFepI)L( zP>T(%HG>F9wwtl1XDH1$Ie56Zo<2!IulAmtX%nt&G51qf?GNQ(HVx2;umY03-7R#g z1&hAU6Kw=(jAU8B-BHw@7t_(y!IxP>UL~zWw!_v=anoVTAi#{JXXt=~W43fF7!ehN z3lbHhTw2oKZZ;vnB@uJj(h~fK@@PzMk9{9%p@lG7{BTsWcWfw>B{%jgysl@~7`?ic zOXmtwY@#MJte!E%5DdiVAm*Bp<>-h|Z1DRtl=b=7ukT;H{_{V5--K8dt8C=8VL8f< zPE#9j!oiU*H*Tzr zV>F!vj==TtfhjUp6o|WcF>v%FSse|qFK1{8S(eC<;&jq7K|4p9?xh!lfkm>>TmHg7 zA_9(?T;|v2oZF<&m5XPNYG0~y9g=-5VP?xRyPyc^PzW<_3S)ZShg>MGHKaS%k0C?0 zQh-tIUqUC#9)eIV0kvZVK3zNw@X2z2U%^Yk$_3>v5SLwDzeF~DlN6AMl(O?Fq7UFT zMtEn5234sDt*UP|W1}UHS*c8|QK(L81XsSI-?RhaN6#iQ|5OW{w`|huWCF#ZIFdoV z-Zm*q?~%s;+giBTV8g`OD);EP%B2wN@2+dt!^!b1U=}7KtG~mQu~j%$@}*v3e-lkh zy35bj4=))_h4)>HE;8$aQmw-f>MkAG9PjaPRaGm0S#lw*CwVDW55`*S4U9l*61-Wf z4?y-8kr)|XtZj^3w?h*x{*3$_l=}4qLN(A%fmnzf{FR-Y#zLa=Kd?+K);=sYPvyuX zv$bmNZbwRjAW|tN#(H|F7B>1JY3ztM6`4du0LB8AH{Qul1eT=t;MoI-uGP z-7M6;7Tq?LlL@59s1XcQ&s3f8QO=^J^=$R^Z@$TzkMAEwd~!%Z%SB_?M@BA#P_xz@ZOWa;#80w24|(b!!#{KIP_s_321z_QSOe4kK=AVTF333g}dt z)yoHqeGfio)k5TUgQIO?YqWK2Q}zz-q!}z^ z%cHb@F-Oz&WDUxi@XuB_(0sp@xADnyEXX**Ax~dRM?an6XMUv?BXb^kkEw zW_J&3U}+~DmTO`VT->V_Y@ItM8*NC~6+zCWGXUJTW}l$oq@Bj^s22Ad(Sb^{cUv9f zw{xP`?HpCTKU) zyE(D)x{FO3VhR&VuY4sazWkf--alU7{_xWX)>P+ac)pLysEPow8O84>DyMP+V{nkQ z``DV0jVenzZ82y!raHr2tf1>5OL@!JpWnwRe)`KBYks6U4#8+ed_d}&UBaJ2F;r=J zsbk}APfr|qI@x9}5Gm9)$S4#r&l|?Z$~~N=nAM>Q<$3`lio8C|)A_oJH0Dm=-P2p+H{9++%0kPUmMTO3qVSQ*UT%6@8~RahYs!V6arS zzr{f^tJ17YqR9R|YaHhx>5Defx4N!@kM2-!%DHVq4S+O;V6LFm)yIGF$iV(Un~Lf6 z8@;)>zp;@y&)o4#$9}(r>S13iAk9)S?+La5ap^G!dt_uo*%v` zChVB*xtK7^sYb*6TZ&qUf2*}ZBfu!Gzu(8*|RrIN-)joM=5+1SJ4G% zupp!XqGlDBZ3M0|H(ec;SuO4#vvYrHM787&G$yYXeFOz^EF# zv!LKh)LZA8&><@wR>DB%yW2JA$%f5|dfcmw0|@MO%vmW)Lr5DsM@q?~4ZtN4>uI#s zdJ)Cup+(P+;nt=&lw-a2bVgGPT4+gyVZY&APit&PPkxJTqc18!R4_&Z&n$5xPs|O= zBe|)fsHrN9zJ9ooBi!TO0|{+oO~xdvX1)CE)r)Vw`29csp)?b=jU=j^^JU;Qp*{-N z=oW6`GiJ9G|9%jMJWyKOv0hPhNu-p{J@aaPy1W14n{R&j!;e|}f{2XMRasFL3S!W8 z2c5iRpLSG(AOb$V`7q8KBaYF2-*0>7(`~<2T{GUkeIT-KJKMkEkGLP4)}Tnw50Bem zh4MD9?;mQ5$J_omYe($2;%oy60md>zb3M|848b+c3^~@el`sbW`lt#!Si8Tl>5@-S zb%Yir>Pm(Yw(}pgwyua|Q~?VTwECl`j;=sx-J2t0Z4?SD``4#_1&`tgS%Vrlep0Lb zkF#wJXg#$=boX12m+r>0+}9YHx<&*oj0qv_J#2rzZ`^MDUYaHhCua~OR!oF}$m;H5H8bfI z*aM;SLKgFlT0}GqB`+P0hfS-DENLLd!pc5rOIKi{Rdhxjx%?VXSbo#@ua!)lAk^uU z9WzWU%IX(un12bRHm-?YM|Mw}7M8kJ5gL7CWwf~0BZ!6Hy_bbBEW~KFvPJ43H2U#D<-(no^G9SwXmpOKzoF&F zJ%oWQL)(nSc~ouXSrkPB&m*{(R8d`HG?&TFZ>}B*k&lMBPX?fYoTYy-B;0hje z?@Vm86T-f$E_tiY_o|Ai%?A7^3=0J^5W>hpO(|HY8fXkODkVilBFvd`dh*=^yqV4Kbsmcm3AFd9O@}2AzraD^+f+qCp zyD#3q`EdRCq(wM*{4yBu7e@M|?iat&v`lAY`$b+^F6 z!?=3jErV$}dT;H{_G^-OskN7sWKjWq1+W!cVRAfDd0;O|X z(8VmKYFx48tmrAt6+YWzn!VZPBLoyifTbu)1~jtm)?i2L=OIvDCP1J4(V=GL7VQ8w zYB)Dd%l4_UfwtAUY=#{l<$u?R0VBgxPon*OQs(&b?!#&OSYu)%6sSrAVail`E51oU z3?4@B9uLI9jl~Vp+`szO=N0k0fBwT3!W1%!j<*n?A#GIaVONDmCIqArMLJM4TItm@ zpI|)4f1%mL;Zg$cBAcM9Z@&BbI`xPD@%shoAb zJDFycva(*hdVPPodl9Gm^Ei+C?2DI4-S*x6fQB*sEOR*!So;YY=d<0*FJ9kogRjox z#C&18jw``zV$+33j%p6*U5+!CHHb&xFY6 z?(S;zy;|wz6^8aTYD6v4y61dD!qp$c`WIL&?1)eIo0MfrLfz70lYG}!oEj>XNd z#Iu%Vtn^|y|Glw%BeCYsPGV!gkn@~DR)YYDooh%QaYc;SHJ!0 z_y6a=>+!~bMwG=qqn1Q*no4rf61$zaU%_Nfwd|`@5y6TQCnG;yuaJ^1JLv&S8dT-o z<`ZjU0&V$SH6K;xFN(lHwSRKJ1gRL zdv+r#j<0LZTZ!Q9mUGtmbf;uQ5Qs!*5~&Inp0CfKwsEKuIyuG_7(0=JwN-b1)u&+M zT-pP(*vV2&Jj=@;!@_>t3TaXfQ#8vkv5{tg*qoes&mOXRY>rmy^@nt4yuS?mI ziCK(hpR6pq&5l~ZSjvgLFa?d07>MBqAwU1yU!TAH#wvqKLR&>7 z8NuO8WYma=B*BfYv|~iL_HnPAuvjMk`tSZ4S9 z_NNL)jOPzeRr_`s9Sh{dt_O*J~&vOXXxil@jS;g!Ac^S-}8D z?ep>NyNwZr81Z=B-~RmJ?Z5r$cmMUDe*EK)j_X0!C?t?UY!+PjgA*fSqehogYxp29 z?*s-#OHQ)%ak=ynUIRQiGvH`EbzYJ6S3GA|Olfs{9eFX$_NoqSqnjQ7=iW%6WG{CrS|+HCGswpg?uJ<*4abvdZ3B-}F_j^RuGTJQ=FG z4TFc&^iW$6x$5?ocD96c9f$@USSN+joH-r6e;VWU80QUvji#bWH>ixJU~4-;E~9p) zjmX#}D~lwkGQard%NJjK@rQr;o-;=WTG%%m!*PcZnO>?Z*+(jaUFs6J@YESzxkXJarOciAqRwzm0A4 z)ncE2T=Vw*kIWe?Zk%KM>EHkS!ykXliD}p72-Z{$YRn zwzO9w!7J*z&u@SI-B(|Hu|GZS*B!l`WJkrfF5fEUZV{16RQBQ3>%UoOi<1iJsWi~p z6avNJ0H8o$zic;uUQvoHDk?&UO`megY5PZ-EKzfghf3`*OS2{61zKO`P~x8TwU`rl zkVP{s*7uCozjrHYWeZUzSHznkU~jb5qqSVf-s7V+Cn#kTn)WYO^!KJ(R$vhwVW1Ur z;}^w8ryMnI)ZD6P1s0g#>BsmHyB1zc{7!3V>5#uB=u4OF5QovSo-D}BNC|-X{hH22Ld15y8qpmZ=;$#*H zR*PclF`<=Kt;}lrs?S#?9YVtve_O*Go(WKL8?+~SpZNqLuzprZjc#(mNE-TMkAH9M|ltYuqZt%e)Rhnr0C_fn%%8(Q+D z7Hv3Vh#a=ku?8wqTbo^(5t}TEq%fG_6a*k!eLvi~qR5C0hcM>clcU)uN~v3+HU`o? z6CR29tH1m1`~U5q=XJ)GOY#=(GqZ2rCwZ1O#(*~DuA*cHi9+tB%hqU3NE|FNnC^{g z_aAyvVUQYI%-jCztIx;X>8HQ^{OZfk0mleok(NCN9E-A@o?UYk2*t1^oabLQJW{ivtsdcMARd4C#_a^++atvTcK^W%?iu0Q-dpRU~Vtm&216zZ;e zqF(;$+t+bGApO{Nvy30-DLQOkl33BtjAzN^1EyeJ$;~}Z#Nu+8qNS2fyRtHns$wYQ zr=(gk=xKg40Ty&@#s-)_bvV384z}^AZv;@%WKaIK2e9LBj%y(Xg3i)y{pb;5@9~!WpX zSjRS3HcFchj%$eRPfBC}>E}lk*s248j3TldIod+rp+MCoLk3|Y9Q55AO#`o^Copfv z6&)u8FJ$RjoRYu{uuC1xv$=YvI(*xqXRT{gi;bl{s z=ZWF5hR6by3QeV`IZ+%n%E!V)jDZcDZ4()am`X3~C(&(%hC#VWyR#JQSAX}bfB$d4 z`{9p2{PzEL?*k@QS#W|?*c7{b<4!NRBNpWv5^YddS(U5q>Y=M-yVjX|Xp5~*`7)hh*RXvwy zL-L3CStyH2Jgbuk~=|%zGEDB_fi6W3E&YA|;23R%moseQsu~th@DS5Uo0D z2X{3s;}49=S{Js@n9;R(m~4}`y0QvwV(D?d^~ne)XEP0DW4RJlK_HP9kcFQzCe5q% z1&0oHU+7kU{z?`x3g(vE1Qtxk_{LIMFEN7ErWq00$;AG(A^?phSy+<>FElMg!!|e~ ztsL=mn5gXiX+aO4!myN8IH6Q34QH(gS-QKNzWDXG|NOuIYh9mP-lJOV52GAF-EA8h z6vxpVm}DNn@)3`N$<@VHnT;)LK(K8pnyU$-e*M?q{rKa%$B&OOqO1?-ftcvN2bFSJ zjoU9XM%+F=&wZXwClBQtwoqkOA-K`+S+XW$2gTTgGvki9SKX^ll_%m7c{+orp$uVI z_r+rvg_FAHJ`uU5K1jJ-vdEN=^E&iv;RFm>6i%4>XoEh9fp&2jW$}x~7J`XDw6&}= zP$A1mgkzE&WtB-Oiz%aomin%@3@ypAqqwa%t*nmb?xAEQhpoBhu zBZE?3oB~wQ(qUsTPHiGqzcEosv(&ICW-)0fcYop7P8vn^qn}6e_gdj;WY=f`J2t0X zN|I}t9gW|&OH1AR^pEBsTmW0a3|G9ZPZjdB4z`X@maIv7Z{d(lKflE|yw}9V=I$K`J%aKiEML#6%^u!heWE zW-A=w4m$X9m88)-X%vR*oHs{^*<5Z6i)c#J8^$`H`?4CL@+RxdFe?~8-JNU$GJ98S>nwW4SdO)5 z5YJ|9clP!-u~hsB)Fy=@O2ghueS&nB8P(t7bjk*uJl+N9P3)r+yo4mD0fc@@JhT)m zQNc>6ragIsyWMTx+!}A{bEX3~g}qEAMr;V`#EMiPa3(^j#0Ca4UCxlCD)aNNK7V-k z@ZqO7TZCpQluCQQ{pYBag|fJ{|0|oeb-+T+P{~1Is9`o)%R%V7IF`vmTg!{(-A_0waSh=3y}l_6RBj1`K~w*8d{>7JWf z1G9R_FZhA?8E%WlIwymo(lSkHNkOe>?|yDo)KZKzp1bZ-i(!TA>)jKwG&Gz@Wk@Gg zsi4AktPxl>SuQDTOu-*M*YCYCu+bV~I^GabsZ6bSrD%kZPQJ7pMXD7T&~sp)G_5x3 zTdj(vtrh;|Tg?1>Ln>ChA+kd;yxD4XeM7!E%Lx%xSlK!qnNkML9g^yt3_oNp(CKQ`&sftcet~T|IrmUR56X{8~7VqzvCHHo+1+M(0;{Aj(THCo6 z;znQD(RfXTHJpR4%mvCfm+d|+ILf}l;rM=)G+`~4At+TX*{B~vr<|7P>!EcWkaE%S zs_I&prsh6zCRT)^vy)O$WJE--z>>R+Kt=S;BUA#}&~9W0Wg&$ z&mG|CGGGYO=fC>=#h0J``@jAGEU)gyTyFbnnO{>%J_!q`4xmz)#ARhmZF!@2iFsRh&{* z^{MM58|$XKK|*y_X(FY}PGd~fO(^YiC)}j$Z`eof<_74g+OKo4)i7L_uisaOI&0Wr zC0vx5RS;$gS2{~~PdUrb2RDOswzu^%4JQ_P_yW}$AjceZ+G2ZDxwzPZFp68*4XV!L zNZ;4y2vO$kx{_$kP+ZQFt}^QCiq5rR3u?OFHhSd5avU_{-RO^+_3|m*_%61!~*>*7%Um&!&bw6Ze8z3ra%A7=lSRcPTV`5K4A7 zfP)USwsZps>jUCyyYi=1uA(S;AE;JtXuXs6%Nn6=p2(-G%Kw{?6dn0ZMXEYXb?HN` zhdL@+3(6K_WUYXRR#SFhk(Jj~s$y8gtj^PM@q}T^0_GsQ{%$kJf)U{;mu-}2A0s{1 zDwHfLa!Q$0W@aH7aN_CAxLmexe)IMB|NQ;a`}c8Pbjb!GRny;RS1BD!dX?+tqGKo* zDjAR$gMRegap@ebRnb-@=f@Prh|hoh)z3e@ozKtSIQZkcpemKy3~XjvJR%9$aYB9O(@NT71|aW0PBP7pK{d7HvqdyCzy zV1-4cK7tVqS*$Xtp%|XN!rYYV2uJsinLYH`|KLazhb8x{-?Tui&i7JK(c&t9k`0gp zRMJ%xh28=Ud&+UOZa>H)Zp35;mqNVds4*I{MWu4}r?sYGCETo}=&p{APG9kzX32q* zL^C#8YQ}|lwaJ5()V)<-B z_K9nyd^F|WI1o}B5X7K1wwXE5J2}V7YEWaLc7)AkTd|zB1Gq}Vm!1$#c3$?lD9bMu zS}}uVYs6ZPt8ESKwlc!vZcm0oGF^B!tR!^yAK~I^W0Vo=%JDS69Lww@qw%d9Yq zfi{;Zm5%!A;VzoNfA`(x?&X_5zO9_rYa>C> zmn)gB_6o2nyD-Iwv#|Gp1NI=y*&?kj4r;64NRv!M!2@lX`Kw=l`{CjF=O5nD{`?+r zHi&7;QAaWhpa941_Q(yV`%7td_EK;#P~`wh%*L0G;nh$;5ef~|a0~B13@7h{(UnHS zW0?BnI!AbL^L9ReJVzVV>VL-=gY`pRBUpkej}?Tycr1ybKj3wux$5ai zR$aGMQv!{zbLk0IoreO%z%P0!T@^qpYg?&!Y!R&xM^e*5sH58$i%~`yO3qMc8Cs`Y zSXFY1aWBitt14aT;&s8JsB2#-Aq=~!*Y{E-WemP}q)d_rDXvPPLQVyM19?1IRC$VT zCL)G$Z!c$`lKKc{TY?gf{^**P$Y!98tYLS*{OXQF+gcya=RvV#4(tYfmxShsu z!ZC%7IE`%!Zb)bA#pr*!La719VA_S_kD^*x?emVIat*>vE*UWfQ3_@EvW^DY{Xbn@ z)cq7a&Med;k1jetuU79hhdg>_uTl`GNzJ9eR+SJ?N8F|%OHaXIDYynUS((;U;*yOR z4QbFGVKI$0Cs;QZvmy&7`_0EAMwt*ax#tA*#%K103y=>Mq*`nnpKu zE!CtJZDIsUSj8UgQ$v=r@z*|tBQYx2`ArazDNHc29Jz~m&5(@>Bnq)e>|R^aL8mr% zQ7R3tTJ>-uXFpg?{VsWJ zx5BdLij^xQR<;}37^1}|pc7ic{g_R@b^9EP(K6~z@$20)QHktmQK49&2~1yl8z)(ZW+TN@6bv!CmMrk0Z zO7F)8T0$DmsshxxBmMw_?T?jvU9;n-a^a~54rq>V6Gj7UVhF=br|F(9V#SeWNdH@G z2beLaR?ZUT06?e5Kyv;i`qx0^Qh&v^4RsDORv`9LmTaL>V>l8`lzRap^LXK4^aPAR z4o%`Zq6UU9$^mRGd16!``OR;?dwiN7etbVRNNLYe|3I?u!5+pmfbTG>g`>J;yT-8# ziGx;TJGjt9dWkjBh3Fx%@*LY&-+cM@=eK#gmDj?Cfx8_5YwJc7k%M@6^WkzCK9&ZH zLttfP0^*=g!zP=-SS}&V+~$#%qe?a{x4X(G zfU{LB{D%V0Clr6PA56^11s^LOn;BI*%r5=YQ1r`l zLYZ3J0wfL>qV{&#sTE$cKYdl(Y|Iw;{0TUS(Q`%f`fEBgi;f75-cc4A1uIR_ZnKUJ zB*G*mdTX}GH?6Mr77!MXHGkP3aTThn@{=?xj`gsE1zIgr5~^!AqZD0sii&2BB)@rZl^1INid|PK(3RCTnQ{7QPl>prR}c_O(<+ zYZ?`m$|a}s_*P`~fZ7ZVL(MArB}LVN^k$;$+#emhik>D8C4FfVR$B_feldT#6{VoM zx1GSsS_=h37(?(JODpw!k_U>3QPVVAWs5GQ8km(YU%vd}>#zU)-@gCmAHG8tTZUr; zr5s+P&S_0e@Z2FYR8n2}*P}9-#Zek4m96l8)2mp8*qRFzII8qlfBo&x|MrK6cMqR^ zbLmO0I={eth%wH{Wu9zI}Xret4En&OFd zCALAleO_4naZhcwyJzNRuQovqq17?vN$Ak+$ctdlkXUdueO7U4{k>zi><<;;4naQ@ z)iU}uoG@F7=v)s8it2`3Z=#kdZk2HDvB`G7P1Za)hAIe;w9-Jj+sICul@ZwT3vb%3 z>@XUd&?wq7R{$_*Q?=|QZ*bfF;STU(fx|bF&jPjf1EaIuJ4Zp#A#U%p!&gJf=%N&I zO0#37Sp%${gW%X#KJ$H+#S5shJ&_Pu&uc2eb6ysSoM}jt3X=O zX_%yoDt)6yH$am^Dvu}YR$MqwxsRYw3z|3P7b{A~e;13HA;z+KQ4mI>7Sr!~v1t;a zs8Feb*5(tHVpK;p_7KqqL%Tl=;RLFL7WuG?w8{&wj2i}zcn-GdEo_65E5TQVa&!O3 zSixf)_s7{6Kj*0%UQXpcY|e~EA&TGmh*?sgL$*O+%sd0k$scY=oNnv z8Z`<-Ss|oy2BxqP!<~@H?KHmr$6x;+|LgzupMHFdak5gNn`w;)b)F&u&U~qIw;D%6 z*nG>$hM~bMMOMXFJ{pcs)eb96$Ron5uV3QKAHM(bi*LT%3o+Wp?_GcbvYd($5zp^G zAauUJhbkC*BDm2o;0P+S2cn4LfRy~=yU)M=)fa#NU;b0XKm={7+2X?wZ!V>;|K?XE zgz)xve|-15?>$^FLfV8Y2cNIkoavaEB7!v-X{Amq8M&vQu#U;kN2z^C)#+7^Q!_{= zS@Q*8(Lol98w`ncrc`60&1cY^%O3R5r8HXdw*_T~7~yrqxNfPyVbmn4j76A|sE%q4 z1Y2i1`cCP2&tqN`M>MvMMR{@f_1K!lG!oU~)dt>LmhY#%?7s7<>E)1Z9XO`BogAvr`l!u|5vQlDV`eptZJbbdVN9+;@Yx5U=)julgm9 zj*@D2!D9a<{P)wdeyF|)i^%MRM;?O34i_z|=WkiHXSy%w3fp*LQc9|MB1dRU@aFQl$LGHqowB2pd+=3(L{}UG57Gb^TMSH3!N> zXp{@$6oO{4GN1@Xmd@w9FTVTsPk;PrpVRHR#=P{2$K9O677-8cKB6k3#g;Ut***e~ zz{3hBo>0^mpTGLM|Ma)%fX0$C=FUB(8PD%;i~*{&&F%d1x4((=OK@-u4h&VL;uPaN z_ACr>Ojz8g*wEBrG*BTb6`AO4Y7><>WXxJvPtv0GR(4h{2|yAvWKA-bRR_7klKU>9 zu^*Ti>%?pxFd+U~%bG2eTO7Q_H-ctf>rhaslaAX;WlZ6SENi%+Q6@6QnI)A! z$)+EB>4Lm?d{T_}x?jdBP+6_kNoReS;*nvjxk{Uxd|p|K)^PPN&`fBxx3g;1V=nBe z``8)>vU#)7qdE+6*->DUh2{&M7l!EkRsbp&9!Qzxn%Qtv)Io#G=7>&ra9@c>iB8hX zHpEPKZ+O(TO-_|QVmpc2qS*DJ0~1~IS1oc_^3#^qB7$6Gd!c91BC69omC63?H@&;M z%2er3*3GtlHoYh=$-y+c1bCRY1f;B)nkWB|#7<+IbKG7`iS_)ZV+0 zfwI2rRMKg0UXL+`nlB?YT#5q4Fn|nD)9FyG&~Bxyl2KmI3#S_Y@&EB3e)qdSe*Ez* ziP9{!&m&fcT?t8X(kX%Vbw&k?t#9p?xF7~A!Y&=o=14ou@(|PrQYOFs&38Zl^ybZv zZ%#qV6>h#hDq(EG$dKma_3r-8epz4y6p<$NW|d;}J?lkE`Reug#pf@!?F=a*K#XB1 z3%cD-=WW%hD=yplvzHz{r;j2Of-y!_`zBfnrOb{4nBZ({2#StiJ+?s&eje`Dw1ORTb@=^hD!vxSJ(B(}tu%46fWm zd}>z#J5-=y($O7UzUtkg-O`loHeH`ymRR8zY7g{f*(QXR6r15T(YXjjTYXKn81VI5 z-ZdD@p|yNL=;Rjlx#;GU*7VZ>F~;bY($+XRWFR*QIVgz5Qq-XkHJ#jVWUYk0g=omH zc3*JlZQSUZ-^?_LI8oMe1Q2PpN;(6WosQ_Zg{oyt0Kl|vJTVnE9C9fxN?ig`LYfLK zi?CZp;BGN3lZb`xV6(qkK6{Us?vf5^kSqUBN1umE#gahkaM!8Bk5evI1YxFx>MM_0B4r{(?;w~L;)*^x%xzo>fNijMuD&H349FUA<}et18^9B_@J;kMe@h2Z}DbbEMu@!3n{I_7)| zpaP5-zWiCvec}*ay?z;|Q|+0v3oa#zdE2kI>vem5H_r9ty9*MNwbxnC0s zWt1^PtfsSS-H2Q1nZ0~hpJ+|1dLd&55))6_GB}xMtWcPBmx<5otj7n8z`>WU4 z%wa-wVksQZkLc{FHk%@An$QPBLyK5G86C+xwamXw^R>^%+VKjA8T}YFscE}M9F~IR z16}89i=VsMJo>Cn9^;!?qikw1$?PHA8rX&$OoC&{l%%F@t(hYH$NPTPR7d!tz^S(3 zcNRyKGvSt^k!^%U$I*HiFdgkgk>*3H_bY>X*;f^+=WOpPM$qI?MeEr+xZ4l4yBY^l za7()z9^2dB|4*A4JTOb*Y^kqRN=+Jw{zK8m85>8cy5rut=Wg^al_{oRYxRiX&AIGe zRF#(<4*(s}s@6_MGY2SB&4<__vV5SS9m0xw z$AmjEZ&?7BU==HIo3-FGHj;<(Sz1+ng{?``>uHffasfpBVKWqjwpJ%OYP*fE^l0V7 zs@B=<+i`(jYKqtbA-{=6KGpHFUMjQmj=Ou0Ztq~#c8q?p+H%T1qe)Cx#3xdqc3%-r zS|}udVp;y&&1_RtBsfosO%Bpg=O(qdVEBxtI=?U4zr~_XXa4O!{_VRzy?3{C3zApi z;D#EIGXpyc(l=TgFD2O+j5tC`gu<{%gTu+_^oOz{PZ;9;>lfet`kSBs@>9+!t3^Bd zUVVmW#?bS_ZG?S}X1MIht$%65-2=>;9;4l!)CxCivRSvjF~b zxRIrxR^|6h*Th~gqOI64;!sC`5n8Qb2W4~50Uth|-23veLS%%Mt_ynVO@h7RE?+fYaTp*cVurPj1{fK5z+?y=oQQED)TXFuD-Aw1V*F!Tz4TB13+eP zy;=Po%CUAUlBxBSLRK-0sN(TCnw07X)bhnZ2?I)KYFYOH`_-4^ta^9F!Etyus_fit ze=`G;N$`~i;dv_A$=v>7^Dw>IVIW`RD6c>%PH!{*a8MjhY0F%1jRiy1Wl<`r%1;I| zt4%o&px8#!K0w`OWzN`g&KWTnRjNWTxdlNwHXveb8Z2eiL?%EJdIPCsR#?a2tz0No z1Q?;@#zBY?-~9T^$LHIhzW?(WK;}4N$;$(rL!NE&Dp1Mkt`Iw`mZs++i!mO%i9m{KNhN7Qt202>KYg2=`*m6WiAy+THCBST22a`pp-8;R_l8n(Z zORP4GT7jh+L&C23B!6{`Rd^#x6kI3Q);J-frJ!ce&_$eV6%Jxrr>;$e9x2-Ry^=O+1V>-$YCO=js=`VcM>(^- z{Tc-q9<@2M2fy@hQ$`2Y2v|%9UigG`d{C7s`czp~KiaQ>?31OCmhm&x3spPU&BCJt zG{j7(A_^hLXfJVoQXU+@m2t?9Ntn^$FXc)w^#f{;cS`O)fioyo)Lf`6Dk;Xp)APgo z_aJdTzkUBSpRU8CLJydhm4tD|(f~*G3X2($F&x)v^&L?xyJ5Xh`-)%yoOSo&^!0DQ z_~-xQck}i{%zikd5STl&b3hiv$BHtuoegM87&Nhz(nPO|&FH`~B!R3P)Tl%v_FH}P zt8d0Q{rkWEsi6VF8c(;00IXYG-+g%b*?ptZz(8nqJ)>N-sBnu}@C=NB?J|Ivz`RW& zh|0=9KD>RrKVO0-3M)czzuMS}c4$>rMr^=#ecC&9CZdEL%?Y$E$yj=qV0lL^xj~KW z1j1O-lQn5ohk&50Td|vG@rZ(AnP-bNd(K_C3f`lNNXMhJw9Q0V3+Y>5*>_Guz&${Z zqBPR)KvQ$wI|n-0wFfD)d)72(7(Q^l+bpzB#OZBjU0BYzr0m!+7h!3<&(F>Y^3Uzo zu}&Ub;$YMJ_=KKvc;_iqXTN!P>h+_sv`#Y{)+8j%j~aUyAx+b4jbd>Hm}50h=gP(j zS>0T!YUQoC+-gRP+Pc5ge|{v5jo9>H%3(ds4PaMC`=FM5%r{2^3ce^@j&^u_9W1x( z2{QBtbly-1M1?WQ7Wx~p=$;4IpzA}OO`hAxDvUaoznE^8rS-Qp<|=C_Bo;8fX_(mq9Nl zgIX2PrLMxCfB%=;hbJh+%AtVH(ym$E z7$b{*!D37@EBs?SRVAF%CL)z6|0W<+B5eRG)nEPNU%mO^?VtYj`#2ROs~5)z5D7^& zmYrl4K~~BdH(_N8I)d0;5vKp$>XS^nMlxM><$5C|F5CIbFJJ%hU;eDQLX(izm)OxZ zAFuoM7WXGFN|os~T`EM8tU@4S%V3s}-5$;nij8|tA-fq-eE#rIW9t^aq}oBnhVCRN zH%4Th;_Rsc_7yrlcG|F1Rh5*|`7+WP0|bSer&c!Pfn@_O0JR0A?GZi(d&X^5Qyl@Z zu%6qie=K{r+{2rGL)vLz@FZ6pR{@AH5NK>w)wToYu1DCK=#|tYZ=jP6+K|93mUBdb z>TEF5=>-C7CB9WnE?Ui#jlV465W{91TuA9$Kq$RFG_7JJq)Sw}Hau~~f+{_O4=wiz z4!;c6$KU~>b@%A=SA&SkCJwNIxnlZ!hz?OVGFE*vXmJjL=%-~>$z+2#^q@0+$Qr}7 zhO$Pbx|)gGo$%uB7*Q`5_x#oRD$-!fWhus&Q8)g!K_eyUuzCai+61=F+| zQ&}mxnlb%4_u%epsc1=ht11v&0YZ(po8mHx>l96`Lu)ZItrv8g1=&`NX6Pj$EhhJl z1*P9oxPD4YXJD;YAV#LE+pP>80!&XEK$4Y~&cCzox>a-0>1{2u>)WW4xzTq-y>XOwdp%v8EfDaA78prUXbf&t68ZDQ&<1 z{!e4x^y=>J)oV(3_bnB4&Bk02u|Mx?>g6{oSSJG?Z=XJL`6N^~x;7$-{GOaNL!Hb6UdB z?Q}$0AgYRCS$M0+9ecUTBvKd*jn+{E zww^znJ{|y&bQBy!x(JFMVtoV}DCwTY#)=!cuPmEiA*2D(6%vE?1tTy^zz7LciJN~A zqv_KVTsvzUAzmTAEi$N1iS+{1y=d;=R?ILLoE;Y}YPT)R z2T4RvrtQjeY;UI!w#k|HXAFqxzH2HyAqS)hBWqatrglEi*7^`L7D;Q5j~Cpm9!}Ls z11nKJXp5{BwhaP}R_>uCs>aYg;V&DUe`>3%OefOF#DT>$DghSKeR|gZ`fyr8&vNO` z=wH$3n}*AP5ElL#uw2F;2X~}>DDEq(N;Wpe>iB8LSawG=eE_v>scCs&*7|iFY)Rur z=G+AhNwd2P*=vPZYVnH$vFq4wR4u=Dr|%)n7s`xo4VDG$R!u~k&Y-GbUp$s_nqq8E z@exKUdzFBSj9{3Rbj+LyBNNGxj3`6FtY*YTW@*^sMGW{muHyQzyXzEP@|g%x!OhpK z0@C)=4?ox3e}1~&zj%3j|L}N;cbZwT5n>{CB?I%ujS5nkra#FIP$0MFmTYGZynlL% zKflqu-F@}?bb0ad{qyIa-<>X}dEMb49u`A2Rp8(LFMs>L|9}7Mzx~sn=H30{`=`hK zdUtoZXWZRiUcY+z`o-n);yzF{H5Dhcb8bZXK`4zWDkII9B*iMGGYe9s7^*slCY$}2 z_{Fzhiu~#OpI(0Uxy3eCcM;IccR#ZVn1>M?;NB5LORod|T6^ zNJE9aqW4ViU8F(4Ht3ldK?}(gD>yl#dbx37h@Jbe@{cQA4?beD{I;yDn*LD&Z07Y- z_P5_jb_1!~eEq3Yr=OH%rv^kLNnZ%h;-VlMZz(`=o| zgK*qHALq-s9wds+lr()rz?n9lF2Dd%16dqiYjU-v^hY-+r1O_-8?1GG_$DAenS>P1 z55%Bcl;qB^j&Ln4Mx!sbY+9zxli4DKWvfq^qNp|Gh)#rZ_8b>J+`_K)bf;h^YT8FX z5bUP7SPzWL$*M~uJ#ih`$u0bI7ICGxK{0`S-)|qDw^@%*k8d8XBTnZL_m9upAfmK< z(h;g02rFnUdRJ!JE4kzxeF+)BDFa@9xKGeDm4s7ccLkW6VJe zRo%V3eD&LJfA>$n|KhK|o449$Dp^$@o^Nm7JidB){_^4ZiKsHlfSP^;_jwzt zEFne+$QAqHu$A7L!^)k}9+b{(k>%Lz9IA@0e>!yT0g0nydf6u$gy?f>lnTX7NV@gF zqmmn7my#ds)@U$YKh%$D2+ZhfrTaNNBhs;PE&8*eyjGGBdX2|wd1xsH$gJ7sdB4vF z5XLAXg^dh`4>T{|Az*kgrxPSlUH6OO%!p1cY5ir{7wx~CJjXC$uDW1i3pUGxv2W}S*HBYqgmaOWJv6g=$qex`SASqRLv2Y8> z)=94wVuq;J^J@933%~df8Uew&-MbfI)U^;!1B^cb3 zBb{I+RbtrFA1$Y{`*iI-9jw)YMn45Y_+yM^H8J|RC8;)U1xAmInI1*L|2hV1NHD+U16@YJJzsCe9nmKhe#O?gBQ6>I+5hzwLY z3pnQ{5zn6mLSTq@vig0|Qfat9@e#{P_Ms`~LAmrRLLzhcCW) z{ndHPwq@)?h3)d^?&^G@AjJA zU<{aZ3%7ehg9<8Homa%FN^t~PnhI8qD#VEhX4RSU;jUU`0&HeU;Wj0*{2U9 z@c8cId2E;ayUYsb>BON6tj)SjOKw0qCz_bbR1!5Jo_0$QN$L6Fc6WD=16|D#l*r+( zXK_GdXbUifG3vUbO4ve!E&lOwz4C53rQsQS_B2zHMk|zFM0%9$Fh{YY(>v;eHmX~OVOcr?j;_pzN)4N=#*(S_*`$P)K^ly3XqTH}s$>KO zWfTR#+SegPBoWm=XVQXmE)JzzK3r`HYA*5NYK?8&(fm+gpyjAh1}9S(c9pjIt6}7F z5}xH#y;peD;Nde2`(_L;R@bzxZvbd;-IrD+R{(r-Nkt4$iE>V<)A*yw)0CZi4Z*Jw zu)hzMzgtE?q0;m{PQju>E1K+KpY8PNYt>uE5mtc(>u(m^TK>IiG`)q*6%que=m;7u zvPN+#UcK_YtbLeK^T z4`Hxf^H}B_PU`&4=>KA^uvaB41%vgU$yHC`@nJGc^ z@Y4uL8BXo9&~*hd#A406@}xIs!g>6HG}t!<*YIaX0nU*%v=&xbto0%oxg2W}4A-59 z?duK7DJv91+O*%IX6}9lCwBx6r z-hT7`>kApJ0br~L4=ia2rQB*78s&^Sb65)%3KTbTH{(WyV&C`AK6~-m>sN1oe)rX1 zeJg<&0|nsSpMSc0aqbD!Z*nPA;fxTZ7{EYkBP$St+f9|j`7GztX@8zo;0CBZym|Ne zSFaa$*fAr1dNva2j4Uz>b;AjBrW2ejNs0N0JH z4CxSOc?Mftp6@n~PMtimLgynPOk*2PK3Ql;FX?Tg@^o&WvAEvmAQG-HHzGQU87q-4 z3Se1$<))H8PW(MsHR*3F)O;m?4h4${b_CYi&<6EO@JWl7U3OmQoK%BeJyaT%?nHNV z(xCc<{Ny0=Ma2RKyp%IySm#%Wq0TW};wK#n4*0}Fxmc;QFRJm{T7kx%<{X)~6jkdq z?ybu=pRs!?s!L|oC{n-T9T1MSWvtQO2UnE_`ne`(~{I!>{CU5 zS&r&(6k|JDq>hzj4V3uv)#}(;6-8V;8;;*!xni-S2z8X=^^X{Cw_y}E!UYg*GO+qx zZD0uop^7C~i-rdiaQBE=tpPJUMnRDloN{T&h^TM|RD*DCj5!2ep3o1ZR7JXR%zIz| zSF+Rk7R_EoY}cImd{beZN8~=aPu>cpJZU};APU8B4iKOSrRE5)NM1rJI0~H5Sv+m0 z)7Uch6C~}Fv?tGJu%b3S>;3iNzyDwV{>AH8uV3ChU+2^H`tsHN)6ehb^CMs0-ER9( z`P4sWt;#a<5M$5*$#ErC3uIEDzL*cQB+pKhi7r^Sw#AFd$NORe{ z8*-Hx**#6itLvko0Ta_fQ>Ee{%}5ds_*ETy<8e;<*uZE6fLvyu_1O5VO}|J30i`@8 z`W>>FaIBGPz5gm?yPG>MF?^nQ@HPXVSXC~K`LaV?*l#_@6zBk=SQ%kbLg#!CQ*`PJwFQvuAu)P74|L0`;l#d1Iui~( z#xkrv>Tck-e(3*eat< zRH34=WURm5gNKD?1Je>?|Ekp@3LC0B$g~l6w-a(5{RLJ`*|F|L(@V+fSf-p6DF8A3 z8C44}-G|4Hb^{Te4niP0pnuDd)GKE5_@ND$9CQyH1#RGx6jYFtUQfv1JCE}e0Q#FptsS{a^sfLk_~lxk@k7IY>)3gVjJ82xm3ia)d0ZY zR&qdEEfrYB*bp@V+X|30W!EPNmom!f{JC7az^VX8 zgF*#?Rwt5V&9)9l6zuTr5L&f!%=QSa$sL)L7IuTnt=vxHa65lRqa49 z##$ew&QDpDfBq;`%{ZDtg$fvg#9*o2?M9{?NcX^LmZnM4xoSh8<9exIC z1+MV0BL^tkU^*%RepDis=``qcKX$-Jp(rp_Cq#oAiY{m(C2Y>#au$oRq-sgR(iud@ zdbGkXNNsYZw_>MiYA|91!5SmC*q&4fp%Qr-X1l;`D66E2x^WL_fFcJ}ELIKZdfRym z#n=r!Paj>yAd%aMB6Yn*M4V0{zWnO*KmYp=b-kW0cXO}V=7|c;2+rb9Z=YYkzFqE4 z+{D;^{Q1NFG@l=zW@W0jI4SVF-?S^p?X;av+x=zy)vv$ewpr_k7%6qy0_yY6KYRV+ z<)8ocFW>#c-+cV=998q}$NR5dBnS*fZ~%qJ>+S8whjAJAxBYZEZ>KRBQi8KzE};~2 z-dGi56ZYFa@4%<`4{>4yXC@d~8Guud=A6@2iO7lsvFB_bez^zQFQeNZR542%i=B$! z5@M%Ndtk_AbUpN!a)?U;CqL&#yqt$jqVxzVWvILe zYNay7N^xs;%BOt4^U8&ie=;kW%PJu-P?bxX-S8^w7sr$B)7daa*r%n;w46E~+mcOjL_(Jpv6RG{P^Ue0#5R-p4npgWF7R%e{})K{p+} zEVs~ihY5j-gQkT50Du5VL_t)poL@2i6|&5#gs7pYqDJ(e)+eIJN(TYQ(pl9C5UAB* z-|ra{IQe%dAIW=a+(36>v$MGh}x6`R=dZ`Fo5ik2MJ!b>f94szAC z*!_Y}lxlMj-44f$3UEOuY9%GaRB#}wQXQ8nhoy9|4H1~$9oXBOUjhqwDqs+jFuWMh zj0z%bAE-79Z-NS|qPyQ>r-~hkq<-TIKooufoCb)lr%5w39`tk|gxHcim9_#Ii5;lS zaT;;4drhbj>R__+?}eqn225=sY~k?cG;B!j8P6YY`%^y5?R=TVnO^^5EC?fy&DhJE8c<#jz(%-FX0;>(vcwjY0bbH3dD{Nua1PgUJ=?wMO` z+iA?I+w(-#h%Hl>P~C1{eEsE%*B7UwI>FC$z_#(XfA_23|Bv5)eE)tZ@9)p=7_Ywm z^5I!Ozx{B_dEKWiR}W85`(I`Wm%H;xlFh}%Br zZGU=ty1YEiDfI8!r*37|`wtJ#no$|h4(y27bHAoab=!3wsUZu?kI2y|6|wc}mJtd%HpOd~Pkm6Rtgt|%omSP#t>aimMT8rAeTo>98IFbs+ZBgBRwhe2xIPvZ zn5{Kps%+hl_PwC|ui7BenXsOHt1*?vj62Y?J9X%gZyv~Cnm9*@*~9HBrFHh?A_Xj^ zb_h@LlgY^*9)ASG7k(Lo8tp04y6z8nltpt&XdS2X0ase325KSO);?0M5AD^Gk=W|iHiwF+7_kIMp?~hMU|NX!I(>LFKlMnl2-QGVwJ?xL~ z-hafLPG{bLoORWXvCYT*`TFzrbo(Mby(1zzN}ep~L^2{P>w0^Bdiw0wpMx;G;jL3c zB<}Cdw~&H^IQemn7^f)Jobv>fu)J6$jmU1*n?CVMfiNV}dM`)XYLR&DQBSwLvGY4P z+$n?#7q@6M(|Kse9IfA0*A_A|iC_|m3ZYwv>{4m}Sy}1bOu_K_Vfnb3)Q%+%NQQpg z;Tbr_cYttH3Yi2@Ly^)>824!Z78EW8ppwZ5wST!;#Xg=6`Q!qmyz+la|Lg?*a1@a> z@H!9xmuI2-+%04=YBb2%ar1uJ4~U>e;0MU(6`buWh7{(%Cv9)^6O*HTf|dOp#&g^ygO4u?X+@|i?v zgtz3XidEp$DlD#eKy*Es+RVp>#H`dJ3Io&zOiK+~(NXO8FUiruAb&+ax&Ad5m*`K1 zh_$#j?|l=U&R*2UKqdT7pGs%ObtcA`VqhC9ro4aBsjX9KSr$-KsubIBLP2C+8BaWk zJGP;U`TVe*&Zko(>NIe-&1dd)Lkc@F&Rax`h?*HWU)*gEKfM{}ZQO5)D(EzZ`>Hhc zFaPqVII*%YqH3NPJjIB(D7Vd!BWCIp5NC2YL+SZ?dwSlpiWM6%E^V>hS!d$@_2v72 z`SVLfUT+_X>mU9ia6^!lXKn>;!z68o3`~u|OF5H?liET%F-uR+`?DTDe7q_i<5rK? z{PE4hI6ZARRpqP+#rd*X&2&~o#TYq5;M~YK86hnbDeFCRA{bjU7HV&r&z(LM5T)9j zd!QwhUJ?TMsSvlr`DD*!D+XqccCrcUuHc07DIK37Kg z7liFT8Om}FD;_nv71AO_qRO7yQbb!0`n$Iu$$x~0-)eg@T~!8B;nouwXd)0v|JK+M zBMWKrXpc|FTiMPgH%KZ_oiGw&AS)>#EX1jG-Voig;yE4*Q@7l$cgQYAUyyzD_|+7o%V@1VZ^))u#SWWpX=5&rOGiea zE$M7iSWB|#x4iSDy>wMsspilbhXVN9@pEaBLDT{x`|N zpZukP)e1JJO~x(yGVK<%LhWjCM#DVGMqykSp8bSh(LLi0hZsjfyz*HwD+dSnt6Jx&(Gt+IrjQtPM%pBAy#Z3h;6IN z3USyoii#Q_Fz4$Rg6oWv|KD_-55=6u#H0nc+rRkHGQ!OPDuW8bGm zRdo@hb0)9PFGm2JAD*_$y&DG3!j{rjIF*8#$ruBOK%Agms5+gr7!}b8Sz{9_c)7pByNBDy4>K@cyqo|^gEs}#(RpJ#Fhys#?Rx>I5-gR^)QF$o zzkm4M+>86QKK%Ip={`POZy)ykbdJ!dAt*x;0wPW`U*=R*cs|%@JTT62&3sXAKnjp47 zl}jxp?^gykQ$mam7VVPIMlgJqx%Qx{>twS3%JP>%5ppNCsXB{sm;Aq%>K>XI&J+yi z@8^L*XkB+p#XCt3j+yb#73jJZLMrwzs8XA)y!I;@Pw{2i*6toyTZ~S! zx^62RnHv7SxNpulx9WoIXhMkDMdym( zbWoxNQ-Z^iqlcIlpV}nE$_09IUCJo686CjRh~)`r^PxzweRNmuzsXJ{^`z10%KG$5r=s@b6swi9D2tKx>ijr+sC z-H$rsMQI!PG%ELcxpi}VFmDn!Qk4}Ta-W&A!n*C)S^4qf`E-ve?Q?(n7=zFI_37cd zVV>^JuV1{#Ik`nmj;i|;liWdWgQxT9tovM4 z%x=9(X>4HwW3kHR-6@8`1LRzxiT-N{HeG7k z>(ux5ZO$mDYK(!<9OE2y-RtS;HWNIbu=AX#nG`OJkjS)h1eq~s0OOj{UZ(-)0ygg#YDq#hm@B4{?6jwA)w7U*qC(0e$jiGf zoAojlLQ=t+ib#e-L5;T`A_h2Y+Ow^^6fBLJjz|i2Tnf?^wVJKoP7X5>?q}5`Zq4r&SM`MuLcY%is z|I;C%vbGi{4Whak7op?K1;dqA&K#BNNZt1M*YJv~ke){wPMND|V?UY-odF z*(hO;dmVI7jsNm@|2X%3znpJzx=C4zyK?~Fyt;q!`u>);k#)c4i~AFaOYppHeEFI}` zFeovY@7_ONUc4BmO|FPj%U;+g=CsUtLYj3>eO7yEPN0T9M> z_B`!5Znx9(^Xd6|db*vSZe#Ae-L~f&OD?>9lzyJ5Vo=wo+tbr+25)=a_WAR>_dovS z&6_vxPv`OQ^!)DQJCWDx^>R5&WnD*;F&dUuH2ZI9fxGLLcEI?FqbSLsJ>H0LGf8_! zT6+x~qD4e&v=L@Yk0uQ3-GZTtJ`Wq-^mI+<_Bf5)8hdqmFR`-V80^AZOm$37ES=IZ ztFM`VX%WMw+!f;H(K0v|wr~jdy~i+Ppn+-!6VY|3J-03!4rGZfS9k)8=5gCj)pAAt zPw~vKGrS?OmhD-U+plZe=31qX#jE-rYje`4%$GwoRO-0NR-HOCO>F`0ukGTEP)l(e z)i(1Vy>zkvv;iX?OIOvZB$#gHQLU+P)C~c#Hds6BJ~%G-Zhzwk%jtxl_VYzYTr3pO z&r11Li$%1EvWmP9Fef0wkY&}XKwW?dK1u9NNfg4X9DwQ{3I|<0qM{}6?VzH@VQSFo zarXTNBWnr-lag5__nr04NvwzD7a@AhnlHh1v&w5Lt|CI=9T?69p#wfySm}XC$YDJg zovyM*hgu^37)K^Hd*d=^)sGfiV>WuzkqSz<)!a*NKgESj3~RW6&9#y~I-=sVjV*wz z(}}M?d->y^eqin|?@p&PiS2%HY{Oq|Kk-x;+bL*FdK7hkIq`DQh$-c5j_R;5W+?*T zJ~NV*jCy)1CTe$eYzk7mxLn>nJdV2y?l1Fl&IGb}z2!-q@iH^@bW;pM+a>{N)o-oy zOncRynN#P>U@$6Y=~jq@v&1%FpR5o9ciY%hx998j@=oc^8>)1mc4=y$R4MHy zL`6hqK7M?!?KEe;y#H|8HvLMUfBuT%z!F?%dYcfm6==a@SZ$^Pro$vk9Ck$6+~`;c zwvm>H!&qY}pbh!E09_H~Kdz?=%fc+JlTSbk=B)1?j3UI04n{a4{Ct#mIWJqFv80}% zDvO@1e24-y5asmwhJ968BZhr1PO)~S3R=`^RS4J0&~KnG#)vNMZWgWs?GaAS;;Ikv z#%%hom9&OzqW>5pU^?s}?d-x*^8P|LGcbxOt4n?26}Dyk-CVFBHQZ$mxjpg6p%!-Y zluKfx(Sp7<#Pa*5;NT{)(*8IBqu?WrvLm2RK}H*9?Jh1EiLgK!qfd$s%_lW-SGwb0b48Aw(XcJCzRsphF zmGAcY_*|PMG-Bqf(1p6*Za0Fb?e=_SU}B8ZDT*@&r-!(frRyYT&YzR&exmLsrX`cI(jnRWaX@_v;hOW44wm{;)EJZ zmNrHNQethP&|qqwSj0xujrH?hATBS?vyfHWo#T=URl5VU?QoWE*W1VE{f8gle|&g) zzGg`ekB^zUyIe@^QfCH*B9u{q&Wc;ZGhwK`8sj8UB@7GgJiG(?Wh55bE3Zzt_R-`S z6GNf|4tc@%C%2|hn?H^3x3K8AVSGk6A=nNm0H#R}wS&>6bu~2l931LI%|4W{zEJ~Z z6)j3%LVGNsCVcDl673MsS_h4Ck$V1FWf{=$U}ynr|FbP(7eCRs`PZe^} z`Y&s46sC+g4)m<)dLu}qsrd$mqPk^h^jq9(V-F6_1%YEX*f9S}<2gWbleqAL!sX&M zVBUHo3-$RaCu8OCEG^kmxpb(LMF-J$u?bd<4h>TOF8zo310Cjc8g%pT)%&l2rN-VckIposlY$K8IqHg7wC-Y%tIJ(FJaB!A z9)8+ZjgGN(136*YS3#qL_o7&(DaHtuHucg6SC!;mr_-5%eSdy<_b~H03XFI<$GhZq zKD93q!N*iiwi(`Aq^dG@o?@JV`wjbZ=Fa{3nwi8Hn`&y_rfVXUsr_^!a`)6DQI)!B zKfk)$e|~!U_;CN(39|(rCn*MYBDis@dCkiGG?=J4JzZ6tE@uY!ozlJv8iU#*f|}SP z2w~ras1vZ=_Q%ZoSNHE8pPxQ{eD&q$C^!zWv14<+LoqRgO4~#Gkv1unEr->B?lwNp z+g5$D@2_M0d^(Zh z<$V6lZ@&5J%U3V&FIC7xo?c92n#Ykv37KTrm6fP)Dw~{+lK~(`U>1yM{^DOQXl&h= z+ps8~0LdhRvAQHmDJi&dsC*`A`& zs+gY8Vc&f-*vdxCTME?5m5`?CJ|sN8I-}dCry61KJs;Fm9}QY32#KQ;&8$p76&*)N zNZLAZL0Fz--^En{bsC1XCd*q@$Ixs3SBH3GFxF+Mg#xTOWhDq%l_khUEe%ewRJ(sV z0cnWVWIr3?_HAlVtg=Z1<7(z8*2-hSusOf2<)mXb~S{F zpq9>b;8XLvB0BJ$2gR|3PPOu{I@Za)E&y^+*U{_XXy_hEdJyqCyF#(6;~%W115=yt z5TOm2Y}r^g;>RY5oTsAUXkF*U+OyKq{`Az;b9=7AK?km=ifGO*Ak!8lrF%827A?ch zWc3#4b!Fw97m$h3*{&Kol$Ea1#?o+cFi{b11I8dN zUm1%r_(aOu{Ad*f56GAzY>2WX#{gM$_C%jWUAg4K7(bAHD#seSc)X)TA9rd2S1f|L z7T4VRRO1{+npZ)-OwYVsHt)lHCF|6oL0koybb0VfogeKdBCW0P5p3qJ z32V;w49jvD1!iFOS`$szdG>Y#d-%myoc`+;6EI&KbYrtSTvNlY#r-)`H{i4uz) zhK%hnj$ly(^UReh7QTPPXvEKnd#&;X+>Fx#`*oaSTdLOn!^4>kWEUH@!=eC17ZL=N zWvRT#P%Nvs#h~b`{!=hdua){FCm`T3M9bUR>DtC~4pLucngnmNUF*q~8!*IVXH)rFRQjju)+r%mS{oP(gmMO3`$N=9A-nJF{6GifdbwFr|qQsCmxEG%G zS**KLyxniNQbau6_WgRr>0B@FRlo=oc$=>RgL!k_T&gjIoN?LWbjruu?Rvd`@gjn{ z?Uxt#ASSB7tjv9$wovgd;&O>#>`(J_9vFesMHt$5kr$3}yCL@=xs4v&GO6thJU%~j zI|;mO+lP z+q}*5WgDk}U0U>u(Wxa)lBzB~SzrbGE%Nc`jJ@{wd%Ee$tyX|KI(c+GqLJmL2wlRS zraQwpM~m#yIT0Lk>&6Zfwv>v*x5$IDJo1?B-u{Mm=hv#3GO1 zfesgPF0ec&-Il1bzXDNAjjogBQ9VTP&n;#8_MA&{X8lKZ7FH;vJu?I zc>3@N;&Ok{KDWCq*@e!Ml=)&C+v${5(|)AqtHwx;+f-G}>x{86I8L|>06LBBl9~Ig zFli44ZC7*5|6INfMiW%KbS>@JxJhiCK!N z5xvhrF~nkIVY4QEgpymIc(r5voDjy#`%4Jdthijp@U78Amv|-^p|vWI z&wGA+cz*NljVdbgIR|UF6Q(#eL9ccU0q!nn?`*Z^>gq$kY@;&C#=eBCI^_5K?ndz^9J8Q9m zFPldpt;}L$`|5wpB?${!?fW0=-fD>v)=kV~if@#i5Taa}>OJ94&hT zJDje0fj-`GAa=d5xCa%Z^7u_3+XhtW|ck*D{wi{%%v1%=#jzu!N8V+8n zVeJikQxXoAsXidxxE5VF@0-3~t+kEOat>>uMiQHtvotFUTQWjVS-E41A1n9g8>d(p zsSS0f+IG!rO~hW>_kE?^0N_cuMC_GguOe?%oVpv_E|+sm*Qm%T zYKDHkO?N`R`|!t>?Hf|s~E5iUuF5Gr<;Xyv<1k%H_t0+SOF_Wi(TlZ z1s8R8x~HjdUc3P(t!yl=;WFybS2i}V0w}yR0I8)kbm4pd|CDPf)fDK^n$QoUtVuPP zo=^ac4ze?&5Yg^ZSHi9Xyl3q|@s~%hj!GCdRj|T}i|aya_OEM8+f^OL$Y8d~W}#}*yOnz+}BRGmyv`t*TC@c92% z3_R1RdSN=a0ph+Ud1 z#tQ41-nMN7s)WSgsBJu{ChHNnMW>61xK-w+l=6A6h)hVS&@SaZAD*A9DrY`luY1*$ z9^QX&F=0MG--fOqp8oUy^EbcxPcQ%UyPxjIX{-JD!{ZhkUtR(@jd2b_%6(2DYd|$f z33Fzg7=aPoP6PXX30%&n5VJ6^xt(GLxt-#6)6>&=BeYB6HW+RineX3U?=E+78i;-& zt#fHJW!5IVoO|R=fgOCCx~4YpSLc&hkJot#o&d&1L<}(c@JMN#tTXpBxSfcJ`DRve zd-?K`;4Z`#jIG)+NYHfx>L@7FdH{oEEncXUy`UCc_{gAGKmGji;oiTdHb*ydJ*)=q;+=LQgDE9>V8#5&@u<0LMyPyL@XdS(gTJx zX;MmdeEu}d)kc;)t3gypGl9$!ll)*@+YdUSdyyKuWTvDIoX(k>W}Ui+%(u+!e( zN*(k@YiEJ>bof7;y!gHYx_xAj=V>aF9%cLsk#5DJY>LmL614FvhoE zemRS?FlQ!8nHB&|G zR0%s!h`beq%*3q9x=!VFzg{0_P9+|$*ALgHhq=$pHy_{Zr|VDOKWb-f+x20;yW7T# zlb+`mc|M;q_3`maW97mIo(ifNm$7jS28jK79b;fSi74fMo3RZsPTb;pd){Zfyd(#v zpxU_YPuGp{_eak$C{t-~Qn!g$BIZyv5m{!WgA`+4L7$Bl63HB1F>Dd*Yd{bHenVNfnhDWkqx6e9!6H6 zqX&$GGYl&%dYkZB*641LW&@k!qa6NlIGNpL2%l_gaanckDmhsk4!B`h;HK<>%M-Ct z)}=M&FU(6eoJQ2*Q2}TK)2SQHQuZ8YVZNgnqB>aLt9Ssx$Q9e>izKR1p7Mr6GK7l~TlNC#$Hrv=}&EcLohh;7oR`{Zdz8j9Kr)$HwlJM7| z+u)}T|7PQ34%}eHk*#f3galLmHmZvOw3Je@zFiIWFj6W+&~A*T`9b#*^tjdIxMz@P zjQ)V;P^us|S&z^z=vte^P+034otDubWua*_#R_(DP(MfwIksnM=wOAj=)J6wKVt%D zsA6Q00e2}#=?OO3?a&@#Y%0VEVEpy3zHa=szoULwFa^#@W+LnMEL^Lu&-r|-rK z|MdG0^H$IM{CK@0#`E>|e47vNAD^C|9{0IdQLY^7%%c%d>U7?^wuqIP+=gOQ=~th< z`sSOLAFdM-7u3VMkGelij>%0~6l04jDJnKxAD&L*6cH+$2}$oT3_&CD`CgmDG0C@8 z*InOU&N%7mHcyvxjd2^)7T0a;=WT8yPbZx(<1{Fq(9X}W!93!}y$XEs@{R*Ft77oP zmKfir?dK_D9r?GX<5dD<42)`B5 zJ-KRa?AfOy;~->txJ)f9s6((Hv=NB_D~c;b#Ri+6M3M^431Nb!EGCH+L+|NPl{Q57OsT^K4wi-1h17(nKKb325(t26K+vp z3QEKG+{_S}A>fQT~TMYLB=kskl5oGN3+h4u@;#aSJ{PE-1=X}0C-g3KaPJFcg zVg|*n_WiVt+il{e%js;$d~{GG0NkCo7sSikq^9L~Kkajy@cc-Vy zxWBLS1$Sqh&*OB)<&@_QW1MC?-M1}>F)@Dr|5Np6U6L$Gk|svPEUM-n5qHb2rn-7i z7|Z}?2AFdO{{sL29cawb-L>5<7I!yO6(+(1i~23(L!HdZ8yV(qsv^7)eN^(u=ck+8=yfBE|5G4`=PZwLvl z>XO6NE}_Ni2l_!o=gl?*5pEh*%g+F$J0ybm!vV86Cf9_#FQ}zJTqmB^n!!!7RFAB+ zAX=-?fB$zP*f}9^ABol1O1uN={#Ziy(JEZ4i-@IsB%%fWSf=5nCG2JARhO<2FxCfH zj;w_OAOc#9n6=)(A9=B@9?=>xq%Os#$e%zymr-y>S3-P2HKGJtJkAU5VOBV%L>Y*BDQ$`n@SXGK-!J`xfEmohLe zK>G*|YTLHkExBbxK1J@q+s26W+E$^PXm!92TsDl;Ak`yjYUNBfjx`LGP_vHXet*RA zAnNDW$G6|VJU@*Lw3TTwoK9yCfnE^yR zlr z=P^Hgdd_WdMAy`jOJ&xT>C)zSDU1U?n=GPb0_s8KlD@~Kk#;PE!TXST4g9^-m1`yu zYa)T3VtWmwSDg#@hv_Tn+Hbz^Z95RalAP}dhW<5moqu)My%YH(@oUMaA#@s4mxHT} z?-FgXb-eQH-_bifD4k}hFmR^e#cqPzF>Kj`KWKhsNNy`|9IwAna6(H z#?wHu?AFC{EQw`LPs)zuW@gQf@=WR^zZMa(f7~O&Wk>AWShjpt$Fmj?h=GWRvu7z@ zp;a;5b7m~PK^xaPp*|wI0$T#00A+po`u6$vZ}-Q&YDRG1vjHjbe#ny9UjFXlxs0mW z4s$Q{v6q!+4VWopv`6T@wdUF&0PSe$S7OQXx=?B$Ixna2IFPz-qtG1!bCE$UH2pP9 zt^c7bkyzIftHm&U?*%St+Lb-L8Un2BWE46QvA1Zg+3RN_{l21cHwa#9EnOaA%>DwG zx{FJfl*40>F&O(68?i;~v5h8R1ehzr;)E(f_SCeE z>d^Gl$8j8w$J@Qm^L*6TZ?AxblUs7R1c9>{WaJ3`-QRsu#$(m}?c+1}^rc_J^};)o*H(e8sO_J?G=eCTRI~&(s^=7Gy8pgq?0g?Dg>(&P8aUxzs`t^k zsx)5Xp;ef=cZ^G+q$|Cxdx!>61}`sA>si)qEnZE2|0lyvv#S&JO}sJ;xmvLG6*N8& zL?GXNvFIOu*`o=qL)48$2OF_C6u)LT( zq~C*4#cZhr-Mwb?V7A-J28+a6Be5alSfhNlp6%Ts9}9F_XNoSyel^1eYmq; zy``95!Jc)ULTC}RR=AW4&VTsvPg^7aNoFLGV*y>Rh!HTN zBQKJS%*>HttAokD9mm`KAo%6+`1$jS_$b}yc@R2RbWFi@)Onn5$NBB; z@i^yMn&-KVjHH22-#^cZx7Whd$9>%Iryl3i?fEVo1w6z8i_f!IMN)&m&iVDw78$oh z#@hN>3`DTc<({5eo(5*^Q&DE9#f?8p20wjxjv%Ls^wt>jhHRP{k_Q;0pLwqWrhB`| zi$TD$RSgA+po5M`P0Vg1FKkp{O^Y3PJLcyv_b;E{a*Ny3ZR1+uH3O%-V1w(CX{p?` zXJ3lVKlutaVor(3X>EDqhqlfCf#=JE4y|3UEb{xy^x_;!fqhDuvE1ll=_B|A0 ztShb0XkN0LCDUAm?i&0rqw7**aN&lQC~FzH;*#`4yA9L=oR#6cx-zbFr~jqEh3xMe z!K1xQ*Wnk}MsqEFmj-@)x!1s)*J`ApgmA2WrwPiP`QFD}=>02SLjRt&_b*w9LbYopFxPqC+K7&D&P&&OX&|`dXyLqoZM-N|S_u`G zOYQwK0@@E@H`cZP&fageWZ>$VuynO*{pSi;YQe+OJNTVXT0s8ohd)L4W6%ndUMmPo z9o-p1O&WA&$A>O97*I?)GIQtDBH%G-+=5R}H@XPko`$DzVr0&maZWPtN5!0DjPpLv z!+>ADzA5-}&Tp@$Bfh;n>a53{k9o+xKOQB&p01J}zP!FoZ6kN`Mt=DC;p?}%PL13< zKu(cFJh{O02>n+2a?ApPvF)RE2iZNN%%|z=5VOTHEpWrH4kAh*CaAlR3an02@g^vCM+=#kH_)b zub=O4kK5CbFkX(d2h68Bp&t`oLSVeqDdO?Ge&q==8?3 zg)diG#%n@l6M1>Ymi*mb6_&jI?yktRV4ot5OOdjCxh+>;=1l+*sOD=d<;Jz-W4_-I zYjr`U|5&gSix2ajW1yv3UBde{B|)b^FZS6VTAp5k$3jP5^nDZ-OSzZIE$P9@}jD&6_VC7iffJ4nDs@4>2ezZEveK(?p#XVK8Oo) zVqob30$hw{ta)nZKsLCxi-1+%FHhjwad3HRXw?<03HmaPwBBqDl-3;|5kMI}mz3|? zpta(lqgj`*Ibr1Ae*Eh;Jm8Z6lxT`_&TF_DEvzeUnGq`Vs;6Nv5e#fmLb%#xl+K;} z{^JJ+>zD~-#wkrO^#oGP8?QB!`I=gZ?U zb>8of*Xg@7ty#i!l86M{>+22v?#J(Qj43G~sgt_Z^>R?N&RKVzuXP-!vJ==f_vdYF z`F4N3zdg1@j8I~?_c|Y;-yUZ;Oq>8Cw|yURRWB+65rgVTCK@>92H)Ju!^LofPR8%k zMDBZX(8O7l+qjf@4965iC&~_Cfy*`{PVy3vW@Za`{#8ggx}r!YsAy5rbKJ^7IGjcqQWrJSUg7cAgMoq zMKSCm;>r-gRqn5xa>|#X zVl>J*t|=Fmj0avfV_%0wYbkKLty0Z`iC8hHP@Q+zF4Bg0|86nl+a9r%O)+z-0jp=TzH@@qVUTcns z7SeWd@B;sJ`Oq-CrAkmB*tk!Gitpa#OX0af9)0aN;I(wXT%)!{7Rrtma|gZz%?ho3 z4Qn~mV`+vnyyEMl+nrcwx#dsL5>Kr-oD0i;$>Xq6Wo*WBkmwo|_7fNiN35@;^DbB8 z61^7Ud)5QFawXO)wHmMMA;b!MxV~CC|KU%6cJxS=Hikt;SyXdt7D-gyl9lMluJS~J zxotuFSa#0=1iWwg{OQAK&toPcwjs$fw=BzW1`%q*+6kF85+w%*L8}6mW)4o#hHi{!L#=cxA0SIN~$S#*7u;>Uz z4BmjK)2IwQz%SFVKYn+EUG`}>MvH$6bS{!2ldjJDh_PFfGcz+Ae_5^Z82$RM zy=6lK+u!4^djuu}MFZJFZ=S02tU2r3*Vm69#)sz}8FHTr>e$0IOX(V<>)bwRL+riL zMImV@SSQ&oh4#wcW7p0bgtdyAc39B(~zVx2P z?DGikTiPYu4TLxqerLf=FI(kd{>(*XAU+l-(E0U}cpoJ1$qt zFCf_yi}$y)Hzh4Vx@IBOKXLD?`&Z_xA6i zTr8o^pnq3o^&d;EuxKyUkfZnV%XaL7RgsIow^TsyX%mY=zf4Vizi_GBd%8!~y9jYv znB=R=X$3ptO04gbzpwN~FI|4LycRQxR+ROMJOG#1{G*#K)vA$tiPF=aOU%=~&|11H zuIY?945R9OM)SuWOlwl#E9jOL*;=5i_5VqO)Lf6SyIokG>TKtH%iwWog5Rh5Yw@Lk zEp%Yb`i8aGCVk_sc^#>^HbX=&@)VbT%4E5X6h{8T4?m7f8Dz3LhN}OkJs5}t5aCK- zq##7AFhVeg(U$ZnSg~phZzJQj9p|ZXMl2RJ?KI_V6?Y4gBC3E!W-mv*Mqlt~(0gB7 zD?Z{%)_5Q5Ef$#Jwkl-w-LW1gbt6KW+JU|M=I_{`yu^Vn#UEHm}bLIrb5k3dTY@l1%tk%6X=_D^A4k zB_M9kTQMojvi4wx15B1K_QP_6vg`PBYH`>NT?qaWEqlED-o1^>U=wc^yqSRmkH%7kx;A(|oWjP>Aikyd)=%s;dn?zg4|AK7I%k{zbJ-uDI* zbhL42yL%0GmVUnL@iy1@Acaf(-A*s(8fBeG6i(A`uScvi6#n&ZXmy^J<%VmW*ZnS_9&S%&bQ1 z{n%R61vGf(;;1F$>ZFDB!K;0mt2&S`zJstrkC)8XCOf72qRn1M@w&#^x*=cv5)+6n zy5SCY!Zm?fYpUvqbsM4dIxg1z(3_~pi?P{5$XGq7WP`jJ3Z;3k3Rw%E&HYYf*MNQ4{41FntSziq&O@VjHb$?~W@fvy+M|zsrWrT|0Ge{?^gN{Fl%%GrB^c>e?gRn(G4;5gJaHW7bnTJPdw#gx zKH49j$A|y;m*Y`izaFQ6h!`W+v>TQLj4j_6NZpjRg#0Fq;|Mzgwei=(({cN_J0cLM z!ZtJ@z_XW_B13|ty2w}^Rv3(+ORHh6YRyc%7qvjhS{e{_e=T+T&~D_ zY5)HD<@aA+2Kn*Bb8M}ZT(0tWP^K?`?wTM(*BgDZu2!-CkoE4lY^BY$BIep-C0UT@ zT>Q%(-Sh{A+A8e+_wT9UxME^k3DGL@HQR5N@gFXiH4s|oq#?CLts2eiX1)GZOCf*luvapR*DzpRk{!9SI>!$GV_tse zg@9XmV4X9#G-it&iHJ7IV}(IB($8Etsix68t_j7Ocwg(=K8#u`qb^?2IM)8L?MvcM zV?zst`gY>w-D@rw~|NJpE3FS13oeF9g>{w`bB z0(AG2rDfP$s^LDGsw>(y+lAEVxd{F72G4e6EE-*RE>|#e2ePhBcr2k*^c9e3N!oP* z_3HUj3L=mJ=YRa+uMG73)AmRz9Za`25+QRWWJQG5hFD}^wCKgScEyZ5LqvVt#)t1d zJnko&uOde<3fTq#!$3U0&NU@XB50)?v8bD222*)iG&+P9$Oc#R_q#MM5q5N_>O~zv zB-cX(AV$WOJpu#Fln_?HNyt3Z8~d82vvABhS6nDbY+D*s#96*q&6>w~9P=@!4)Ja3 z+viu`=gTqAQ`?r>10yzIqd`ug;|G?Hp5&}HT5<~anc+xJ)bFz@^6BXoiLy`iK<1j+ zSa!-fq^V_WY8^KaW?g4%EW*LNDvpvH`l`#>5>hWH9g8D`RzEZT(9e&ICRz5}Wvae> zetEgSzCP}^{b}E`_Y6J9AskWogE|>kR~D_1?jeX4HmBeDj?L~jJPJlRddHVmwz9nU zgO_sl5`geMjhk4}NwHKRT|)OSqsPR)0t3~V=?i5S*URk{LSEM-r(ImFfPIfJOxjl* zjF%C!7k?3#CpF$jN39cSc)@ZLbQiJ~nZD4?B%*E5u@=6UhAKKgz6sya9q}4oy{Fu_;NbEB zcWsPlqs0oek6zC#p|G!CS64s1q2cI~zGqo}{|vT>g1dEHZ8Od6hwsYHTttueC$hJ> zv0AlmVVCoGEuz}_c)h0G74o{{!*;gyH3cviiPuJTg6e{)cAn=Y006Jw6&EWcS0j9V z0krA-hd=#|jOp3ZaVJmckQfmOgwp_6>A|*eSaOPklsaN~~O-R!YdwX!1p@ z^yXz8?AVY1;pEztRuA(^bGl@zBrng>AdG1on&+WA^xM6@J&wmQodc2EErY#*Z>|f` znL}L~sO^VDxC@?53Ok50emUhBPfxc#DI_zn#mKe5O#-uxKkJ>B3q*9BFO5WAvcAPL z=wmF_i@kJYz1$={G9zQHNL#q!C>deb3Tsq%h&tuwyoLy zwbNP}VS4G@TKvBB3PO_x)^r}G;&K@EJ}+YN%bS}@Tn+T{`-I_uWf=|cU6$KLW=qxz za9#W9YlOO{(p?*^b7%>h(3Y(=OAjlcMl`i{hz7HFn+p)UWI@!GJ)&TPa^3N0i^CGY zl1lc2+|A1SZ+!jXi|N^Gl(>fT$yM7$t{~cVCiCCv9=%FUV$FdG6IH$cMSG+@)~L+Q zV|M3Systt!t2THgpb61r!Gc_jx>S=(gG81(_!93kF!AC}T*_WStvM7gozz9EaP)w= zy%b=_XrkHIsA$iDfyIOFd%ii_{nh)LX0y6>;hIJDFLp6HyhKoa7B6TvSK4=Vjjlzh z(1phC^bJyFkda+iTvu7G>02++^?uI2-`JNR&h1X>FXp<8a4lT|VXsljyW%+dP78pd zSfB>nobuH_>*_5RQIu*=7+RHfQCY4wDcA}=^@Ny9wFyyb5wND}^{7DwLetn7NzQek z3fVtnYp<9baQ6Xgrncu)eQsyh05n_}G{|5!t9+#$A+-L~Qq@7B z&_fCW=d_iBTMnD)G zYs=c8@G#sKK(+D3t;y;sA)pd4IYxMmVpqsD2&qsDUEHfpRc~dBeWpsJ%goX7XUOc2 z?1<&1f3GFVGcqFi+vneZ`|?HdFTeeA+i!|}BtJdxV`CUGk|PGjPK+^>DI-@)kZmKe zs*kHs`#|3(=(Q+XeOea4CZUAkw8L6r@>;_CE84z)yz2yAtv@=*hj8n6FKZRAvHtoG zq)!r^>UC&@m!H11&ZFz003D2u8TiG)Kt&bfpEZ)sJ%0Zje z0-M&NcZjZ+7w$T7S70WxR+dR8Gxz0yhy^d|hq*KZoeHk?z}MRP^d`QU)!Fr6wz2?@ zUdlO_63g*N&(pv@X>eWd%yi;KIg)Yt6lz`sC6iG7Zcg zH!T35ETmiH7P$sy{Tx)En@e=M82xAnU67cn#R-WDbm{2#*-`75mK48#0H-Zi_3~s5 z6-gJCwXlo1)rG06&0fH_hP0NCx3d!1Er<)!qT{w>7eUSi@~G9Y5%~<;jYg%;Z*@W>^6h z37p}ryD_oskv(4M_>RdqFkwbAfhraaDtlLGF=_KI4LFfn4|abYJvTJNT0LWw3v34) z3`qnqPYK+DTXIg88#9x(-NsBh5~9!3NkjZV}_Q zMe=srkle>@j4d;I+*j)pmJz7lg5~1r^k_XV{Wic(BY?-6fi%mrley`_dntx%M%o_K z&QZ`34)m~l@t>ERGTt?rUR)d0s?E3}!+QbII&&slbMQXIboZZH`LAn%sp|Hqjhg*S z6d0>1guEJZ*RpF~yF~_LLWJI9Z(GE@I2~Au7+cwD6D>@HtR!b|xx2I|iG8NCEwVkI zvJmgs(xv2Llp3X-WdXBQ-tKJ%ufg8s7qe^8FmO;Z)TN)el8DJJeAWv6YJYTba~c@d;h>hA*0k&yOZU5mp;R-Cs&9P- zIDsxzwDOH>jqVzoL9jXrIF`IZr6u@5tJ}1^SxfeCZLgp(9CmaE=HsZx^xJuUe(CliMmHKs zp5_?t-HEgyrxgV|VPq}~o{iRW3)3^h?ga>Ae z$0ady)pj5bYUilp@Pch2+nCca%B{=jX0%#=<_KvHTyvAe?59B(F-Rp@&fYsQoayFd z1|SJ^_B?x<_Eck zvb5BEa6~Y9jXf7cSj+OIu7~^T+n8^&CoG)mm5vM7mIP#abceI5)Lw@<*1l>Dp?O`G zjG`_%pqR;CH%6?Gpok80s`rt1?=8!&US-ZDG^l2kW;{x)-kUi~_5}1z$Zx@n9!y2# zw%>B(*tYM#dwRM(=Ni+zi%4ztV!~_87;EfvEi$160#v=r)!_sgR4flkfU2eWv9lRv zvD)IEowc~!m%*$t^^1hL{9Jw9U-KGijcC-y21WxEnk)d@6qUXj6ahVgOkP$5*zyG4 z6J?#4t*7kuY0Ev9wW!~+s5L%d>$k9~AE1wrYx!mORmTN{URQS@0;pcJtFEaq8Yr;z zs9Mg75hK~VP8S?@{!z%iT3&|?>=XW`wo zaVZ-3KDF1o26x$=7FTqA?c!XIzpL-hH5gg)`5rEchSrR{b%SeBvl3}~1FKGP7Oeov z>cA_bg+>T!<({<$s)-3)Cwqls!7o+@f|}adj;`wA{B(ORuw2mLLb%-FPL@_D*prBL z0F(VCFZDG5quxzE;ROa>_V?8lQw0x(h0}H1t8+8X!%t89)0SVpyh`f^Ra(~A90yT! zObdEWMUjZ4NOuA&tDQf?hLu*V46PP)$<)-`7|1{jGE7Z) zFwy~+j7esA!+Lt6!@#L*=e26(s7WmWo*8PNMtJtqKt?%`$&~a5{a|brQkrs5dY8qM zCqQ8D&EZ^T{S{1#uJ6pWLUHx?B~MHgH&~lEaNDC8^Yr~O>o~^87#n7Zk3l#_j9G}u z+a4L3h1nyaf@VRAY~DZx9YJ{u%1nfxshY=BBooZ+7s7_BI1tRKGdk4?YJ~e57?csb z2%S}KAQ{%UF_)YkGs6R{ju?}#aXrjTSI_oKqgQcAx!P+qA_Se&`G-``RTT?~1h`-k zgLB@G*~s@_f8Cy+Z{L6S{Qbv|&--XUiDh>p46d3+3bHIJh)`psF411^p_igZe=H(8 zfoxUdtOd?!6s4PDPsgBROJ)OQ|>2jq~Ew zuCI-IYctlCwmOu#tpP$?zt%clRICID0Ku%Ks)fR+?!LsIQ`#6)MvLDQ=huXj5x1ge;cMD@-%B%!KDEmQ?V(CjHXq2*+{_EhZO zjA0ZUg$Omp2r?YSHO)q-6Rm3Xf6Fz13WF6&PJqeky*|{-akVP)DgoM0Lq!nFz}2eG zr6B6HTwUJ0HM?3f;PrA{x-C1@zUZK1fxBs#C8I~pB+Kl#s|9sfAxQmGTzG1)c(E4Q z1zP;yf7ObIY`etrc*>o?q~Kz8_rT7AdaKz&*sfTHtMRz6kK^S&ANTV(J*6!%2JYu$ zCyrBss>PvY5cv;(`g2K-096@Lkq1@4774Zk2FZwwDRm@DZirNu$1BMI8JCQVh!1;y z|I>G`_em)d$8pbKWFE(~$lM=CjltN*+i{E}nfLQRbT+`uxZy-(_Nrs-VU$4^bKj=C zRAnPNB-cg+0&8pA6&|+i`%=XSj}hf6K*G30c+FhRH7)Xr$Vdu7J5tOn(LDsS)zK?$ z*$p*T-j3dC*8*z!14M@a%WVnl{iOpdWrWhjBCqed0zBEOt0;OTkGEkHEuG52&U z7Xl-kjOg_DMDhX!FNkjd0m!-96?Og+uQl|<^KBiHV?%ZV_R5ob;vqa z7%#&Dv;CbN>!H_G8JS zmNF85NcRJ1eBD}ezyG5x5$XlR1!^|`{|sFF|Ofoswts-6TB=K0&fYvEpA2qI7 zQ=dzH=`WyYt7XwRzpxetV`+-m7FX0C)~&U3UQ_uF2J2sd*K#*j_U8K-u|rycWmRgu zG`Z4wdqY=b=Yln0us>SI?qZ=Uyh0*k*+AB-ex;@KW<wE z!q{S2Wm-Q`1%hKR2Dhq~Lwe35Z$1xpJ)YJ36d3$}F#B}wENARoy z0cFfp`8#H8X;}~v&Z}{xBP0S!w<&WZCo6`>q{aK=tg0B187H8^lk4ysbKh^7Bb*gf zDo4#i9gZF9=?fDaoPEmJr(+f}8GCkWE;sv-g(i&zf{v0DTBM0s+RN(2M$o9iTvkl8 zu;zu0_mFc+dqSC%Jym5#B-f_U@GxaYH03AO!)(b2=A62;R^GOdJ?AAJuN7y~8XLhO zD5};v5V675%j^B+?R@(3`j}JE&d*=(6JUwu%m0EorYNjk>dg+(n?{eS*}PWzoXd<$H*> zOC(sW(f>mxiZEs`JHS;!!HQ0~%r)qVrL1gMYziJLIKrQiH{1IHr z&LVC5aHnX4lqXCkY)X!FYwg-RrdG3idB2u73vl%iroqyqJG++b$}1YqEr$V+?bp$~ zcmXZXxzq(ctuTq%2JJ$_XWzHS)S_y4(_tVZ&ZCY(S@*}|{x(aC)xH#}b{Q6KPvg@k z9`_k!aPG;f7|ed9%cP{X={F?@w_$kN1Il0(_e=~)c7;4kQLX%{wq1D!V9x3De*W-r z&#`Y~`|%^HD#(ba@QD2GyASOH8VR`MtgVZkI2k%;J~8Qt>(|NmE#gdz$BLs!AM7NT5c3M%c-P#t=31^Qw=Ta^ZAg0=PjJZ^F z6fo&=74ThXl^7iDr0uGii3O{lq%2Y6f+{Fw=kLCIzTLLSOTLI)#!*Ao5|eUiC+9^zZfrty9Y}>+0b*MMQj{)9NN~0`s#?}9bk9oUAVL46y9jNJoW3MrblmD&Fr4T*nK!&RKuH?GATc&*t+pgPm(vfKB^@@N- z*mE@m>;@%o0@ih-uiEti8WAFE)&;p3Ojb_Ew+>nLLonyg81Qb}$J zX(w_-4oq<8Z3i4t={+Fk%W}YSAS230pH@rsPaq%6qAwGiH4CGk;JkriT-?ljIr_T zr(ZdkWHPo$(A(Y@yG+8HJn5=(v1;{N?-PZ%c#EUDPrQmkkex9tdQJmVdoVJI$Nljl zKYh5x&NE;iH=SP0n>k&>W3z$TYLpe)i%V-RB{N&&Wd$wGP%PcDnZXFmGEnh{XJtj} z*=%}F%hcJM)2fE9UoIG4RGRmFsFt%O=~@vQgL&2^a0cqsT%cyUT%jiuCrKXeAyZKv z!$_174J193br`4iM>dy7_ z3!PoiU3zv>K;w)%{ua?21fWMp9SGi<%tpK{vCO-$slUssCc#Cwb434TO6nm_4UikhYwGWmtzD!eR?|P`7i(W+t2^<@(=&;(+@vD#v+zOM6NudFre8qJ1--CfQ51;qP2u9G8}R( zYD`aKTXJhxhpB|CMHmSe&YDbTG~!|1*$mdQqIE}?UA1>-(Qk|vz2<$H4nXCOFtcpI zkH?hs)RW$I@gyiPWKz?SU>t=~AvI!L`r{Jx_IkX%oM%hn7WJb)2UHq;{Iv+x%p8E~ z)G~v|g47BaA2T)5L7dNpf&Nwge#d-ymf7bPU7RW&=w z4XQ0Nt=;qhs3(M|!`hhrl@OZ8ofAx+_Uo)}=78Z_hQjjoikToL}#Ww3OhRbwHyUMrgyQ zePdAGGDePOou*yDtj7E~HZ;Mfb3bcFZvX~Ey%${61D7g+Ni^rMTh#V(_i(rKCfvdj z8!1moF`m-3)Ot3InJafHB+0DVSAz&<^fbniAxjz{0z6N6mKiEQB{{DyCzU?EQpPr=lI;bo4=p}w9)%As1 zu5j<_8#KTbtlYY#Ygwxz!>WjdsEBm0AJ9s_p0Ta?F7YCF5H0>Rqy*ZMblH^IxPyXE z>-FV+d)n@^p7$+B%&S=GvZ7111z%pPWi9U;V=hLiEFX_Lk26Q?W7O1Pm3&Nni1>KR zgZ1n0cXIS#EVpeR1DNOeu=w_RzC8@!_7piXY00y69+MtzfqEB15JoNk;x^*84cT!b zXl9(#b#y{OshvLt|6l))|K+V}+Xor1=W*0Y!DnUUwyikUDZ#NX?0KExLvwgkxU4ui z5Mp+O(iZvs_fPwG&-=dJZnw9i?vJ|d8v$4!ZW)7*@($*}>v8Oer)^VGr}lkh#-Vwf zrf_@800%j(`=R^WobxagEmx3F={#LEQ8Ji8hE5vQiyLN;onHwRkOd6ZQZSp0A)K0C z0s^YHc@7XGK{LjPs7eGRxG*l;p4$&8Y1ZV8fA8gwXIvw?^p(>zdM4sw6G zZIO_bh>=_7wr$(ka%0dD`?hUu18y92Eb|9zKom_B;Tg*fZ)Pi}q3qO=j(7>8ZKt?sJ8keThocu7%C){< z;HPT+MS4+R7xtJ$6`7rEu0W{CZcPq3RsZ&{zn-N({pF``-(G+Dw=b{v$J_m}+!4vD z%7z@3Gh#%ZrIk40YGMhYy9!Pf;Ci|RGi=S0krvV%!Tl+3xA7nT{%?`|{M+l_{oRjG zPg^jvyd?JO1~&#NXab{WK1%>g*gcpf7q75EdetUcgDep;omc=U&xy$OftLr5S6%}{ z5*HW}Dgtc+u)ch|zr36XY}+```tuK;#-3GH9Rwfe9683us`jS)c1x&nO+g9PIepFo zoWS!wj#J3^c0Xv`j{@8g>6t$45Vd*^Q>=9IJ zXF;vBS!YW-88So4fXr&RG%kwM)R;Nnri?wGZ?Ch?xBH%a)O>Pn9A?mU%S3>vPz1mV zVRJI1P>Ll_uo1dI3K`+d$VlV}9 z6N)XK#@=toKDHzts%h6bKiqC_-_EzkTY@%Tj~O(kEf+aUZOpF-mXCjQ6C4O9jGKhJ-@PgCVF%b(b)w z`ySd&>Tfq~tL>Bvp)u@)XE?UJzs>*c|M=(MfB9Nd|NDRb84-1qAlNPO8tc1k zOHm624&s`6g;gg`6qre{azg?cwC1d(8>(xg z*aK|O6s)Tw^{e|Oo1D7 z^jt5{J^(?+A>o|k*4dpd&2(S;{re!$-suYXs5xHm_t>7N#q)&ybi2hoaocX>wzzwh zNP|Tb*W$~XkMfq;u)CFRCVS@0!X$h;=@mo;G!kbnonwI}o`S#b<8uv}J4~KAC5ol2EWY51m!k z5i?FfAqA(|_ky8uo}>E2;4L^^4kiY{lX$?hqX8}5r-DF?jyxValVcl+LD!t8rrMWL z7rc^7VeXPnQJd-fc0ZYZLfrPjos&8->6oUg!;uOegFOM|bhVXS)lxoo&?KA@jO>FY zRn?(+n%EOf3kfn3m>5l5Ilah>W-m!D^bImFoAH}C(e&0}qf{cQfmDQ1GpK2FfVdcp z8HyFzK}I?uX0={q(#goE0>h<-CbgR*E{d4YoaSoLcBoff@K}=#wy&%U!j?Vuz@_Hg zMnkqF{rd9%`A@%m_^|)@)6@O!al9R#MY33eRhK4@k}+~@5o3&CY-5Yev1K$?DcW5> zmMTIKBQmpFlsV@ulVi~B;&0JBN*p#_;vyvWSr&FlzyM@(F6mGYklI*ekiUO^h56(6 zx7hgd?f&yGUtV92-+q1R7{dE`0%K2Zq5A_OwoY@Ss=VlKlvH6NGPbp$a<^;_#_1%D zqsmomv^xN3xzDuZN;-nyeSG@c-+uhzr%%u02>|J-I`7A}Z)L)f zgXvo6W}@i4EX~#6UW;72<(5Y@_HyQea#@|h?QbJnM)+ep3~)t7`$ZqAK4wysp7T#xfOMU>Bb z?R##-Sb5HVl*2_Zwk^Uk>r|QJ`=9?DQC{hx&p`ecE2-g>_39G&Wyo`ny$0CSb_jE8X^u93;~bsKHq$?&o}*=Q({$ ztE_EIs1$R^rH(>q#rxi+Dfy8xEk!VVgyy8mrz=X2^NxtjVva2%Ge-pN*>Az1!%=J; zA&saKz|1m!nU2s;VUS1gzx?((Mg;kRX-AqEm_-&Hn00nuN&=J%-RiO9Ri}$FEJk2r ztrh1a92|BR@YhZ`83fM$OdV_&F`lw98#FkO5bDa{CJ_bR6(v>_vZN_*?5$Jp z7FziNS9DxrW$O!_9du&PPS{m4KvpaOB({x+Y~Ee_2-6sYNzdTKl5RJfQ;c@5aSzdn z3wziYcm%?QV-VZkON;vX=ilCrd7gn_6@L2R`Okm)_`~;~K0Q6HCCB2J8C4{%X-0kd za{u|Ce{~(_QNRA%H;XAKTnky#{CZpZNvWHhMOR)f z46f}rRu0x#%SP*ql_nxekdOPUw|l)k<{qx8Z=i^?rp0m?&e930V}6k+J>9tNS+j(0 zUb}&I51(%7NRH&=aesc=ZGL{MGCw_yi1GTEL40`HX3g`V3**DmM8FfV1~{tFWBL|j z8#qtq+Hdw&qZ-%Z(sAgwc^?_G7RDV$mG|^x&bB&~N@_-YNNp6(E%K~d=_tLh?!+*u z2g>8=(?^ph&B5E20}(l>vy#VI+c*3$#`m`k8;-|3X`m)i!CgV2Org?U-<5>z#;2#- zPd_}z7GoQo%CZHO5^$fzwqn^ML%?|o91#?1PRe*n<`~@oy2=AaU@(zWm`8oOMGQRb zFk*UAR=6@p#wHV|Jz{7&vzjjO@k1ig!iTt7emi_T&MMtY_c=8c9H-&5jyN5~db73> zNseSN%G^ghw}}OK;CAT5lo@9ggdSH6aN7bIAH=dwxgap6={`hDp<7l9Je!yqEdjNd6(A?;ICa77W4_&k-+Hbc8Dop5+rH;E#>j1u@$})- z7U?--BgnVMA$i+|?Wd8gm5;#v{x-$u+jzX(zx@8PKc`SX|MIOg#{i%yvmP*^pJ5*6fuag7SJi8%7fgu@#Bx*-#*+L|35qmEPKlacjD=`jf{a9nH@S7 zEstVCj*QIaYY4(N#ymt2;j`2eb{8OS(IQU1mG7sMylp{Z_Li8D1lh~_aJtzF!yI}W5hPl>!2!4pu)*qpy6~RBI1_YzKzTPTW(=6EgZz8 ztctPkTP8UhXqi1CXgh#mMU032SU6P)z9pWp4~HC zh+){)ECAu$w#W@5*x;a+<+cj)^0I@8DV!724V-}_$a7I15fOn9eNIVHMz*nm)fA9s ze!;M6%E#1MO*`#;t~gJdaU3|$W2{Th?Nac!Yq@~xQ)|p%<5A1_uUmdEyv>9 zv3LrzDj9or+=Xe^tmFQ8dwsjVy?y=q`updX$9bHZ=b;bJw{z;Z&##YTzMb{@c1E%c zTmSm6zx|j0{QESR_~qv>x99!a{r>s)7oZrLfaF6u0alww@;qyhkqoP(!v#1kG>x2q z0~r>Ho&s4DBblA+0Zz$h1)*J<)$tBm~~9MWyIzdxkW>U74$^|B%B?W zTg_1q2>$;0X^fa!$dtHXsX4qfW;TgI*s2MSb4F|iCM1{Ngp&^5?I+J$C=oXXsZ$(| zkb@z(>8cIh20#i}q$h&df2Z`(|4#+Dh6 zqaJrXs;aa_)YzJ5dz20@VoH(;Bpg5{V_-{I!^Tml>h#5M_^djoo^pG7qT#cqCyS8- z>1ZKL6Hp-x#`C`2_MDPskw@r>Gl@DQN7%ZJtl)94Tg21OGISzGEQDGjwwNO11h^*= z=UIkPV&q7S97nAz`&somPu$N>&$rtaqGn;ZZ8r{TL=;hzCJHA2h|cz7>YYxxHBrCg z*~$|Q#5JlKc?ZSF=6kw?nvMa73B`nrl0$5S*b?A0!9Gz{6_#{7Fst^Be%eTlXu}W* z1tFnh(V{2g5!+@O6PTs>CIrtady=3>@8=EVZdAd+ihui;-|zPaRP$_*EuL<a1>J2w)#p_&8@Elb)x+_=8|T93>RCjJ&}2xnV$zWg*_S z_nczM9ZY=BaJp8h^F# zInNo1+tc>>^Zn)9TWsUo=eOC27$ZZz(+nwYpYB!XQ2gDWe%iL(<*~*0pFVthdAyyc zOqCn-48enfGW^rW+kNI)bm+sDBjWWqKELYY)954vl22os9VL6EGd)h7a!s6t2xo8~ znf9zkL)PXPBTYTdvpQR<2WOj!9xvvi!g?W1#G&eKiAheM1#SgPZ26k;bFgWf*nN8a8ZkC(@+!?1S7 zlSjGAb56~(9r6ZG#s(@n(S*1KCvX6VU8OA~jN>d;johAZH|;*&idBnQw^D!z_%`x+ zPiIVmBIOUsJ@6#Pbz$uqfa zTb4_XIsJG{m@#6E#O3{heTrs7`d9Axa>>IRS#a4ImR09M`UQJzZX%{|&e?OII9(XNsv%dVJ>oe!u^e%0~(JW>EkBSD_$IcEnp%rIlHRL4Xz zADWNjM0GZOJ2}y+rin;s5F_I@;`zBdz=QC%rBz+rpXHjGv6h-qQo`nn=osCjG)TuC z3p7`14`pjsY%!W0<7k62VhMP*%yI{@I0oANV0EG>7A}D<8}<|>Z`m@8d4KuxFOS!K z8zY~dZ~MomwBz;EJm=T1_qVsZ$zZ{RZvoYiqP*Khf&y84q-qE{4oU^Na0>M&c zEWcS^@|rr^ODA+VI>{9z?-l@Z4HH@Jy={dlaJZ8#!0hXnsviAP}}T^sm3(o}ZqdpFYL*<=dBe5Q&m+d$#IG6Q?*GUu)*Z@AtvqFl$J8+qHp5vOrZ zMbOpcYX+jgQ*xoI1HZV#-)|!`ytd>{AY6&gFAI#ASHNl{ANShFws*MW>{%X2#x_O{ z!?SF08$$tsks-UL1Bk%J4(avO$*ED?85_f=W?5pKh|+pBA5LKtk{At|T={S4mUYe< z8*@uArb*kGr+sDAuLvM+tnx9@wy83$`tV@~HRl}Rm-7Iy$JlRMdo`+#eajfxwkItR zeH@y7m39(bt1==uOXqAedq-WxT1h~fJ_~RsEr;b1oQqeo)}+lGF2>oZG0h`X7${fA zb+mi}&600uMX;^4Y_{tHG6F;f`^iKwGq&L%Bp>AxJS{=(zYfeMCPb=+&7s9JmF!ASDxtw+RBY6-*RFwH$1RLm>oueqda4G$~G$Z+5I zJ%FluJkI-he|^0_9>-Br_P1|upTB%L=Hu}=A*yQ5qfpHruq+qNl2kp{ajOYHR%Ok| zSf;8D5$X-lwk4YdPDUyl?ZO~b<;+`?_htvq7)fl6;bC(nfs836oLn$JcY@%8UPneN zn=9dnJ#*fMU`dFn+FW>!#zkd4h(^k-N&T0ZaJ&H#avXja(kTI&)-OBO? ze%xb#LoJqz75h_Rik?K!4QW{E&kJ8*pR<-0gY;y|j>WGD7ebF&`^H0(;uHoD;z(wW zzN8KbrF4t`=8m{+V~`k8RT-G&GR8yBxc8g zi}UqlD)!s9LvOQZqoL@`lZV9n!869lN!}54%tWaC_Bf`csmcB8DLfv}QG3QD%wYL` ze_*f#aWNu5XhJxbn+vh!#YD^|)ptUs(?O>ura_4tPna6Fj;Sytx%16T+ZrvxQzoO- zX@gUSBAC_3mfCM}1!Seu2|=0wA2chrEtmk^#7vTdNclKz^q$F0Kd?1{;XJ3Bz*Pex zEd@MC2j6}Lh!U#Mj1Icx=_sp$Z2E`)?lnf zz|KfOH*DKwYD z>$f=LWb?bLG#XTRpdyt0j{`9fVQ&YF+{ZxH>)A8y*|Mc;1KaDxP zjVR+k|Kj8295I^rcQ)3Fm{KslzP#Os@8>H={P5}dJY5qb*ih*4wB2Ik)1H};uF_B> zDIbrTqMhQ0jbMpmaLL<+bYo+~j+0DR25Z(lCu3X6WECHffsB9?t zS?Vm1n23$D(=Sw25Sh)QBH+nrWtbH}U|w1S|JSvZ##h=MY`yS*aq9`xNV%%7}#Nl&qg>-Gs!`f2%q$nG#w)> zkfBBRY|6DsVvy48fC#WuDtNL`uewhth|Qc0o%G5s1}S(2I4;(F5Pt7YOIG)9(mWmH zDV7nG7MH95>>~lotpUPvQrc5q9YUv`boME;sOWWN$CBovTW65wxH8P^oS~RXr!ke8 zysbE!V>(n3=0K8%i&QdEYNSIsnq>(gfPZO)o?Ntq$T z((9}Uej`iu@}fQPagUJ{aMsNK=l}SB-N%-W%xo(7Az9wIK|UY%=j8JMqw{?k%!hn; zyPUG9CT|Br9*lT?8n@>yb7O2%+9UQc0F4L(C5&Wjo(Bg9lIKxL?prVt5FE&3w_4a6#p%nT|y%Y(6HJRYLQ?G{F5jOvIVV$RM1<{m4n8fM7*Hcp+8 zw`~KkEv{^2L!wBAix^}3RIwx8sBbl81DS(GJ`@jxSPxhc55;3e`_R-Nk(~o++o&87 zBLFpLyy-D?MkEqpAu_iS=bR5n;8~y;1M^Y07~392mMv@LbvDOhHcY%F5v11(*T{oK z308+43K(3X6jU!8;b1Oli*+8B2f(RD&Irt{y@@NMnj+cef}q0@jEE79r(|%&oFjPA zDY2-&AQ>Ywf*G-m@pv5HULRk+d^?WwcpUTfaGk%uygeSrJPud6$Q2L9r>AYs0+Nm@ z&l6;xf~6{wx$QAFZd*ohMHLGTPv{$P<$nPNW)+nqE@E(4U{in}Q{mWxlhsq*COrbE zN6o1wYH)VUVCNiz6P{(LP(eJ6ZOfEvp0h_tBiP~blrq}++$gmK{{R4h07*naRC*?N zqDqRa3dY9ZO7KKSDMkA_)rMbZIJ9OhhgwE}TJv1TLdY$4yp0I<_0^Qw9LdX3)%@dG zDn%jBs_I;Fu$A(o5gk!7GB}8N&cFWf{hz-7@a^r8)oB$5Ms|ESuF(^VYwz3<;*Ge6 zz$USY)kEzJxjE%a|EubNI0I1?Wo)At<4)&326>q*GJ@=rY8wGWN3TSu6SFz8(Hz1C zq&A&Dz!ALP>zwm^%-65qUS3}Bk16+v9AQ?WY|~}eDNU;}>s}$;HMQ^Y>ErFgKI~b> zoDjr}gaNw&#iwb|l82?)Q4T zKM!vMP3?3^o@bvNHvwJbhoqWMBevk%+k@5FVil)q&gNo!*5h%$KF*hym&fbe z_tCqyvoue0MT3IbCn2}7rd|d{hJ-n1wXLAl?PZ>1&?WYCdp(1u5M~dUN$y+1I$Tq( z!g;#di%d-Ol#f}N{RlVPl7nq?=9Hp3bGuN*6C0T3=qg-mAv_QXK4zVT8}O0bsgc~k zy^x4O+#+twThx|gWR&X(`5Ym6Pr^Q`=0mb4%G0i1!1SO!7Ra@KYp#JYqKo-n9bKW3 z>J&m(iwJ?IJ>QAwxWZ%*5g7)~S%3f2_y6Pn?LYj#|JQ%X+`5BjcpyqX7q%IF+ilDM z8k1WtH98OgazKs0kOJu`jYj2@RmJcWXpQI~A7LTC2$x_Y(g`HPj>h72Bt!G0uhf@7 zA~bktqL4W-L9L5@HXQ!3T$&u6z((JQyihZUI{V+4Q|GNHEABn8%FbE`$(PaFjm z`HmjAoH_kG2N{7md9Nw?lpcjCj#7wDn}dUis@Qt+Iy(%-C2Q-DMoldUznOtP!_e}t zHU1b)_M$z55(gpbsB_76o_{~Bf_>?$QW(k3T5TfvFyZJ@0pN+2rk zpO{P?lh5RbZ9GEKM6H}|K%KOm;K=A$gw5j?IZJ01i3Z~IFflqFBQuEAgF)h`Hr!fM@ zQBOH?PYwfdKZ=23?1S6h>4<%c7aBV=V`P(t@U-EO-|jU6-W=iY_O#o981u z#R4MZZah{5(K5V5@7NGUSMn~+4x9@|_?h_$8G&;atRwhm8P;Q(iH|sMsy%01JVTbOm{x{q4DPXM)+4)T3yh5$q64kcwucFYjxvsVpn4=dPu;e$US2Yi z4>irV^MLEXY|fp8+cv)2Hi5C(2+3P8&5|2T4Ma<+_UFOCWI`fho+_yg^S7qXHgkxafG`8`I6HA`aqxNx z(&7YRrQqd=#)zOtG8Y%a?&=zIhN0ok>4Cx7O};6bnn?=4ECu3nHg$aDPo^kgtI zLY}f1Pvq@GzTNMoK(YcW$S+G?WXRhsZ{#@DgW0Lg?maI`dH$uNd% zx*ph{2uCc)SG?48<|}YOn@QqEQ^ihp2To{kV*pc|;(1T6EweicX$0=m3!i;Tr^gs? zk2BP2SJ830BEvdtjBN|sE|ljQZ#X>8WsGk2lMYo)+>)Fs`$T*@>jv*1J9&=JPg{jH z$2^UZMTMOi(yRuJg*ez{$%hf3M}$yLJ{~?FCo?|oV{2YHJqB_{(zlEt_Hwz5RBIa= z%_HvSK4Lhs9Imh8n~)Jgh#KaT@SJ);V&@&BtXbN|IAJ?um{Da-abUk?W4(MrQg?_I z5k%Bn>7r(IR7E7Kwd19;yk&08k{xI_(M}9Q@`(k$n(BD#7_k=3oR}&h6Y1boUBT2U zqt92aFqjCAD94}^gONQfCK>{oFf%kQJCbsRnU24H|LNPe`#es|PmlBOZkztgFP}c& zKS7wzcI+^4>NWZQh1IirvM_s$lk@-`?i`wx8y4$?NVp1TSkZ9@6`71Ms?VlFrDA{~ z3#Cw%BVz1v%iJ>@wif4&OP3QF9%ID}Hay5xGd5ciO)IAv@!aaM)+`!8SXc>Fhi`RV&l zx6fZ+`$9cS^RQRK6&MXC37gY!6RpcH(-LeUmS#5wBx#BfDu_}~5Wc*LF{-<01+rPZUIpNZyw)j%?=dwjmti0wG>I3DA>c#im= z|L_0EQBPx=kB9%@9rbEi=fO^%G#$biu@&-4rHRge;FZ;AZf+&mUd16I_M&zP=vpJy+?fh z{r9hD;rY`CGH1uM0t(`+{&sW_y^ac2;n8_53!bXZ58$EW^W&^)jYKZ=H#&2+WA6IW zg>VaQ8_(id5#Sh@6CKaF_7BU$OQFvD$=LSDx8w2p%RQ6FM4NE6LNraIgX#`=&s&a)e>=ZvZ}!pEnqv%Z9cT@+WoQ~lR8fkKn z<-=zB)@!jTj|gJGlNckq=0@7VLrqy}flN8Z-@oa9`T8aQ`M>`6AD{o5|KUIU*Z=jO zzrEh)qcBrBCn#!4nvn7TW9q+pZQHUeJ*>6f$Cz_2v+eQM`-sShbdk0)vzS@F$SMg$ zk)XCY*# z$f5$##-UR&ubs5VVC1B=_>c)3i%0ObIE>G3TiZ&sb8|NR*S1JM_qDpvBBk}M-x8i*!!7{dT zHFI(iHz+`HSXhLzeX=9FnK%KdZlO%6*@sZt9JA4@7$t%s+JaJtM<)@E_A`WMXavn% z)U7xonLxrCl8A>4MYtjbw%c8TR(QA{ogDku5tSC`a2Js#A|?@ZX4RyrngJ$B6tNl> zF4%1MZZ3jD>Bz+uRF9xAy5MZ)q%*QW5=*;_MNop_nL3jZoR#No;5_m39%57*}Twa z=Tv;4F1ohy7jZYo?QFM`NwXV@I$b3+BDqwFsHSMHY4Pe|%nA{ts6+VPI#0~4P#Rbp zMN&1)4udpdH3E}WPZA+t12lu-O6^1oXFq5|!Vdymj}So7epVsk+U{q8Hi<Fbw8kgfv$InFIz#HE%)NE(Ih?i7rW22EDZe-~o|pK|;vBOT|nfS)$ZN zY4F|7Lo8Dn3P{pWMN)wxr4VOpUWcN@fdQO~hql!+2=*eWr@7aN$-)}u&)u5pO%*lF zBZ(xD>NO4-!a#%qu$Hi5K#cB=Ott4Xf93D|#rqFWzWDOhyZ2AtdiR4#@Q?rbAEd0c z!qD)!W&tIX;!=aOdhi$_-0R{09PUo30V}od)f*9$thN0*+dR14x1yP}ciQzVB&1S;D29yq+P6(LeX7;QNKgE=F-CR#ubEoV$tm-DFI z5YTE}n?pr5IQ>&L~6WeOu_i5-==n-_M z7ep|iFbjd3ORK9glCp|KNHrIFqJ)t}5I)t4KuVNml|rcKT;p;yb9A7Fs>Mj#S+qcT zGuw7bm85{Qa$}}tL5;z29CnSidJ`2rK`4AooGMAAKtKyaB66U3KTZcNfz?(j|dThZsF<)O%v>m!4svL9=I0hga!6Aj3(>JUq89r0Hd;mMAT>{ zbPtGZ!uDdGbV8je5!7IWdC-aCK2~F>1rEd_9)1xb5(0PknYBIol|YzDQU(mdEXZW0 zBcpH$D3e==l9ajBW(ac+qp6B} zBVUA&qgOZf0;U#Ptfjb8oz~?P4vQEA9&YYt>@-t7B?>{+PDI6<>+}%FP1PI>kzj?Z zsOAIeqZz$5GL>+jM{95+Loiev6%;@f6>NXY8~=&4Fd$&ss>K$jB&Z~3ukXM2@TY$6 z!_D>P&e{4`e&wT!+ndK z`+8_fE<`gc1`$!=U7wGShNN__)3o=w=yJ%NM6+X~MyoiX%OWn;uP~h9C z-i$WR-V2jxEztlctwt%rHVVs16|W967>FQCkU@pTAvoT=Np|qSu~fgD98dxU^a^dw zoq!6OC`rg#D-ZS!nnxmBMWX4Zqz&ODsRlfUNlJ_`@V3mAQQ-JV1fME0C3_T#KfS<<139crztFyY|3AUi>m{tZcMHC3jB3Yq6{Ea>saB79ZALCnDtZDkRFlxhT3o3N?{1BHPu z2^G0uF`0Mb5pn0_v#~t6nvN2~n4pwd(E{cSky;NSg%&zK$Q((A@8_a(1*2MYi3f^! zogoZYi2EVRCkIq8oB0xbVp2vB!9s`Cc5vg@M$L$p#E8^9?hP8@t{^+r=2CGR=k_>< zc}=+mDd5&f^-TkUs8BMr>D;^+M9_7b5;b5F9#KoBKqvyyK=Ihxj1aF(N=m4vtW*S; zAl6t5vsu^F!cJr3kBKYj3ZN5D&5=dA*V&N{jSX0%&4x5@j?+y7jR&rh!NAww1&7c( zp#vdc0vmQ5&XBBH#`4|Y`02B^PM$rz*i7}G{L4T7>gA;Xs8L(bG9*IGtO8-k!Yty| z8EEKu4O2Z_ecF~ksW#bpqesrQ6~3quDkP)j-xC3mE@_uhy+Ong5v7$NL*PUbriMO> z>XB3>g&EyR6C_x;9FE^O6#US97;T{-77j)}pfaq@=&krT*8V8lG}U?TJ03p3}cN1y0nZ0i@8aqB5_DH5=!Fg9RKnZc0^Upj zOa#K%I`hr_>$N~;_Y7ufL`gW&xc2QbSDfMsNRtn=LOn&?gW)8jkyIssmQ(rjZFA#D zsy2XbL|9Y<)e{he61^s+n)sbkKAOwXQc5l7Zyo={U;Kst_W$w^x0hF^y<{^D(P}Da z*W765pI2y?dBPO}Fzk|KrI)~>F8*lfc9L=B6XNs#hk5S5a8n;Z#*kXGer z7N&!9h7nGO@u1gfgJ<#NZb=Z1sR@x=JJcx@NggyI&AgPuAS;9=qBQb>QH7!ohKHI( zZJTvSN7aNng-e+Geu^y7Y3kV+dI3h%7662WiHKQ{2ZBFZ2qr)=0#1Qqt_D{CE^v!E zBDLcV0&Te=B8<|KQwY^Sgean|@f4_SC;`H?=yI z+l@~f|HfPAC-;ti^UuC${UeL0Az@7;&|2>l4KPxG&c=^Ps_nIOV1WG3lXNu;YrsTB zaWg~LDFbcMU(8FmQp8AUFIq|I5D1M3bEGUpOL~O@B4P;@krLJ6EmkN8C1_%b!{e`! z&V*uZ9@*OS6+Z4~)E1ts)oh;T+ueRxuKU~tT?DtgauW@G*vjW&2DetFRspMd1p#g3 zC)i<@*kaYyyi@UjQiJX^YJx-yDZA4&+7~zuGYFbOJggy?9KEJNDIySrmAS&a`qyQn zaBZnC{q`pxdO$&CIK6eu&0rOaYF!=GJm*M)K}CZSGQs!GR;%}jh{Gb+fJ`nHd2zg$ z&D?~l4py&pNh*Mu$04u+cNc3FV}l?xfk|vCftU*jZEPop%%y^D0fbVbS7E1@JKs!} z$aT^#XCRWaOe%|m@Z97IpfhHNI~S@-FIFjsuzoPiVyY1Vgm_>ypGqaL=u+1d2jphP z^{&=N#}hrLbOIwfk)3c?%o$ly7m)xbq*KYkkeSjFaiTg1763#%e2C}}Dk%$R#0=yl zi|!!emh?4g3em*4aN2C{H76w`zTU{T1xc9O*Nh2JH9{Gn9Oht@mW>uin3ixfd{BGT zQNwHdpEgew0;0`E%)>~t6(1=glE|Eqk|xzYi4hiTTnV#i$^Zl%Fbb{Jg;fHpq>|Kw z@9pM~<~`|MpXJ`_;jjP9`#<%`@BZcwZ+E*z7Ig$;hRlu;J`;rz78eN@pocaZJ;2G*4~R&BMA@nZ0S;BCz7Zh+)q<68z(1K)BvaxjtVzK z(l(-z>Rv5G83*D+tG$J0A!vazqh%rxLb{pH%_Rs#gQLaal6C+wDBD=Qnwk063`nUK z#VZ7o43G)n}@2VB#~%`rm18VYODB3wbt-zrP(&y5v6p}rPRVm?jB00 zM3SMC<#L}sF-W%2*!zxi9oce?$ymf1?F@7z24$qyd>+|RxD z;Wr=t{-1ocpG|n^yC28~WlUsL$P zQ+q^&5TYs)q9PH{1WH@XHUMbw;I{)j*zU;`9_HRoXMmDCAFw45I#7ktiw>PqRDtFP z3|hdI6uJ;FPQ}LAi+eXn&U#>lG&)_|Oh9YHs0D-0Y}%5@-moE|gpiRWfR23o{%SFB zS4*vNxE=xZkf1$$tsC5<9S_jdPxkc;OOaGmnUkqFD8+**8ugz62t+^+{h3cbY8}F? zi0s9q&h42M$JK{230=u>WT4%ni~4ppc#B{OD2J!D0Pud%>1wfeVPKKy)e<6!XzOhN z9!`b|n!AqXL!U&V>(!cfTGUNaR&Q3TuYa5>O4S;XC=+;bTi|xONW(%rLMaqFFu9>d zPErZ@f$JMVRY?kmX`_Gmp_4t&VKamZvP3kJhA@_$B$Wu>j&Zs765bJAl2w*ta*+*$ zhHTw;?g{LI3E=|CP(+u+L`sCZsIVkfi&f;6O7Bb-8blI8ugxo^@3VB`%{gOM_NA5E z8&6*$8lW?EIoi4cxg~%BXi`nmh#ql3S4In{G&hNOv_WnQ9jOXa2uKMfm5c-UD5;1j zBRsdW1EFjZOcG22Vbn19MivvmOD%_2gtQ$42|~po1X@=a@I%7H{O#@hpcbg~N4=je z7oU81_Wr|9zVq?-|Mbfz&o)Eud#ykXNmF19FOVvFDZD~+4uk-~=sH~v1DKj*Hs>4? z^W@dq1={QE2+1l$7{nby&k3DMmqieBDPyg-(|kL-x!3CENZld56G}i;lh3v8Yq*wr z_%ymXAOJ<1nbHs6tTu|~fjFzGR7i=I^CP`Mo^#F$608;h)Tz!>W&4D;c9=WKq$)|- zN=wl&7wwcrVI+~9lc+Ep60=82s!1*2<UOfAgoTdKj#hvD)%@;W@r|_VVBT-lwlFcXeM; ztBO*^+(9HHLR91HNhKYm(gJg>j>gJKL~8-HLTTc4N$;V7N=xprRP)fLJ3CyBW;QSwX8&!vm1i#Imf`+KnFOk_6TJPSX%x zRU#N}fkbEyX=mq#g-Wfe<<+BxkCajZC61TfvTt-xwE44pbnSTvvT+}v4D`*&s&uD& z2%$;BQ74~^Er#r*TZCAPh4+-46iIeFzpW0BWlpKaYGAEx#269`5lO@hQc?sYkWwH( zn8H|FTT3%*;FfYEJhGxBLtDNgSVcfXihz3plKHpZyz|rF{pQWyF1EMZvFvWA)pC$d zw|o2Y<@Mv|FIo`}2Yk9TLp>=9iUbaKUx{G)+M8$s52c`|RG2sPV}v);FXKRHt06?O zn1Gav01jp(%=3(fQs+rAm zsERo#?uaaUl(cEjEqqAQe1Z+(A+2$J7{)YKJB7>*Xc$uFTAf{zu)6eo@9sVA^Q+DF z#p^3?FD45ZNS&uzSodPp;f^5#Dpn5!H-Hpr1}zInlD^GSB!p7tnv!Ipd%!Jc5y?W# zoTj-1@K680zyIlvUQSYi0=J*});o{xtiE{p>eJ6&by=MlI=aVP+i^qM&8E7Qh+3gw zqNs%V-1f(C)E0@$a8M--?L2DH$e+>DX5On%!r@*}0@>R|OWh(TsotnAFgFQJhqORQ zP=$$71uf0rj?_uTTh>Y_A`OHt8q)5bfU-G(tilZ99*KZQnXMa~kZ=(;*g!N&1G>$J_)qqZl%WC?LgU55JO*INUs)BZe$g<8 zI}h`m1tL@Rwib`@%s3vp78Dw~1U6K!w61S!Kek0>tIiIZB$&RIPg3A6Q}wH{!kLMB zpnEAp7Ml7_cg1&eovIIHC$W;W7}9R6XBErTA~SMB-#7#mRJW42CdwQ<`!@~RQn@J4GW2&@-XiV zYb;5s9J&+{F-^6aTL6$nCt1U*1my5-3b@67Ec0xu(f|J6|4%>onK#43n4Z77*zd>I zXKw281{*a%*hUMH8WOIy(vORvx|>DPq?zVkN~4;w@6oFy)hfBmv9mDc>wfK9g}D4GN$RiU#nL_--v zmZX}JsGwc1ff%P&0zqxdeXotAI(tbuDN|c;L=?ATVFAqUE%+Hx0r$C>8Co|I2UamP zs+DP;#;J_8mT8PShx=sJe1?0}$-M}8D1Fq)N^PCMh>#Ga01cwv4u@Q39eQzhRiuO& zQ4Ui{5=`%|7hh~|FZ;Au9%;A}%sJpKDd`gpNG4RVBz3NR_&`a*(s;5}TbEo#%@B|z zQfoj&h1I>!i13V*R5Z{7W1^XuS(a89hN>9icA9<0QjFE>hE2d;3gRbGPaeV|eUsnUXTbsc4^5LZ4|? zx7&b*9zdR;#6BuKDRRF99rxt{wR7o(^ zY8ZOyP4B;XZ#&jfLsWCuIdxbL{X%c{8z?(bSdk8`kSEf*0nM^VxP&59S*tW&`JW#m z!a&wQ3Z@o@w$=w0g9uAYZ8#40LWIPD_Z=0b8fcy<@X$o+A*`>W5g}+iQOZI8eHf27 zV3dFT>>VstUVArEP<+1K-(1{G?E9`uS@+z3^2;B*^U|g0 zNxCdar5sMg0rh4bad9$KwUL%QLW9Dv6742TVaj3f2H~hPy#|O@8Z5>3A}X-LAjp_o zmhu2r<5Rg4su73I#zWwFp z=1+e3)DfJcbFMlSp}T9&C#R>|c?|V&E@vlwTJiPe?PgoQ{OVeVtjhO4c<`gopO@M; z)C>_#tY#tfLZv5VHMds6Xp?-0xEQ=Ta%yK4ac_P#%3%ZV%7fe3ogNm5OtA=23Di<6 zi?oc2M0BdDW3QSt8r>d^Y8&}quZNo=adu+j{7Eej77XwIULs8+2yEIbK>71b$w7zZsFjereF5}>)Of^zV+F)@nMn`ZM&W-RlMUR?4HhSk!{ z4+LF(FHjqESmC29XG%vd}t`BE?(|{Jq+gFNCp)B+a`lsaNxc zH`UgiN6_6YA}3h&$*Lx5PO1nv6}QC;B!fvvO~uT@5B5qhTHTojc%q_#G{h5SCiWC@ z$r=?DSe8KJ`0=G3uTl&bfZ!@Y+m5h9XQtBQ1F@94Akok~l!WoKqZz^_LfuzIQjG?zokz9Iahfnq^ITFEf$nxwnWqo_ z!pEQd+(%D8efq_pe)jy&9^X8_;dGOx5fn>W8E$siZAR;YMnk;m!2-s1ouM*GGPrqF z6?3UZnrmvKUIW+ew@pgI!-f;5guk}-WwrmxIt1oEP)m# z>J++2H3_&#Fr1xC*V|wG)nEFL|JUFB2mj;me){>VVkIT!jJ^{QC98@6u97-c-xuvW z>3xyXojb#$`zQO|{PgycIlL{%-V44!`(3fe;GI#M-_HJk`pgNUQWll15$VqdS2u9Rmv>I-%=3UYVpQnlg zXEK==N(fk5>C_z+h$t#nqlJWW(zaww%0@{n5%XBKaT9cLx{HV>p-Kp=2J2j`Mky6& z{%z!x+U#1)Bd8q{snri?ayDhG4!zLbML;zpB61sm2`n6Ssx6A+K~;e`MFS!z9&*T5 z!JExMOhwzEIMMt}^sROG)$1!s-OzXLvq@qVz=a;>p44L&Dn;h7$+_iUplb;%aQL;{cclR}dAJq0*!RSv+wQoFK!13eV1U-v!h?bgU78g&xAk8WAhv ztxw*Xa(wyhs*d%+{qv)HtbMSOQiMbpDndml;Zc2d zuO1?ilk}<*-bp&{7kA9y1qxS2oAE3+>Yiw{RB)rrMo4w2 zgecvj4LukKbCG#$!vE1f{oVh~-~E;SJiUH(IZtz!l#<}J2C@okmE84!S#h%Obgrco zH%E0QmGDxm&hB-F8v-FAIj5{1Zih?;#p%!>t3|ZGl@r2QYE*atX-G+^Ar9<{xj`5y z`D{p`cTbjfyZ_h!?05dg-}>(JXRkl|@mDw3q_i zOPyLJSb_vYx~vM*tXJ3DfAOz=@5i4$pXaIhX>DJY>&0ff9Y>2ArMgY^r#^V&g9m3V zo~&KIy1Dw|i)Z7_^p}3^C*S_y{ttinVg`3pdG_KW_o|3zudkI!vd)u9le`Pv+I-kd z!qru16%Z-rjxY&z*q;aFLImP-lL`}zifBor#yo4Ypp>Ims6Z3U9D$%)#eQ!T39n65^zQ0u=XX?{A_-oJv>?&)PK_tBTH07%9LuVS_43I%F<}((cbeE6LSWop-3D_ zbB;<_P@GPvJ0n8d!rkwtxv*m>wqP;9 z+U^QjNv8!sPmq>AoGRQa!xIu~C@6{Zj3iPVSG(GQ%btD!2gEd4b&4Q~OtYn|nx)a@ zg%VMPN=BC~6tl5d^hv9`ir`Rlg}}mE3tV{gWTP`mNvp@elsshY#+bc8g)RsnRw`hv^bD6G>DRZf?kI;{|xM zjio4&iPB))L35|IJVo1#*r5eaN6!bBD_nLBEuZQJwI9m0?ppA>tSEf3N0#px($b{HmZmou@ zre0rP?|$&TCw=xeAD*7wJ^A#9PmfmJd!M}V`02&G89({tt@j?@{lnk;d`_*v84YwI zfFi=hiBL}_aHJHXCd8pQK!DOJ09Gl{qG(uTC9MypL7VNPg8NdedMg0E*zSMxcRpR6 zuEjjTW3Jeb@4R()?)A&hpMCu1o$Wloe7-qZ4;{qqHVJoQO^YF?u9|OdCsHfi!<$Pr zBKm0Qki$sJ%~YjE6bm$(T3Z-WHM5q;3^VUUh6IyTig_}xDCU$DyZPt8^Ao7`^2ybw z-+#QD=5agsN%#AGFoePIBq||R!eTpxFElIh~* z#?5V-GU8W$^*j5`X0=LXoa<}=nK*8z^LwlNZ!9ifUXNw|lRx2J!? zU_p^UdV{nvDOSsriQ8hJyLOK3PE01**;8$q3g3Y9y8196pV^3a??|G>0Qe3NlyV| zPI}>tySZ%l^(d$FAq&EclX`G6dRFuuPce@E}T+#N3g@T&ghIt638O zaj;Pb37Lr?I(jzL0MrnoOr#XVSp6hoT?~j#CllffDU{PZz5UjMZ~VfC-~a0Mcsre* z9UU*0cOTq?NVxG}FQ%*h$&a2J?8)ov?RJ)w=DBzigtXfLT7`xsBARFYU`}fN^8W>B z65%2NNkIXf(YP7yM@~UFR0D`*pTF_`!`0F8Zl2s(XWZQGUp;%-ccMBBX*e3R8@O66 zkJhWM@7L>o(aX?Dm$RglQc9X2?g(q=-Z%jCi{!?MP))@R(L_Df!X?ExjxR2*|MX8k z`|!cpFaG*Z{lEUfzda)U-hcJi{_+3x`+xR3KmITO&aZZfS)w%9unW{Cj~=Zs13+S~ z%OvYQ8LUV%^JrFWfkCejk}1Qh70*eOOu1{@xd<3gYcObxCH3Ly@yXF*^J@RikKdi& zDa$I4?w?NE&8y2zp8cbT58rxtVwv;wbkR$OU0&^FSYq;&)9qZQDcY%%5t=a7LWqE) z`_Sc-={2Uk87NxZ-CY9V2goEWpdt{OMcK}2h@FUOdwspT-E79&V#a6xW1A^Vb*q$JaO0 zE(t|AT4fVAAP6GRD?nCvK;dMBTLdI)sG_>V*@w4jCJqqAM}$N~ zg1T3esFIShRX0S`!`zrmLtCWH!;mD06)1C~O9zGGR2&=_t$PyK3fJ3B+Di%=;YD5TgSj(o08yJe2HbNJW?m&oa{~|t{ zFCiy2guDVa%0plaNGWaS`QqZLlyP@^JC3_ykhkA|RHceatyPoGQ4Jx`B%GUSm24E@UPTZQ$gM2{2#^RTD2;c;^)S43 z=j87Fv)yb~TSP(9Pk*>rDdAnt%SBHSiX^gzKcqk$)RGK$pUad}n)WtY$%B@0E@fN}(k;`~es?@{R7iqAk|YasWNsbz zgr)LZZ@m5B&dKrF!ou6KM;IZE&lCc6R740GMP9dax!mrm`({7Acz!ueJCk6*E0@Xt z^S|+Prw@*k4oH0S&HL-WK8Tc3th9u}G;VMAr+1G(_~7a9{nq!s_3gL6`0~ZR`er*z z$IF{3B6-vRmCQ*+#oWC}*UMt*Lzl*#M{u0#TlP31 z9N)Qjw7Z!!_c!BydwKQizxWexJUTi#IxaR(vu$suah!&(`_@ms{d%0O` z?a;C8{O;-MI$=RFs_{pm$k6+&Iw@QW~iBt~;fN*gza;Qg>o4EyAhYWyH zspu1hHLG-e7DOnc67&PqO;Bq@gk*-hS9in&dwILLy1p$X%)geY2Hac-dNi6P!P!j# zZI+%eZ$u@r$wLlAt!C?LAp>?Q*76=^LF`MF5USL0HwiOkEW6wxS5h+sPD9pI!@Y_y zBt=jV2q?37Xh^UI026a-P7bp;%mZ3sztj@mGJetU@BxqF*B5qkb9;QeJUv}5yFNsc z>%jv>CRn`LVOi(c?<8lfg)AN+Y&Hm&P^VgT)k;Yatt{~1OjR_l91lneGz$XVx~?;K zGMRBY@I`R{-0?eDz%`InFP zQ;hTc+kg1Od5~e%zqs6f?*~uzW4*k&6`7AxJ-;&?-#LZoZnr-_>bqg_^x1_?)ktUb zn(rR1hOT>kbGxgtH@n`9qT%!`w075nN^-y&`@HQk`o@rGTj|E_SABVTbMg4%Z~v`d zcyYPkUXLCIKy!NW`sV88C4tq^@v!U>y5En>bvN&es?J`OdV0J9<$FK)ajnzwYI%0I zbc^9;v*}V!sy_SK`C78x?xx*#dh^|T*4{#nBwTgfM{hlR|Ngm#FO&SWU;o*9J0?j# z{q1)j-8<`2ceB|ks!yKsAa0s_j|eZ#?3x*W`)~Zr@%`hQ>)X|O5Mh~p+>OgsFDi}x z=wbWae(18Ko+_Vy_4@L6zv{ZQ91`qGW>0`Z*SSAi=+T|iZoO(Qfbad_v)k<^i!2vC zGfOE^?P#^U-oJeL>gwe5_-dS@*J{YBUYVfoj6ZPvnWk%ySv)__(Guw1+CtW|N3A4_UYMry;@L`1$LL? z)308go-ZH0bLZ8U7u{SoPj4ISah^R(f3Yu5KQDcs22H1_kMO>0%R<_2>ayYY>AMgli~Qd&wzIcDHvFF{q1gFY5P~(jnztv8sp9W!Mo?$ z_b~0V-fs3sr$@OTo;|r{mRjT4>&?~eXtOyQ0|x6Z`7+*k>-^q>lg~eY`uNLd&M48y z_f%4;(CCRowNz(gGAN=kELokTCS7Q!3BhP*5mXq$Aq>>wZV}NK$rp-Qaw(f|av9ysoc&KxQ^hz_49;JAx!f>-% zE!Y9hpdnC#Wa!Mz#b$rIzjuDRUM*9wk1$0I22<)P?kh{3%Czqru9X3{ghJAGFVaSw z54K&462Zo43@}<0PIYuI)l;Q*4W93CB(hnP)Fbr?fEf)Ag;<187#ab_vQv#vbBcXKmO|ZtFM0is(S3pWOaXhmKC~M z=Bw-7vdiufyZOU+9$jy5cDu5h>e12a>}2ui(dk3*ho8TStL^P>4s|m_O({t<=pT(C zf-hk|Kt8{w#A#o;ewDg(@%qMIUgq50TyE|^ zJbU%xa=lnb@(3KQm(=KnbTTZ;IDY=wS4T(3pxu4)-tG&DGZ3PS%TIIZX2`VfXHxNGG5D_+>3_XwoSrrGPc)jou<)cw?LaaoumH z*+hVF>6}TcGcEh;*V~-6?`1#E+T~K}7`3N3%W~0|GF`=(a%Qb?6T`3n`gh)W|6Z*` zh>B34WY=}gWdGgoMoMTT;UL7@T3kfvVL?)b034Jip#6IF4+)Pzuzk)$yw=;@-mOm4 z?B=^^s{88I2sWOBm>}ZL>D_MGqf4+@rC~iBb=o_jIrUwK;IQl-zIi6f&362qKl$=% zU&6xa7N!=UcU_qlsg29$UnX1no+QgzHj0#X;L{x&}ZV3u=(WZ1pJ50lh z0|*g8VuYI~L6*6=P0_Xcm3c#)l|YTy&wkXW*#jwSgo+V57e+M-Yj|}@mB(4C`^}zv ztLCxja&ly-dsK5rxVZ{D$m~?n)iPDu?dWawFJOwaOgS%TK8rP)1&uImc5NcD<_KU3 z3<%Dp2R4vPMNKLcBt%%&xcA}1NxRd&>&Vs7;`n%VGuHg{)q5X5`t9HS@&E7-fAfv^ z?yVNNU-#ep{>yd0Se_g``Rw_$Em-C2i|u-mPlnz_KK=2tA@|EW>l%KwFZSZPKUx9E zUDx&9IPDQsvVohbnHY0wDk~;tAq=i59f%o1b0`3dvD)T(Z;~7FIlyr&_s@@?JbCf@ z$;AgBy|vlxx^6f-UM?2-Xg#1J4>=41gvT2X?hMOrcRL;(&7EpDWYv^Yx_j@W2EEkP z(K2gx7a@dpFq0GGR2pWPBJ)&RGpJhZs_o}`-04q#=WTXrHmj2XqFEv$tK_UXX@T#@ ziJHs`YkL$xTs_d*G@u}07AY~zx{QZ!EGP^!qz;rYoA<>cYMrldZs!_5{^G^c=Qqn< zKKQA3YMCXX>vQT-pG1V!{P?4!iB(LDDJNCJz0~M(Ct2vBscW^;0ZqslLHIJ zSvci{fq54m5`?!`21MM2 z3=40(SZm;9H~_1M>ah?xOA1(og=m5T)dL!&6Le!3mC|+a=3jD5vzbG?oYY&GLK+Uv zkyQh&npGgdQcO}BOif~z#K zg*DX^iD{m;`(1j~>v=3z+MV1&kK zwOV+{zIvBZ2dX!gX|2_yVSY(FI08Xn7HUIWH@Hwlm-xT9N-?TuO3EH#k^~V&d@6;8 z%vSGJLdL0xMnd%vL-Up~5H6Sldv7o(&7=m5Ea6Q=Qo^eTODh&~$O5s=SW0C$7RtrY zPgb)AfYhK$amdPRphBEX@Z61H=BfVb|Sbc~<*&b!wyu2v_jI&*c>FZs3#P4c_qmA1DrkCu1L`86k#e%Obs>NK>3-P5}=|YbR>0`o)JxITx!i8nz9PIl=oxJizG^_ zhQY&A;s+nTk@(2M?%qGHC2C8QAXo?fP$_fr8H>98z@zU9b7Xch#AMUFVE z$ooYffV-U>ExRt2V*QY&GGAVgKE>(jkh^?yb-P&h+x@uT%~^Q=?5OLK1-85K>9dQ= zS2yta_}+T5+9@QdCA!yE@UJt_3o{Ukj&3|{ARV1uFu=; zlvSbT9=pq3m(p9(>!;7Jljilh-&@^WZSJlYf9Tt{eS!a_?JKU>ZQ|mqnUZB<|2T_JgcVB zOu#I%TCY~eT1rre!+iwaB8C1-Va%D8&zEu$)B1>Aj|uLLgZsgu4+!B)4KDP{W(Hu7SGd z8sULtAvwDgcUN|82hegl4n|b*tW<_uY`0_D0F*_R$i8bnOo>`Uy%p@;oqhn<1)SpQ z(&A2ln?stugscLFgiCk{_aH**WD=NW^hr{R5>S;8j-@J75;eC&`CEwM-ttVs)KI(T zK?y`tx^@XkP0;EEoC|8yu;^0sIlD-ii&8e@oN0?yXMw4N<}h=~qC`cQV!to&NTiCY zwh$HF5H+Yo0zwu_&9R+qu7?1NleLsSqwf*nQfXi$X?|mC0dyh@GigEl`sZgE)&V9# zstStVTdaQlKmMh&x9|7ekXAj0;r7MV#mno<>+2_3!4K z-0X+k1sF6``cPt5YDXYyJl${`W)tg9YIk+utv;tb!)HzFU7M;5MkjI zgK1E6n!Vx*2nR!@i*O1JUPkLgUR(fFpQA>pV3|!-IuY|4D)UsXH#@6_*GwsuxprON zZ*MPOU){NXmU^8h6HQk)+wJw{!M*d%Zh!Im<|y~~-@Nzu`D+P#|GfuJynbW}{P$943qa_{c(<>h#}**ti7I*z66r-yfrBlF3#SId65bN}q=i!1Ev zd+(f`-8=e&-+z31yws&U{_^!Ab#K0V@9KJU@#5zG-Szzkr<;qL>+P0{C>T?`w#D2Z^qlJ@x%A; z7puEX(JZ2H^PAful%swB;?c~-+%nco4339(;vNh>q!1;l_`? z@!;ZmbMs>KVX~>J#4_~>3P`4$9i4PJi$*EqX1hN>KKbaK?#0z*aIdXcqN*ZEkUB+@ z_MiPY-tPBE>ClvDCvQU_mYPl%eK*ik(BpOExWXzXUS=`?7Y_N+mV8K!jRCS@W&le=5C5r*NL0a zOKG56PBSCC*lZPGFhMNXCex9-#@gW55hsf#^qKc1CD4euM0gcNF=YreDqw7rZEw;6 z2?ywhoir`A(A{D84R{rF6;Ux&&gQi`2~mnjPKn}Tf$&np08zK5WFbnk!-GMo;pyv} za3Vxvu8pVa9+({o3}URc8c9FuQc_Cd?d)CxVifOkhtRL5I$^*v)2bWb<|)F$Np1Fy z8q9K#WNA>9Rz0Z}H#=PSB9Tc&RaTv7BKGaF7eNn7cxYBCS#2Rnz`>#Jl}t%GjWwbu zL)c5wL1nePp6v3+&v!Tb^)RegkDp%DV$sRw zW>1f~<5O_wF9;_InG=)mTAQvtku) zCKL%&I#lMdnps{9Q9NZ9w$KQ`MSd2DCa}h-90-Vm~8Zi_m6M3w~x+FkB__c`EWKI ziSyB0XP2wRo9FlLov$EZ?T(M`p59%TV)HwX&hIX!@V8Fy4~xEEq<8M$p~u}jN4shK z#s`&CIlFW6?T;VbKRp>1vRtJP-?^uTg8IT(~#wx<4%XBj^N^FQ@*MC6|HWHBr2 z{NT~)G}mwb?7QJ%#k+p^=Fh(8u=Z3F!TNh&q>I zCKi}#Db6r!(S)I6?vt7fNtMy{A{r&4nwPn@2e(BSyw%l%q=(PVnT-Q069AYrDV;fm zN9)i)LW5+mWrZWLNy;s0*3n9-oqaA=}a!Vc~KMhv1ik*r%n35IuBJEzk{f~J6JLP3<; zC{ZEdrhrwdS_ECtj<`Wl0^x!rbcTTj&J6>J=o0&`3C}#5?mW<_YYr2mQk5a*AyEQd z00j+_;z9A&^-&FPS}xZZr>c-F6qlSNfN}PDs)K6Kmzw&_RxETP1uK0sR~SIL1sG6D zxHr8ita?^XMB2K8%_ZcPjqP1iJY8CjZ?^>Awkkrv@WKFv0`kYLn z6w6e}0;f_U+{`Vadc*!lm!N@OkTXNWRC87e7P)WUpvSjufz{yhDTa$zmPdWp={(L| z&Xw`--qC8&=T+W4oKa{IDN$Qkw*6YWgFWUkgElXEV45DewsB& zwMa~FzI9fG^Ej7UZ?@w={`$}T`pJ5LLK=aK9@N{G-9k%!|irCR|{1pZNBB` zl|rdBvhTZ8=A9LFYQ&_Pa_S(M%P3@oc$g3>nH00q*HzS_%}^ZLFR}ONb#D zW!zPY!p2%1ma5l2u}soX- zzuc5kDY3a8n*lWmrg2iL8@fJ=GNs&SQSp?xS}2Mqazac|rG(qz*jl4jcL^pCnSekA z9t)vGP?9ptotc1pnY%8Txn@xyAjXgyjwoiDMXBws93(|@u(}ruv#5viqt}YGNO_UU zcH)6N7-gD2`|SDcIFGyiN|7_IMv~~oJAjE{tb!_D=5b)N=EY<|g(4zCDdAxZI6DdV z>J&T7Z#)nQngRtD4DAx(5}0dkE>{iG+s52I#03rIP|@h)0f9E#rG&ND;cCBIX6d7< ziwhCjs_D%<136%BLsC=-jA4uhsc&lHmi=)L35$qelSqO__9CmSDPk^#Z7+flre!KqeK|I zc`zFisW^q41D#=@1W|y=YXS(&=5r;JL?APAP9$gZaO9*NLX30?&=8`MEJ13ZX&692 zJtT0OWNZGx`wzeM_S*{;7Z&ot2lvvVd;M~Id2xF+758#}w0QIVHzUxCXc8S#sixs| zss?uf!K4BWd*73&K+sC)*6M^7feM!59!?Kcp(qRpV^4xGIXKYqZ^N12*rJO7Vlk)84mSpO3)EbCk z7&aHX`rN6M1T*+-i`B533e3Bt7G4oqM038n+;&MRfFuFBL{Zs}HFt@%RF9x^LUUeU zZE`OZj{6eMh2kf^^Ugo|AO78-IcKSi-DW&mFD2`4vrB!7gi-_57ri=VyWP9nVzs`! z+|;?AogNSC^z8Aah@Rg)E+xikx_iGimq?wqf>MR)mfbKK>>_BVg=Km6|ZKl|~E+;Mqw{OsA~O7-5GtIOSd zds7~qEsxiW7cVzqc68JU#S50l!_9tv`t0iXsQ<=C4(0z~``Y&$r_tPZ+qqLoy)1|BW*uEkzi5hxPTSMjaWEBOQ+leXqMZekZ*UQEI`*%M5{Asl+qGa?9D5_zBaXS?^ zGI|k#?ai!#4I}2m`~dCL+h?s-zx?uLues~x*5!$Lu*2&#EUkrb+` zXTQ4xk+T@xIFcdMUCPm8J7cV8& zDQRM;s|aUP(gf~+sM4u$MMS984w6>teL9Ks)4%kS*Sq~~X+3eg{L?SrdE@TK-+u3M zod3Z;`Mu9SeSCJ*pPU`1EM9DXJp%UDnXHPD#uf}CcCufVkOP5!-b+(RCNMu4G9VO~pJt@={z`f3+Bbwl>* zu()%&y4>83a~V={!BoAY93LM&d3i;TexXg7d8YE_`;Y$k$4_WD?gw4!lULUXvgmcH z&T9AWoZj4wyWQL`5;exDX3+9$0j%LgAm{Oa?U^HjS*gF27(beZlyy!*W$ zJ%-?9wVcduuD2iFe{lEV`S*VCnBnJV>#O}-CwudFdG|NYzIgHnb)4UM_s-3Bdi~_; z&gqf&^6JG^pVR$!@4k9{v%8oc+&}JD-PNn>I+uHI@bcAmx3kO3a_9c)`nu5O_*@va+G_jN=uk9xb`Y4B*B=2~v9ciVmLm&+k1uWog2$G}b{ zysQRYFS^{R0_%mW7fI;%@0=W;^y?LGSKVG@x#$w=(Rx|t62;!Qcj|K)*hdyy4=B;4 zMEG)*fBmoioX{3S`ng~HhAcyS>Oew%`PV-F8)xgQ%iH(9I=i^F7q7>**=>e^X6;7n zvN~S==w9=GNJ+Ck%4!aH z22%vxMWPg+OBm3rQdE}NDHoU9(PJ!Dt1tV!(oBUVMm<Ty-fFzMFxxpB*jl79qf)$Piu`A`<4p2#?e^F}zp`ZI~=q zgd31py%NR{DeBEc1A;DsfHasY+wUsWtwA)6?g0g|G6}&?Xiy}efdUnAakwXhAZGKJd=6hE zdHBY?FP=Vs_uKFMhwpv+P=VJHW?jx_i2M z=Z*7|(-nleT>j3VzWDz4o-MPV-Cd`gpFY1jKRuE@|L_No@1HGRyG|SjvmbZ!H$Hx&%iXibS4>Y+3t3?^ZID@)*E+!_m6&T`+EP)AtcIf zf}|3)%wBiXaPMsD zt#pygW>eIo$5bVn~RXY8A@cZ{A%?R}DF#)@s4?y@mAe(1Qj5a_+t;^Ez+zxh|cn;FZM>~}^}cT2s(*r}$YRI6)MNVvF{SS%KlTIMS3 z0y33}!XanU<{7!`MSL1dl0pZ?hw>PUUZV%N2#E@zWxH`f$7Qf$ni3W`-bJ6-Rm5t4?k+l>W^ zVkQ9rkB*Pbrg<){a7rL0QKIWp7M3t4)tFTyJi@ETJO!CkV)c1nIoZ5-OeM^sS`!`U z1muLNdW|4jlGo=_7hQk%!TEM`YvcIvjR)hdY&N%Nt2Ko;n_CS%>X&5fr{XO|n#F+x zQSnk|t4vwjFKse7HPIs)o30V^Bs^5mu(?S^L_`Zz5Q$%l0|ge55Eji*c(7$hgrH?e z7%rw_2e??n`a4_=LxUkT%`PZ(N~o$iTi&NiOhBfD(+!mH2K~?wxI!HCiVzr}67Wc> zK`&N%?I5Vt6U7}%b;9O^sTKR`N>3@NzylOoIGIFPy+$CZDA2nY!WslkJWMjA zGL@(iQQ8VTi14h;dN9eAu+sKQA>xEsKo%z7c=ztQ%Ys-A-P;dO-g@ik&7XYd`=37h z8-MZJl0}nB@ZNgy_D2uGTqx&fC;N-rUK3M-$kCB5AD#C}uf}r3^ziamfyxP4x>)ZWYcGj(OwW2`EG90hJ{qct)0h&1&db;e_cb1PH z-uKzMg}C_bO@VP=rc#U5vRri@YO|{}j~GEuy?*q;{iI14WKtq0c76XBe(~entD8^z z$*MzQs{T{oc{2;Efx#Brs1as0i6qq~qVHDe{L#ty(VK}*QB_#0&{+M}Hy$aq)F^N@ zsM!5Cj>2`WVDd!doNJlS&esS*m?l`b*HFZ_KY26^X)Hd2>Qpbei;q5e01ud-iS(&k zWCXcdXqcO0ecVN$7)9X4LC)iTYHXU~$4C7b{^IHu9^ytsUUsu_+!Y7b!vHDU>$2TU ztMxEWB?)VoRY~Nc(_xjz(QUSzx!dlHIxL29Utsm)kM15FEiO0n_y6dtU;U51`~5E; z|KJDD7hUR?sRjM_v{I< z^}Y8VJ$-$By`8dB1kdGBVN_tX64(^sPW zwV!|g>~!_&YWJsq`uI2g>M#A#AN=?a|M<&AFMszx`^&%odw+6qdAnTnqfP8!i}Vlw z*&l7L$54XmAvt9*?wp={<0pXKMRE3fBv*W>YeF_|r=^74l-tO!++v{nmuv&en7$eCcR zrVK==O4lWKs}_k|_37j&U0mG~shT&;OG?p0sz*VEupvon3(P1RqFEX4Ax5E?MRjk8 zo~{=%=xo*rg3M}G%>oeAr=%daSsz= z96~o1f+VcwR@K19qHdX7Fam^!iibm?5Y#XUW=c-t(!lo(Ro4~=RAqP|Jk%qSLIQ@6 z5)gVYib`S%T`mEiM+~6f}h+3Lls z&5I|uA9U~k_V4~_Qt_y(^`b^xyxIzd;(18rNxj}p)8577&dJgco9!+PtCLl=DN7nh zhu5UhFBYD0bv1g$qLV>|eR{PS_qXG__s-sV^V}2v!}|G(mLet{KQ+2 zM*IK#cmEE#cc0&T>+Y+YtJkl_^?J42?aExv&(`Byce}Fc@l)S?=gSwD&tGkPo{#(C z{H0MzVYTXU%k4Vt~b;9gY)Z)t(vb+S2tIiFnf6KY<0SL{`~rAu{v2N z^LT!7)1|c8%@|7(dE@P~i<|ww{ny|7#gzxlU+^gsU7-+z6zcQ2nm+RV<2tNm9$zS!N&7nirs zpKbe8_P6EY^7hkDpT70zeD>+~@^;+Cy+@}=9!e3d6z!5^RVFWXes)AkT4bg~NrdD@ zclO5e?ul<)&mz^CgbA=7Pu2+4R2xMUz_xlvOE2d-^L(q%-#Cwl++xd2! zZ^vm0lkjj*fkVqMDq!wxCL5rdnM4cR)QG)XhzQ9flD-zfCl+zG4i}>ric1KL!s?5h zg81H#zM71h_4DVi)~oeT{^ZA3H`jmi{b#6_yR;p*wQld6A5SlD#$vsRQ2MM^O+;3G z57=0JE-pz`q&2Rqv zM`rxpKl8 zV{)6D`9Gp84alk(=>{Z_NwMLjbnMI>z#n#!x01*Yi=zWnCF$!Z$ z64R6s0ga_3b4(D%9uUw%YK(KX4ADf*Er|sL3?2l)C8&Yt2gTDLyZqyyT=Al*F}*Y~ z7ON^Mkab2-iZm4l6(y^Sv)wv|s$y<9%@Y72W5`+&>7+@X8kQi8ku}R5kU$$R2*D_t1UW=&Y+g8y9x0hL z-Z@)XvP6`oT(gLx!z{HTOlS!$iv+0&EjcHF9UvKq3P8j$q-hqSB&k8`e9aQ$sdKaA zgVI-|Rv?OKv>6&}q>`0m^Xs>F5BH`;VJ|&$dUJD^1NXaWK2r>jCdxQFn?>f9^Mb~F zaC__4_Bcs0jeE!L@poxMsBBRA!g^G*V)d1{<<#^BN6l#I&? zJ1KotHTUlivu`1^ZPvBDAvD6o)06-4F;VkkjjYY4$qF{Y$Ms4C1_ z{cq4oC6{0mqY6-qYEwo4B1AxpKxoJTU?iZ}PHYe?Ko9`5-ORcyomMf1#sWBJip(u9 z^l#nWt0E()BU|K2?R{XWLui6F4a6Xf5*1NFTc8Ulg9cCoi2vi$j~mpk1;c8HnUn+t zG_nX{BN!tZ!;K8Ty3Lpsq?jdeWbt(uT1|Xss!G4kVmuG+ykVqDcv1EW+ju43= zav-CSBpO8ljIgSa)R1XSy-dn%9YTVk7BJups;XB_tWl(C&2`0&OyU?UN-#h`R;D$3 z22nDAtZGRkNDvHBEU2K7R#bpSTfKCf97a_F14@cHQLjTnv_A^0fQASpa|WHsqUO1A znQ5w;Jgf-zLqrm^W@8*yPp_VQ_RM#`|IUd#|A)W#scfNN*SxWLQ0`C2qJW^bnjrK-Tn<qsRcpmnyr zRaj>YFfs=vmpW8cBx6*35I|#F03Qe#Bs4Jqwl9Okf`ZW?P>cHjL^QFjjI`_-1B7H4 zi<#_b=utSa#yLZP##wEdlLQ9AIWpD)Vu&nC2FQ>agCf9yfjQQaq?8(Mhhl+QSw+Y? zB@KjW6_qSCohfbb*=oEoHJQ$Io zPPaQ8juux2H*anYkH$WR!Jr^eC1PeY_KhnWSFi0F5?r<33j$RPLfOu(cr;U>7eD18YkN0ZvQ zB!qfehi;ZHFZB+OhMCJ+@(;84#z*3^^08KzWoS*OlRyaS!z6^pN2@}{`5=JN8N+Hw zb+*^3eC63^X-0q%m3@doT;kHi4TqJnwq;yq)`&1FNYj8x7?gk!t%wAP2pCnzwSXEj z(lifDjDUo#IR&9jo!Z^bAVW-J1yHucRaQkJV?d)Ciy;IIM5GZE2;&3Yu;JD@1)=pP zpfeAq=>P$l6=hD=!&UDTmU!0lAry*QEx0V~D5+97z zj1g(!0g50>fYty)2r3bbf!4%m$V8G5kO-_%0}9qEP>2$|rtX2pxe5^#Ll9-?7U-;^ zH6cpVh!5;k5=&&E_F@1#{dD!jJO@DvNotxpun$?DH6d~c){!FA<9cy6@2&J0aqnn4 zs{Qb&)DUI|oo+X)Bk%1`0rg;Sl!0Ad?j#*|G%CmAS_J)+2fbu*p(y6`wAD z-QFD^U+h0}`50z+>*jWIP(AU&8;v}Nz*HD-+AWAb1yu5hAh4D_Vw|EC*$T| zXY|Z-=Pq4Z5r!Z9;9at2;^X1&(Z^o6Xp!?QyM5<=1lrphXC^suV*bpz<)i83r{BBs zn_vI@N4MACdi|rvA6k3rspH1kAN}-$z<|cyyuSH~r!QW9WaZ|at@q#EoL`&WIhr2q zjxL{By?A~l?YN)(@V(U&OY8S`b~lH=`Q^vYU0f}z<|jYDSZ0t0{=8Io=^yKM< zo$Z6~eEW@)7f#%`za7i?Tc3a8)S0EjqoY?}{%|lif93s++?ua^;n9_){+gQJc{G|FTb&IYr6u73loba- zjj`w?k3Dta_SJijJbrF(_b5+Ymf5<|G|yt4U@#}?0a%h zB(|wBOsdS1BRYBR*l02t9ZVR6K_tsnvN26(I$N+#suag^VEZHJWj71^>6@bW* zr&UOu5jLReYtd8zczkq}W=^W$j7^J#MOl;>^G=o|i2?4VDH#Y2vlm5R;id^Tan1q( za^%t8&{&Er2w)>-ouY1nF-F^bjwo4Z#4{inS2xjFYZDivhTv@q0Gy=gL)1v%aO!KL z1cJ^OXGB>fMivpEc5CW`vY={64OoMTv59jgu|TZ_90|pevB9Q}P+}keRbXg~2W`Y3 zR2i*+5(rrpP*$`+LV~L1*LF1^A`l=jNT`INrL#&aVWrka0)~8G2bfp^_;th;4XIja z>68krpkggJqat7gfPjIJ#3-<;Z&(zJZIv3@1Z`LpK!|=V0t7Th0VS|O4P=1TAW4h% zz*ZcE!fm}C)5=DkC5$?maDw@@5Eu~ai$y>h2NH@JCcr;qrVPh46!Hh<^F?)AIdlTr@1N9T{vJ^thwOwBJ| z`Jf#7X^5lU^2H}lKK%HJ!^*$;#*F}Ock8h0@Zn14mkoqp%wVB9zEk;jfTB)4yDSEZOdt;fyr<^IW&vzXX-udX+>M#SmfczkK? z)cFN#-IXi1FGXBG9DVTK`swBVWZG9tH*W1tr_newJt{{B)BWMd7_)i*NWjLRaa#Kr z?B;=wx_v#7&2QXqs`5u zFs?34`isV37pSo+}Rz5bv$8rH+3I`zsm?Cg%N-PuJwIM}OD z)O4`Z?d)wIe)wTh42o&R!80l(soUQluWz`+{X>jkEgFKNo8P^8f2Nb!v|&a7%#zHi zjz;B;8(Y)Kbfze}sVS0VZe}2YJNG7&$;2qR+!5%B<+-K_>l;Ttn#Gkxh`Q42&1JnJ zNe=c)e~(vZm%5sqSy?_dvrq@Tetp~5a%}lnTG+xRz5xzqXJ@>(JALGl%SAWuWIYi+ zJgT$(5h0yFf7TeAyFyf%X>Ysa5}teZ;pMft_JZ=sFFf0s?O01+{`w2fLf*;pLDpzY zQ^R8)nwaMqkOsp_n53z%V>R|GD>EWtb!on7{7k=?RJBR1D$X5SK#N>jLo&ZO7&Jwi zCF5yT)*2|m1TqU5SX3mI6DJmL+~tjXL-arhDAGWq1U9i2$zzPH9p{__4Q4tClQCzh z3o-Tw+SH-0I7!jkmX)fLvT<2Tne(bm<&|nbl*A+?YKasi_^`WE0k$rSXsl^M1TtvI zPn*m-FN`XkBxwME2t{m)0YnIlAyylh2|UzDD$bcF&1|1NnEecE+s9{tgMN~#>6c_|h z93rbkB_KpqE2scM(BA3=2oa&h8@KJ=HpgnLD??0`3?ZTrfJKTR1U9t<0Vq|Aq zd%c5}GNB}>mV^}r&;kSyF{-LwqGxTQfC!NFL{0Q8XsivwOo&9$vqMbC1Q8@~mSWol zHwIhDd`q)vfq<=s(wG>9keq5p)SK&7bx@FnlgklwcjqV$C#P5EXJ(7WH*=kQC+L6v z_uom#h%%6&GJN4H&)(V_eem{;7cZ_I|9hXn%-rAG`_(T$BtT%!auXsbqiIDF9zi(C z&4guiP{t@_2ofTTlugqPS1L~$RL0Zkuy)q&?T_NLTA1w|OzNHO(P(eV)YRj6Z{y%f zikKx^+ruizcvQ#4R83&9m4vzs&NL8WqwxL*>%E=B$s}^az>y4&#?=Q`ZbD{a6B7g> zvV+e3?ZfJg+ABItEYMu9NDY=#zH|Fvygym!brXY2^Ruzz38gTE{esiN0S&SuTTQx& zYgktX{pmDby|Uh&9Sn+or+`7$LzW`9bww!@k6t)qoh@e@V-VPq#Ea)nfsg<+O|%F~ zS@68Ja;!De^4fBdo1@)IpgDJbZE0y>Qdg+$b`ub3ygzqx1rdRa#0S(sGWgiT^J-8O z4T`g-DPxi($B!+m3aBNKfJ|gr2o0DATt+emoHb`pC#(tvH3~*{)|kYcSUzTv=H>=p z{M=IrhEj+D&Z)^d7EpqR2Q1PAyWQM8h+Q}#5%w76sV6QIumBQSRZc9}#60oj`3HYS zWECYwmLLf^N)!z#sMPF8)H$Ix*9V|#)i%+C0ZTOK_s(5d`s~LaA_>gCYD5SXg+vWm zGKh&W){+=w4FPKu=b#A^*&?E8rFLi-m8@x3l~IF%M5GlX$%Ti`SYuQ;Nt_}m1QjK) z#u$Nyj5TP58I@uL1(}=6K}D5MKD?|^S>?jx$C#rk_!zjE{Kn^BJbh*{1OP&p*cdr1sR$IEuCx?4k%g6oa+n94&8W0Q<2(ty15SqYbRU-y34S1IrL}@~)U>^`!6`%nYVU7xl zBA`G9070Z>R01MCs6-+`6SdWQArq1{MnQ#H1gxP}TLM6;s;ojRN&rNp_&^R0&SH#l zG_Jb6jzt9#U_?@zXegrE=m~@b2~m{;wc`!-2$7AmPDIGI(n(N*42Z^95K=-#11fC_ zQxu|V5Dwx}Bt?v3Ognr*sMs(70Du5VL_t)cEHRW|3`n5LlAu)(Mg%d`Dy2vjAt+)1 zBoPBZEx_BBwZxzRq(nf*1IKp$LDXs&0Kk#8C;*JANYHxG7(iJqvQcFPHUbLH7>l4N z$h_F;C^C8f?D-Ybx7&MD2~3$*!+K$Lwtr&&vByppokXo2SK-e6(b?n6))4}s>U<|% zIo{tqIC$#elTST)4igt+T-*)3iPE{Z{FTG*dHDs zb7IICn^>~eB*x5S>Dt1~iQ}`7<)@d|kbq+?9F8p?Ppyj}C@8|78|UzeCkiBz$e_^D zEI`#-V+{e3AV6S5Fi9dRieSi)2uolAXAOa(v4E%=IY#4>)L2yT3=|cStLT|IL&|5n z|LC`$XAWpl+c!KQ0p!SpQ4|@el{2F#AQ^`yF}?vyB%!QEl`)9{Xrd2+WAxLSYcFEB zC^AMHqZU~*t}82uQJQMfCXy{^N>)iHjmO|;Q|hhF)fhl%r%mxGzsEsURdZb)6vFc zX}MocriXWiaa-j?TYI2-5FU^wt7*stT#Ea3ee%M|X^f-Y$+_c$YU`j6crC&G(Wq z>8Obkp*zS6po9JKgz)s!7p`2tKin%XURvAOnr^NioL%V7t_^PA-zU!(FP+>T4)1Rs zo<25rY<2F+`QbM5N!%`-6^;F|(+I3?M$J7?BtwV475oPR1p<1dnP3 zX?d{APS;UL{n=x1deD^j3TWOK>#VzB-Cg?A*!?xL==)1 z8)MKkQ4mQDiW&<5q6WxhAR={8LA7L5f9)IqOV(hJ%&H;+8JnviBn3uAgUaf#6?7vK z8Ukhn1yp85YY{+OYqhopoOZIJN~EnJ8k`tI3a9`it(HX;6jdY&i>PR;2SjY0(?CQ- z=&S+N$mpzV&2&Uy$k=?!xi5($kO4wQ6@-?d!%+cLEQTm3pva~*;4-RJg{T}`OrNN> zDr6)K2z3mJOB~u?x0@j%S^{GPK@C!*2&klhWKk7SkXr2~I3$Hggla%Es#qZyPkrqn zCEMu~)7VH5i9p7Jf~q=a6j@k^kjStifjDb|f+2`3Km-rIYHg`}8sS(sT|2jQ(6Y@d0M0-$zY)(W(XY(+T#}^5rio2blVw@Q(9%qH;ruG3 z$!l-iUcb9rWO!`3Q}nZY`$sXbARg_PbNym%Wk3mSZf_Wq>>p0+X*1~NXlPnBd1AV~ z;$YZ-O0S!ZCrw?}gPE+3u(v%KJvEwsS)p~dGv5PCm z7YAZ3Mh-Drbk1rg$!jzd_T$NP=WsM0mTRlMjf0_^hTr()W3$KRC4r`dsthp(GTI_Xfl~rabx}7%F^tx@nP@i3ol;mFU`axp}-u)Iwvs%!H8y3#lvysqupm{4`73X)q! zzoYK%X0uc4+?oDKmQxUau1^M(wFX4?@vzbxn_;((lf!zg+q{s&I1ApFI+H@5 zNQtTDNfhfhST{eqJ(`%RL?3kA1Qy&MR@}>~Mx~7Vd&5y#HMOXk{lm$@eib@8Jo3|# zjz`?g$AkSztQD#TM8F^rwDN~0^#TAU*^n&fVAbw25&iXhUGJPo%9TO$T3mf`aG zlf7<{xpaADrZpX;WQ_tF07cRm6sHX-=0yQo z?Tmo76Z$Bqga%22s8MQ*1klp%KotZ;(HIc~WkmsSL@oIN5DAoog)9;w1A?H<>xqdT z5L6(N03sqHP;6;JOo<{zZRmjs;X(Snl?^Kj2pa_)Rii}6)AG{glZQ3mx^>$C zun$De1pn}}7q5S`wY#+kNKA+v2bRt~eEyxQw`Dwe?&*tbXID$spZ?^%n;)(tqL%=Q z$^aBWQ59l{L6J2Y6SK)E!kOf=l;qw_KiV?M z`{DMqmQHFjm&M4!+=KwmfHN@)#}I{Uw5Dq2Gxx|!A9!3&Sde?IDMbRNikVH+j3$h1 z+B9u8+nr5JHa&DEF(mg7YX~M!3H-#Ry=TrJKXy#_cO9ulX%H0&LqxTPBc}VcpM=rD z{xf-@_ZkC(km-SV=qRCbCq z&nPuy1cpaVxj9U1*1nZ0Vb;z8Txt^0#vg4R&h$D_Gy@XGey`_~=&X>Th?Hg4=Gor< zKDMCvmKi~y)cPRI%JG4cShVxqd~vbUDY7iJ&Y>4I#`wBMBx5WAnv@I~5b%Mk%7-XX zG%&B<->YkZ_AgRU0Ts|#K!x_Kp>~7KEo1={MAQ%hFo>l{$_xM^0Lp-%2msiwD3L`i zU}6&_ZJ%8#2nvL)HSX8oW@ROH#sI3I0YL;(HUiqhnOg=z%VKU*?oox5hyYO#QNf}B z8f;gett=e{T}ql3J1P}~ZR0L!eMI`GC8gwbvkpzr0B7%oLPRkIY zpdm}d1XUd^Ss@T57Im$TrDfuYpusj#+XB#7K}DixWFUaV>ilexfvn6H6`F&?X@82( zef9aj{Lwo%u5LIoQ9P2I?sr#DE&j##-o18p-JwW?82wYHR*K_ufBILy@P`#6gH3f( zefi@LzjgK2-+t%KOY_}NzxZ&7q4CAjs6!!g)>%Rlmif8PnU%$YbZ>7op8BrMdP|Nh9P4yQ_5S7oikv^TN+~TZ zE^wt;LX?^l3ri`+&TPKWo0Ud7Gq5}d@$AXMDdqU^i4!T2E$IA-jjM7vwF;fw%0x)GKT|Y8a%-P>?36XqE&5H#MNYk5GWB6@rjwZr2wY0_)KBYX zFmS$MiTvbq=d;4i9r?OuOVS?{9HD7K@XRDhZp(2~HNk_{b)!*_T{sagFL+;afIM}m zq!vVlnMb2$>#&|AO#*H;Pm6Bhf()y7Qep z?{rc$Mis!v($^dJ_HR~4nyB-k>=(BO1Dfe*#4O9nDszk?fpPzEdUL#6<=ztAJs7<{ znj4&2trmTfBxypz8l$Pb-ye?G%l+Z31?QUa!JCtj9UQMO6o$}QtAdK;g~!wB#^%mF zkFiJ-oAw7ux0}0>-`_f%ot?S#$jR$hZYLTpUOINPKl$LD;mon#g@=#T2Upqqv*%Yj zGhI+^=en`${dG~ATA%9 zbGbI`QPtNHMQ`031{FhK91;9lcWI4twyr~BDM^f|W_c2t#-)xKJPR1K1O@@nptg=& zRulsykpz(dTX8NL0#!jlD*$AGT0{asD?|cSP()TiC95rlQkB^vk|AveLx@CRFi{oT z+U^y(1sae+;g-&z3IrmcmK-XHXkrZ@hyu0xWN7P7qDG;up@JGBVQDct){+WagX~BJ z6%-BFeU>9*Owj=}^A$OWiUBMkqXjZ3iqW)z&Gtn=(EurnIBVO15J0;UkifR(1*tw5 zzO)Pq3y5R@fS_TB0W?8S$wOj1Hn4r+zwdd1SIUXdheYOJANC+Rpdztq3Eb!2XAKXmCd8azJRTY37dwZ=LN z!Y5Z}i+<GOdoK2H7N$i8+-v4&8lLFZ$%H6y7w{C5mKf9XF_TK*G&6#d` z{>fA8cXp4qM-M%I@?cVb^yb}19y&IEeEz++?+m)x>GMn1uW#;e4Ih8{Tp9iQZ{9d{ ze0FxZckROs%85@NyWdn*(YKa5NdjP4wPwG$KfXKKJxVi^Q!@=$r-72iY9&#Y#9CGG zK^om~P!aG^nbOxlAP&Z*b_VxaBb*|H$Nyeixb*V7`RywsA z44k!Y(ljB8)G(=<30H^vO?6PYga)(55jxim5{ZC}Yvl+{6GIhyMLPBVu$+RJsJuHF zy>l&gXS3083QA;&SqxBUV(?8+a!C>-vf7V6+L|vq^Cy>#)2u7}V7qE#MIQi!@=nrt zKdIwe?`|%x4z{-Us{s#5U9L@Z%R!XUlP&75Nj-UA9(+N7M69oF@R!;E!q$!3T{c zM64PgL=+1Zjm@NXiE$~EbvSu;nGA`tO3S$fP!U!Fqrywa2WQX6yBkOQZ+AQ%4qfKDgCYVIxobkj-V^0B-TcifcPr1i zNlu+wSX)`z+#YW2jnF9}kv=ey`a0%CI_P9G-E?DnKh3gUC#%_KsdH9E)mmu0Cn6N& zmV6^5s-T7lTT)pIKx0-=B0>=XgNO*MS(b`w76{3JFLO_NHENQE~1R_KQ_Ccvl zASnPLsS$w|JJv$Mfi&_1zf<%94UiH<6$Cz`d>`avY&yF)VrNl%fw&6mvGuJbz(fHotK3ba$r5Q8_XIc!{Io zM5duX-^Ii@vIt7Xs1T6`jUQaw7~bE#bn#R==v;m4TEADEdgSCgZ{5^s^W?La?(Yrn zUfVo>YU#xJH2|{C#Hi)C?skfut2Z5puS*PC4##tA3&W#Hr<=zzh=TOo%2N+XBo#0n z_uBh+U;f$qs|&q_PIm6p(#qOAkpmSp3P78~>Xlcn)x$}r>lWsV#X)Czd2V*D2h!FT z2mlquSaUQgeHjoGm|aQ=nz*#`Qk7+%I#EaqS4XK1s)dDa0I0^kTR24pFg|!i$nt!& zchv0`HnpR}ah4@X?)J71$J2UeYYz10d<8<114>5AXG1MAa9YW@S5ayTWio%Jg4{U*2PizxnRZCShlJ_cTqKXn$bp!xro=ls%j=@WkP?9+xbS6&}bUdyI)EHEjEOh`v zhHT;pO%x@U&dn_JGM5$vib-OvHBA#5jzUz{da%7e9gompIc=ga3m2)&Qdfr{k>LV8>fG6t(YVHl{fv^#Dqsi^ zg!3dTtAMD{Gslp0^SKjCqhYnbH?6Cngyl5czqg-erm8$xGdU{j7&=8V+f5c1`kh|- z(T%M)-o9;}?RN_C&8elufA(*`w!XRhtC#OS_4KL8lUsMDVkkwuaA`Tu?7>m}(_h{i zl_g?KT${ni+t+tGMYg;=nCs@7J4Y_h4Cw4^feH6cg2&k<*3IG8SD7FGp zY9~cmQV2TAxD2;#N((!-%ufIO^8e$Yx zWZ>Xg*d~c8A`6g;s&&psHDpX;KrzF#=yZi6t0GzzB~&29C{6TAZh2*S(CI*$3Yz05 zSIL61J%8pT`%p(14Ehf}lw_%!R;(P1MY1lc1dhiZIn7NSLQJy^MVqFXy__Ooj8OzB zv2EN$4I;L#6(jh)GFLI|A2p%jy5>;(qDZn%r*5LNC`5ZZ z!_1nQejX#U3K)_Q#k&3NgGAYOb44MdJacv8cX!8PO`16-L4d}4G}bq9?_e)=hO07< zHp>$vNbjS?+o{M59byKWbNM0WL!lLLa13`#AC-TMoR{WON*!DwZ1q48DKR9Rkh zyPdiYKxh*?KB`BD<=In9US%>3TKg>R@9&M4XZi~#XLdtSG^wSe*SmdZcQURz7gu{l z+M6u^%w${#jzJ{tn4-w244dnF{iT5g+1WZQ3p>-v!~mm;C`ZW(3e(u_Wj3|WflJKj zaGGSU)9;ki+9Y;5nuxXI=>!7U`M9xtFs*fNrvK8*?^Dn`Ppc;OI+<9NXkyi5xl6kF z{^3ZX^sP-GI;Jmw{o??FXy1Ql^C#bV``Ai%ZF%AKA70(r*iU}z+4hx28FpVH~RTBfVGugsoSGD!2f`$`yRR`vB8V~oUK5}TP%7?0I zjt+)-nm+r?WwNf{O)cq6Cp#LCfJ}doX9f9?++V-ZpUWZ7uDrKCGgB-s_0F8^zxwJH zlBzSzY7?_E-^;QjLFU*Dio}a#xhWD7Ewh$pAjjRByU`3UbF-rXZ%gYe74iVLKJ0_ry45Wx^R26{@ zqF4k`5Cs8gB`w-ke5pMf5FiSxf*KWJP@@t#04pg(22ubU7#!It%e^2n=u488jb!QDs(3LdYzR zjXo%P5veVikH&sngF#3Q71qu4i%=vcC5cj%tey=SAlv8W@nfKxSw~l}WKtmap z=eqN!j=%lNd%{cxkgy)tYl|}rr&iy2_XbEbXd(lb)zi;i+8$L`-@auM1Yr>@xcS0w zz4-dodpED%O)_dCYlJ0-FMRcxKmY4rO^>Ez(fb(7`q2v~RxX|V;h(%TgZNv&`{L~C zyf7a%@!Q{h>+wr#v!@n+^tW%GSsXn2;^ptXe06&N;7eb9>hAvVt(QM~;bZ4dUp($> zrKpPwv#3&yr*SepzBYLIts4~N%!!q}pEF2ZPOEx4o%q9pp$+`#lV{(*dh_+a-TL?^ z9~qoG_0mt@J9}cGvod?--Hj|XU-;tVm?YEM@9rE5;Kug29@dvGuYU0AdyhYS(sr`- z^#ku&JQoYypZ)DGPtOfL`{gIc)AHW>e%{UAy>j#1>D9@>(fPBhE2oxk-`?ii`)McH z*xViMkEVx1HC7Y`bKOZD*6-|IxVRSmH1D`HDa5j$9FF!zz;f(tF)IDR&hX@5rWz0P znQnmKI3RPe&_9^QyB>i8i zBGwJhE_E^2g{7s<^*zruk%Z{6;kt_C($PWL@8zyA)vzg&H0x#!3&dcPltt6rIYZrq zG}3Zvn}(I4lO!|qvy|FlQ|FnndA7BCM1&4qEzQheFc{>DbU2>IvZ(-KuTzhzXej_R z5qI{-RRcSo#?IbT+!VfX&%#HnRaj*T>eNBfnE zPNt1#AE&;bxuc`fPZ;thNZ8w*M9&=ygQDXaDU6Fj?rrVagRICp0J3p!uP6#p=?|c) zYAd#x#>(TCWSwUW9tZHCjVmyHgasu30jVPmaC zS?YEc3m4|Pw>QRB=~I{WJGLy#L7tj2#6*peUOxjvWz+OJSwBnbgNX_B;)@Socy!5o zA0?c>xOV#Za<^x)j(+89&sj3Xj9WZ0N0(1b_9uxm-NjjxCo3F8byjh2`|#wY)w*hi zlRAV5Kpa{UH2{Gc$-8L=(&^&dLRUeW5F~=I_y{3J01RSO86_gGtBw#TTH5vsF1pp6< ziuj-d>jl{BgDNSDfB-QI08>OnM0#)pfwH!?C?hIFiV7AaA_4$nZ0)!V0*nqwkQFR| zdPAEbPO>i9!bj~9p2ojcP3Ab zd*bAh_KNTR)hp2lARz=QWAEb+fB4FkmtVSC6p4~5Yf}69&pz?WYga$Gde@;^M|Bz2 zI$3!7^pAh~=I+KmITckY<8v2Qr%nCZFW;N)PMpIC#HC+*{M4QGo%gQXGK2(7fY>y> zr!T&L^~V0r(V25g-Ci0zqqVzR2X{W$JT=JXPR?&_?ib_oi5D(U5B%<}Jq--1qrG7@ zt`Gn~V&Juf{zDg*Z+v)reSLrV*zE1Cy>jB%w)FmNjqP+F3m@xPN!oSE1@~Icb7ej$v_e zVKmp5raXCe8BDtK;m+~3+1}EOMPwf#G=n1PEDTO`@+b+-c8BB1>Rf*`9FGpibAy2{ zcBhj@qn@1a9iJJLbx2dw?G%T5N8KWG2`tQaR#q3UzH_(eC6;M*VSa6~nACcBQ01BN zRTGaU=hv3%xx9&WmZkz=bFgAg9Ge?XhDBnIJ-n($>lj;DkH*M8%p4n#!r|7qJJZcG zGh1Y;khmnzll{@CBvV$t^s+QJm>KlzrY^_R<)t}tI2kwnM2|gwu|HdYn%0&4uA+bx@>*KrEa8?5Li9ckW_zTPT2luWa54JHwCwjf zMdrvt)x_MmA}2M_%jc8KLQ@aA#ku3hAr-R3Ub|@~64Op5WLd)D?$PYbeA>%nHRTw{ zC5|Y>5>3vE!lkMtdCoqZJ98|m5hQ|!kc>?URX8do&L#xGdrq^^pzMaV<68XI)v zC_(WGYQUsvQZ*G3nj{Hc>Zn%i4Q`rkL*;=%Nyef*}S1R%0w#1*5>=5L*Qm8H-2)(V3BzKfV@v+D{3Sew>Ny5NKcc;us$^wc6 zApipyK#UrdBWX%j6j{I^k_a$Z00tpK07L;66r^^Cu9hMQ#diNok)t6a+&=ULQIrS- z4JBv{2!m<;zS>F*@&EShrTYxKm|@WeLk!wOT~=xaMY@ff|MCBr~=S#6VReq6V-a=Scjy@ zrgdWwHOgFO`-9v77;EYgGlC#zhz~z<5*mKt$@8;kmbW*LfRH0AsEN>9$anUqv2K6> zfHZ1~G`HH>KWf-VVQ>W@Yu6?DT(Pw?VIP!zQe@(Fp`Y17c61mtMrBUYgit$O%Ver4 zbMQ!#qzQ(Y_0ond1fN;%%?`li!=pp%k|J>-G-7S)QVfj;NnFQ)l)k1UO^pq{7Qige zM7XZK%d^dm{hL?sB&nHQnPKmnvJQc}-2!9ahyiq3R^CTzTsKQkot|TB4i9QlM#EWA zkU*9a8dR_~$9vm{U6=Lx`Di$`>BtexUr!EmtA~FC17(6>iNoLDQZHbaR zslAWWlE|d}ZaFP8XOg^_lpZzgzjTUS94p()QLcH)iqp;AmLx?NzDMx!L~R^+OKv`0?4z?W6s@@#^Y8ENgUPo@&3*AgJ$Z_pI;l*)Abu$=gzJ!otVFQZ7-Ddh0Ck!_m4L3?3_Ba*qa%=|K8o) z*+-u|^TG9v`*(LQU0h2F_rXV7r2Nd2=XMUJ@4R{Q%!#>kkDYw|^;_fp@e40pIyx#p zc=z_ga_{`Zr{DPHhf>E+eD1N^ckg|0m=q=pLy)HH*Q^fcjI$k zd@LPgKl#Cx#eVlwUwGuzS3kISXa6&wf2@)C^OxQ~xjgsiljmN4?b_b%;a7g+x&6cO z%RjsN_~qkIeC)#azVntJm;d0Od}ia`;rGA&=5rrA_wmm^_T9gHb-+tpOUw-oP6DR-Q|Ifcnt^I?4{ncOn^4iaTboJ}M_3ZJp zOaJTt@=}(YfBG*!|C1lS^XgBo|L#BhEHi&X`%OxKm6?B!SL2cdyhVImMp&e+DD5^3&&2(ZQtA9yu0_*R38A#O4^?Ut(zt`)Gjz;67$@1|PQK5E1ffQrdy|;Jl__9mf=G}YUey2Y>m`v-v z-ThN1jv?X3ovor%%rA5&)8_vD?Gq=Dsh|Q7DiLv%^*dW@rQs-TLJK>&vu zlmS2iMWD5?7?mPVDj%W>3J?+!MHWJ*#Gs5|6oC{36sbk^x5h_R6hsigD4HZmuj71O zS3XKxMvFkIb|>i2rLNOwaK=$WDpOus7?{=h^^L>a*dX320;o}=2n<5V3ZxH?UuFTd zfbB#Hv|WA}ZSm72pfO^W+sNKn>)LNX1=`P!MuLXG!6=I|i)G(UtTfz1{rg{f;)&-U z29rq;)fj;QA}ToNxT=V>Q)HcU$3$3^MF0_kk28ZlJn+{*``sQ)N}I&_L0Zgowzoz( z(ad~j|ES6>&MyxrOYhv>?{-apb$0u3JQ+_;tj}1E!Ex-BhW;2>T^7zTaarxfu`{ysLQEuLT3r|!KYVj8OD;Tl_SIM4uMfsAeDdMV{n3@zu03)2#OX)R zz5KIx!?b?kvrpXGI(p-KZ-4B`)0dyU@X|}~@9!O6dhGa(dq?m8^5!#7o#-wNe)ZA^ z3%%m$&pi6lPp|IX+WyLKKbz;-OMmn3r$2T1^drZ=|JSb-4nF<0kNxze4{p5i;Wz&A z7miqe`rThWesS%IPd@r5fBfSx9Dm~vzx39XJ6C>j{fl3Dy0bF(?LU6$?CQ)XzV@-d z{MO66ceeiEUwrk>?(na_^~$GSy!eT)J@@B-_VYVeZ~dcx`Xx^6pZ)vq9bXuH7?e`0V3<`QKilhX3jR@wa~bled2ISFis5KmQt8 z^X)%-`Qn+C-}uJoe)yk%ym5W~U;dB3bARjTufO@DFMi?ahhKR3+yC*0U6nulpMLAL zH}CxN2k-peKl@@fgMaqTmoA=N{q2A9x$phW8#ms(`TPI!Yi_>t!@qsAYmT5SwzWyv`?)6tbI=(o2;{5#08(Ukq z4$hul_H}so)w|Zy?8?lqUir`;RcB8x?r$Hx`SOj~ZfADBcm2KfL7qPI+}UziZQR&? z=-gUbq<61vTg7LeJYSB=o%P{dkxJy@&SdZ2Ve@3uG-0?`EicX*#aK!`ZhY-S(0V9- zC~;o6l)93pjE-%Fxo;#1LLRx%rVbPxdKVi8fLwEf#-%2)CNpW%L<4pbcp$#j_`^aiP&O$4`W56B?cEbf3I@e$eZQhv%Mnv^z*+;MJvt z7oT~w+v$PO_2d^zzIT4`-<P z8pXZM(mx7LVYpQnNr00SJ&g~71hm$KQPhCWVpQ#S`$e7^16iJ^_FBoK3MwO#s6v`| zqOvmPc^An9j+Sty+ZPoQn4KF~YgolOTv}Wp1f>USR|Oh z1R?=N00Lmb-+uN{>Gr{7h-91r;dJW1`q|6Vh1qw$^+qw-_Q4wC?Y@$ zg=mo$A}UI$y?$rsumAXmkDpt9@wZ<5^KbqXhtt3N`(J+NgN=7ydgqH@eX4)z*f;;f z50`TK`ak~CYj59v_1mv}{p-)qT{`jKzxku%z5KJk^U1&Y?%O*buK)c%{KDOx(JSA1 z?bDySJbU`sU;o)JPA_yn`SlmR_uV(go7-Ri#;0y?4`2JiJD>Q}BlD+Mzx%CUtoE}P zzxJ`0esbk#{r+cuBE`AJ@mqb53X(wHx3?s`t*e1!`E*=botoaiTQV5zu9qk@u_pS?(B~@ z_s>7J7Rlat@BYeMv3h>#!}soU-CTa=uI#<-4~Js!@6F z((=Uf{o4mC^Tq7(x%-<(^>Dg&YDpd4yS3Lz-16z!`}anEQXfA(+X(D#9Q6mTx6s?$ zoEqVU6EovsoE%ISRx{(=aCed>wwUh?k7};#nZ<6y;Ky~RNNko)Mm37|=hC`XU;0kp zficynu@=&9)>IK1wjHO&h!LLAl%M*d&>jWnFth#~iD=HrA#|5<^oroa9Anc{(oD zB%RE0(|9j=F9!qDahWDI&6BE(F>>C?P<1+)=6Rkb$+Rw2pwlUs{bXF_olfHHWIRQr zUZ?QfOslHf$*nchNlD=PgCh7aE$d#tunwogI!$bU(DjY4Yd;wDy8UcADLLTGeAgH_ zI-F!#(d)UNA0<6&dTCN8b28bGqF;21-Q*106JRb7K%C(oMD#K44z)<%gMBa$)3 zgvJZ2{+c%;0Awim0H8?3BFsuaX<`Eh0y4%5OOS|G4VvJiwuUgI5T(7odmjZ92vL!} z7X$#q654)~2sGYLr#`X+LM4O{ zW8fH~23F?4QJ69Mz#40>A|PI3U=NX5Tc`kwijoLhV-{By^In!Za!R74sBNV{9+0tXXQy&>)c!ViiRpBmk6F^$0DnTmVrl7)6MPhGMG#ixI5~>rA&u zt!V-`A!-m0(l(RuH=h3(xUA*y6Co(|C)GdygU_s^{piQIbt&xl)7-XXq$QXqpu`?^PWKtv)RBN08?DUc{hI-|-A{5IF#O>kd}ZO>@!&zU ztgE{gq*b;IjCgLA;EZ3TATEWys7Gd zkf*6c-}smnnL(PCB_%dXl2H4|Qgm~bIGt8$n&xR*)xPn*)9E;iqoXp(v!Zb0Ny$C0u@AUH29FB*CuHWzYvMI}|H`_yk;lU`) zvrdsr#+8V62i@rXbXs?Mg>`0lG&R-?21PTeCllZ87fEW44l4khnJqkr@zJE$>m<&N zj;7>nrlo-kau$c ztS6OC6PvkuTB%CbDL8UHZIUcY6H`v7k+JAx0$i1~wbmtxgb)I|Bn1%Pcw-GB#K<5< zK~-YyJp*uLi4nmP0y$J5VD%DXh#?9nAOeyVVFD&JO2!~KXM@0aQd5j3b&;hm8<*H5 zb(6Bv7(00pnWtryr)ieE;iwXk!JyOlW-|7@Zs8JpIGhr~>`Z4eZ6?EdZoZ(z?Cp#b zi}MRJ`-kJY@(XhVAUxPRDzcHXFQb?Tlt-irLxj{jCG`divzTw5qo5 z4;SV-%PX@xyOZJ3^wjZ%!F+N1_AUWjxO8m)pxWBlUt61q`aeHHHYjgkHxwWE`zW@Gu z>dfVbPBKaiK1)+Vs;X$nWSNc3wGVlb64G>BlBG1Ys1ST?Lw~~JL$ubSLK6ds8bYr! zEvw9Bh*DM+M@*6=#^~!N&of1;eL#gQPh$*aHSKn~h*&kXcquwrkT@OrqMMV2s%+Rx zuakO>qjA;gB%mgG6=g8MqES_VL87wyD3L{@1lGVY1|K4fDqs76O3_F5EGn#8dkK*} zvkC|YX7)h=prt?~XpDjegq2iPg~3JzA`*!f(I7Fj20%0DW=pFxX`TQQf*K_O5E2p~ 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≻jnZ5Z3~-?*McaBHa2WDQy{ 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 S8I-XA0000 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 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 Image transform(Image in, BiFunction 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 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 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 @@ 1.11.253 + + com.google.inject + guice + 3.0 + + diff --git a/src/main/java/guice/AppInjector.java b/src/main/java/guice/AppInjector.java new file mode 100644 index 0000000..fa9b01b --- /dev/null +++ b/src/main/java/guice/AppInjector.java @@ -0,0 +1,18 @@ +package guice; + +import com.google.inject.AbstractModule; + +/** + * Obviously google guice will not know which service to use, + * we have to configure it by extending AbstractModule abstract class + * and provide implementation for configure() method. + */ +public class AppInjector extends AbstractModule { + @Override protected void configure() { + //bind the service to implementation class + //bind(MessageService.class).to(EmailService.class); + + //bind MessageService to Facebook Message implementation + //bind(MessageService.class).to(FacebookService.class); + } +} diff --git a/src/main/java/guice/ClientApplication.java b/src/main/java/guice/ClientApplication.java new file mode 100644 index 0000000..474520f --- /dev/null +++ b/src/main/java/guice/ClientApplication.java @@ -0,0 +1,17 @@ +package guice; + +import com.google.inject.Guice; +import com.google.inject.Injector; + +/** + * created by stevesun on 10/11/18/. + */ +public class ClientApplication { + public static void main(String[] args) { + Injector injector = Guice.createInjector(new AppInjector()); + + MyApplication app = injector.getInstance(MyApplication.class); + + app.sendMessage("Hi Steve", "fishercoder@gmail.com"); + } +} diff --git a/src/main/java/guice/EmailService.java b/src/main/java/guice/EmailService.java new file mode 100644 index 0000000..91c89d7 --- /dev/null +++ b/src/main/java/guice/EmailService.java @@ -0,0 +1,25 @@ +package guice; + +import javax.inject.Singleton; + +/** + * EmailService is one of the implementation of MessageService. Notice that class is annotated with + * @Singleton annotation. + * + * Since service objects will be created through injector classes, this annotation is provided + * to let them know that the service classes should be singleton objects. + * + * Google Guice 3.0 added the support for JSR-330 and we can use annotations from + * com.google.inject + * or + * javax.inject package. + */ + +@Singleton +public class EmailService implements MessageService { + @Override public boolean sendMessage(String msg, String receipient) { + //some fancy code to send email + System.out.println("Email Message sent to " + receipient + " with message=" + msg); + return true; + } +} diff --git a/src/main/java/guice/FacebookService.java b/src/main/java/guice/FacebookService.java new file mode 100644 index 0000000..3721197 --- /dev/null +++ b/src/main/java/guice/FacebookService.java @@ -0,0 +1,12 @@ +package guice; + +/** + * created by stevesun on 10/11/18/. + */ +public class FacebookService implements MessageService { + @Override public boolean sendMessage(String msg, String receipient) { + //some complex code to send Facebook message + System.out.println("Message sent to Facebook user "+receipient+" with message="+msg); + return true; + } +} diff --git a/src/main/java/guice/HelloWorldInGuice.java b/src/main/java/guice/HelloWorldInGuice.java new file mode 100644 index 0000000..befbbcc --- /dev/null +++ b/src/main/java/guice/HelloWorldInGuice.java @@ -0,0 +1,10 @@ +package guice; + +/** + * created by stevesun on 10/11/18/. + */ +public class HelloWorldInGuice { + public static void main(String... args) { + System.out.println("Hello world in Guice!"); + } +} diff --git a/src/main/java/guice/MessageService.java b/src/main/java/guice/MessageService.java new file mode 100644 index 0000000..90df8ef --- /dev/null +++ b/src/main/java/guice/MessageService.java @@ -0,0 +1,8 @@ +package guice; + +/** + * created by stevesun on 10/11/18/. + */ +public interface MessageService { + boolean sendMessage(String msg, String receipient); +} diff --git a/src/main/java/guice/MockMessageService.java b/src/main/java/guice/MockMessageService.java new file mode 100644 index 0000000..1d890a7 --- /dev/null +++ b/src/main/java/guice/MockMessageService.java @@ -0,0 +1,10 @@ +package guice; + +/** + * created by stevesun on 10/11/18/. + */ +public class MockMessageService implements MessageService { + @Override public boolean sendMessage(String msg, String receipient) { + return true; + } +} diff --git a/src/main/java/guice/MyApplication.java b/src/main/java/guice/MyApplication.java new file mode 100644 index 0000000..ddd7e77 --- /dev/null +++ b/src/main/java/guice/MyApplication.java @@ -0,0 +1,27 @@ +package guice; + +import javax.inject.Inject; + +/** + * This is our application class that consumes the service looks like below. + */ +public class MyApplication { + private MessageService service; + + // constructor based injector + @Inject + public MyApplication(MessageService svc){ + this.service=svc; + } + + //setter method injector + //@Inject + //public void setService(MessageService svc) { + // this.service = svc; + //} + + public boolean sendMessage(String msg, String rec) { + //some business logic here + return service.sendMessage(msg, rec); + } +} diff --git a/src/test/guice/MyApplicationTest.java b/src/test/guice/MyApplicationTest.java new file mode 100644 index 0000000..8920606 --- /dev/null +++ b/src/test/guice/MyApplicationTest.java @@ -0,0 +1,37 @@ +package guice; + +import com.google.inject.AbstractModule; +import com.google.inject.Guice; +import com.google.inject.Injector; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class MyApplicationTest { + + private Injector injector; + + @Before + public void setUp() { + injector = Guice.createInjector(new AbstractModule() { + + @Override + protected void configure() { + bind(MessageService.class).to(MockMessageService.class); + } + }); + } + + @After + public void tearDown() { + injector = null; + } + + @Test + public void test() { + MyApplication appTest = injector.getInstance(MyApplication.class); + Assert.assertEquals(true, appTest.sendMessage("Hi Steve", "fishercoder@gmail.com")); + ; + } +} From 031ed8f6beeb156e8f2b52750e267d3798d224a4 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Mon, 15 Oct 2018 07:27:29 -0700 Subject: [PATCH 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 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 list = new ArrayList<>(); + list.stream() + .map(i -> i + 1); + System.out.println("Finished."); + } +} From 22ce43cc86058adece9c3bdf6951c59864d59af4 Mon Sep 17 00:00:00 2001 From: Steve Sun Date: Sat, 7 Sep 2019 18:27:49 -0700 Subject: [PATCH 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 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 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 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 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: + *

+ * Here, the TextEditor should not worry about SpellChecker implementation. + * The SpellChecker will be implemented independently and will be provided to the TextEditor at the time of TextEditor instantiation. + */ @Inject - public TextEditor(@Named("JDBC") String dbUrl) { - this.dbUrl = dbUrl; + public TextEditor(SpellChecker spellChecker) { + this.spellChecker = spellChecker; } - public void makeConnection() { - System.out.println(dbUrl); + public void makeSpellCheck() { + spellChecker.checkSpelling(); } -} +} \ No newline at end of file diff --git a/src/main/java/guice/relearn_2019_09/simple_binding_example/TextEditorModule.java b/src/main/java/guice/relearn_2019_09/simple_binding_example/TextEditorModule.java new file mode 100644 index 0000000..9b77dcd --- /dev/null +++ b/src/main/java/guice/relearn_2019_09/simple_binding_example/TextEditorModule.java @@ -0,0 +1,20 @@ +package guice.relearn_2019_09.simple_binding_example; + +import com.google.inject.AbstractModule; + +/** + * Dependency Injection is controlled by the Guice Bindings. + * Guice uses bindings to map object types to their actual implementations. + * These bindings are defined a module. + * A module is a collection of bindings as shown below − + * */ +public class TextEditorModule extends AbstractModule { + @Override + protected void configure() { + /* + * Bind SpellChecker binding to WinWordSpellChecker implementation + * whenever spellChecker dependency is used. + */ + bind(SpellChecker.class).to(WinWordSpellChecker.class); + } +} diff --git a/src/main/java/guice/relearn_2019_09/WinWordSpellChecker.java b/src/main/java/guice/relearn_2019_09/simple_binding_example/WinWordSpellChecker.java similarity index 77% rename from src/main/java/guice/relearn_2019_09/WinWordSpellChecker.java rename to src/main/java/guice/relearn_2019_09/simple_binding_example/WinWordSpellChecker.java index 8ab2652..cd841f0 100644 --- a/src/main/java/guice/relearn_2019_09/WinWordSpellChecker.java +++ b/src/main/java/guice/relearn_2019_09/simple_binding_example/WinWordSpellChecker.java @@ -1,4 +1,4 @@ -package guice.relearn_2019_09; +package guice.relearn_2019_09.simple_binding_example; public class WinWordSpellChecker implements SpellChecker { @Override From 58bf1680fa869828319a20331dfef9221be0c323 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Sun, 8 Sep 2019 09:36:47 -0700 Subject: [PATCH 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 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 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 { + @Override + public SpellChecker get() { + String dbUrl = "jdbc:mysql://localhost:5326/emp"; + String user = "user"; + int timeout = 100; + + SpellChecker SpellChecker = new SpellCheckerImpl(dbUrl, user, timeout); + return SpellChecker; + } +} From 502128a5fc959b39911f69cdfdee4111c5dea959 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Sun, 8 Sep 2019 12:53:14 -0700 Subject: [PATCH 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 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 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 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 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 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 incomingSetOne, Set incomingSetTwo, String incomingString) { + Set existingSetOne = ddbRecord.getSetOne(); + if (existingSetOne == null) { + if (!incomingSetOne.isEmpty()) { + ddbRecord.setSetOne(incomingSetOne); + ddbRecord.setSetOneCount(incomingSetOne.size()); + existingSetOne = incomingSetOne; + } + } else if (existingSetOne != null) { + if (incomingSetOne.isEmpty()) { + //remove this string from this set if it exists + existingSetOne.remove(incomingString); + int updatedSetOneCount = existingSetOne.size(); + ddbRecord.setSetOneCount(updatedSetOneCount); + if (updatedSetOneCount == 0) { + existingSetOne.add("N/A"); + } + ddbRecord.setSetOne(existingSetOne); + } else if (!incomingSetOne.isEmpty()) { + if (existingSetOne.contains("N/A")) { + existingSetOne.remove("N/A"); + } + //add this incoming set in + existingSetOne.addAll(incomingSetOne); + + ddbRecord.setSetOne(existingSetOne); + ddbRecord.setSetOneCount(existingSetOne.size()); + } + } + + Set existingSetTwo = ddbRecord.getSetTwo(); + if (existingSetTwo == null) { + if (!incomingSetTwo.isEmpty()) { + ddbRecord.setSetTwo(incomingSetTwo); + ddbRecord.setSetTwoCount(incomingSetTwo.size()); + existingSetTwo = incomingSetTwo; + } + } else if (existingSetTwo != null) { + if (incomingSetTwo.isEmpty()) { + //remove this string from this set if it exists + existingSetTwo.remove(incomingString); + int updatedSetTwoCount = existingSetTwo.size(); + ddbRecord.setSetTwoCount(updatedSetTwoCount); + if (updatedSetTwoCount == 0) { + existingSetTwo.add("N/A"); + } + ddbRecord.setSetTwo(existingSetTwo); + } else if (!incomingSetTwo.isEmpty()) { + if (existingSetTwo.contains("N/A")) { + existingSetTwo.remove("N/A"); + } + //add this incoming offer set in + existingSetTwo.addAll(incomingSetTwo); + + ddbRecord.setSetTwo(existingSetTwo); + ddbRecord.setSetTwoCount(existingSetTwo.size()); + } + } + + //do something w/ existingSetOne and existingSetTwo afterwards + } + + class DDBRecord { + private Set setOne; + private Set setTwo; + private int setOneCount; + private int setTwoCount; + + public Set getSetOne() { + return setOne; + } + + public void setSetOne(Set setOne) { + this.setOne = setOne; + } + + public void setSetOneCount(int count) { + this.setOneCount = count; + } + + public Set getSetTwo() { + return setTwo; + } + + public void setSetTwo(Set setTwo) { + this.setTwo = setTwo; + } + + public void setSetTwoCount(int count) { + this.setTwoCount = count; + } + } + +} From 5129e74da12acf045274389d84217217efde614c Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Mon, 23 Sep 2019 09:31:57 -0700 Subject: [PATCH 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 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 @@ 3.0 + + + com.google.collections + google-collections + 1.0 + + + + + com.google.inject + guice + LATEST + + + diff --git a/src/main/java/guice/relearn_2019_09/_8_already_configured_exception/PrivateModuleTest.java b/src/main/java/guice/relearn_2019_09/_8_already_configured_exception/PrivateModuleTest.java new file mode 100644 index 0000000..4cc0551 --- /dev/null +++ b/src/main/java/guice/relearn_2019_09/_8_already_configured_exception/PrivateModuleTest.java @@ -0,0 +1,554 @@ +package guice.relearn_2019_09._8_already_configured_exception; + +import static com.google.inject.name.Names.named; + +import com.google.inject.AbstractModule; +import com.google.inject.ConfigurationException; +import com.google.inject.CreationException; +import com.google.inject.Exposed; +import com.google.inject.Guice; +import com.google.inject.Inject; +import com.google.inject.Injector; +import com.google.inject.Key; +import com.google.inject.PrivateBinder; +import com.google.inject.PrivateModule; +import com.google.inject.Provider; +import com.google.inject.Provides; +import com.google.inject.name.Named; +import com.google.inject.name.Names; +import com.google.inject.spi.Dependency; +import com.google.inject.spi.ExposedBinding; +import com.google.inject.spi.PrivateElements; +import com.google.inject.util.Types; + +import junit.framework.TestCase; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +public class PrivateModuleTest extends TestCase { + + public void testBasicUsage() { + Injector injector = Guice.createInjector(new AbstractModule() { + @Override protected void configure() { + bind(String.class).annotatedWith(named("a")).toInstance("public"); + + install(new PrivateModule() { + @Override public void configure() { + bind(String.class).annotatedWith(named("b")).toInstance("i"); + + bind(AB.class).annotatedWith(named("one")).to(AB.class); + expose(AB.class).annotatedWith(named("one")); + } + }); + + install(new PrivateModule() { + @Override public void configure() { + bind(String.class).annotatedWith(named("b")).toInstance("ii"); + + bind(AB.class).annotatedWith(named("two")).to(AB.class); + expose(AB.class).annotatedWith(named("two")); + } + }); + } + }); + + AB ab1 = injector.getInstance(Key.get(AB.class, named("one"))); + assertEquals("public", ab1.a); + assertEquals("i", ab1.b); + + AB ab2 = injector.getInstance(Key.get(AB.class, named("two"))); + assertEquals("public", ab2.a); + assertEquals("ii", ab2.b); + } + + public void testWithoutPrivateModules() { + Injector injector = Guice.createInjector(new AbstractModule() { + @Override protected void configure() { + PrivateBinder bindA = binder().newPrivateBinder(); + bindA.bind(String.class).annotatedWith(named("a")).toInstance("i"); + bindA.expose(String.class).annotatedWith(named("a")); + bindA.bind(String.class).annotatedWith(named("c")).toInstance("private to A"); + + PrivateBinder bindB = binder().newPrivateBinder(); + bindB.bind(String.class).annotatedWith(named("b")).toInstance("ii"); + bindB.expose(String.class).annotatedWith(named("b")); + bindB.bind(String.class).annotatedWith(named("c")).toInstance("private to B"); + } + }); + + assertEquals("i", injector.getInstance(Key.get(String.class, named("a")))); + assertEquals("ii", injector.getInstance(Key.get(String.class, named("b")))); + } + + public void testMisplacedExposedAnnotation() { + try { + Guice.createInjector(new AbstractModule() { + @Override protected void configure() {} + + @Provides + @Exposed + String provideString() { + return "i"; + } + }); + fail(); + } catch (CreationException expected) { + System.out.println(expected.getMessage() + "Cannot expose java.lang.String on a standard binder. " + + "Exposed bindings are only applicable to private binders." + + " at " + PrivateModuleTest.class.getName() + "provideString(PrivateModuleTest.java:"); + } + } + + public void testMisplacedExposeStatement() { + try { + Guice.createInjector(new AbstractModule() { + @Override protected void configure() { + ((PrivateBinder) binder()).expose(String.class).annotatedWith(named("a")); + } + }); + fail(); + } catch (CreationException expected) { + System.out.println(expected.getMessage() + "Cannot expose java.lang.String on a standard binder. " + + "Exposed bindings are only applicable to private binders." + + " at " + PrivateModuleTest.class.getName() + getClass()); + } + } + + public void testPrivateModulesAndProvidesMethods() { + Injector injector = Guice.createInjector(new AbstractModule() { + @Override protected void configure() { + install(new PrivateModule() { + @Override public void configure() { + expose(String.class).annotatedWith(named("a")); + } + + @Provides @Named("a") String providePublicA() { + return "i"; + } + + @Provides @Named("b") String providePrivateB() { + return "private"; + } + }); + + install(new PrivateModule() { + @Override public void configure() {} + + @Provides @Named("c") String providePrivateC() { + return "private"; + } + + @Provides @Exposed @Named("d") String providePublicD() { + return "ii"; + } + }); + } + }); + + assertEquals("i", injector.getInstance(Key.get(String.class, named("a")))); + + try { + injector.getInstance(Key.get(String.class, named("b"))); + fail(); + } catch(ConfigurationException expected) { + } + + try { + injector.getInstance(Key.get(String.class, named("c"))); + fail(); + } catch(ConfigurationException expected) { + } + + assertEquals("ii", injector.getInstance(Key.get(String.class, named("d")))); + } + + public void testCannotBindAKeyExportedByASibling() { + try { + Guice.createInjector(new AbstractModule() { + @Override protected void configure() { + install(new PrivateModule() { + @Override public void configure() { + bind(String.class).toInstance("public"); + expose(String.class); + } + }); + + install(new PrivateModule() { + @Override public void configure() { + bind(String.class).toInstance("private"); + } + }); + } + }); + fail(); + } catch (CreationException expected) { +// assertContains(expected.getMessage(), +// "A binding to java.lang.String was already configured at ", +// getClass().getName(), getDeclaringSourcePart(getClass()), +// " at " + getClass().getName(), getDeclaringSourcePart(getClass())); + } + } + + public void testExposeButNoBind() { + try { + Guice.createInjector(new AbstractModule() { + @Override protected void configure() { + bind(String.class).annotatedWith(named("a")).toInstance("a"); + bind(String.class).annotatedWith(named("b")).toInstance("b"); + + install(new PrivateModule() { + @Override public void configure() { + expose(AB.class); + } + }); + } + }); + fail("AB was exposed but not bound"); + } catch (CreationException expected) { +// assertContains(expected.getMessage(), +// "Could not expose() " + AB.class.getName() + ", it must be explicitly bound", +// getDeclaringSourcePart(getClass())); + } + } + + /** + * Ensure that when we've got errors in different private modules, Guice presents all errors + * in a unified message. + */ + public void testMessagesFromPrivateModulesAreNicelyIntegrated() { + try { + Guice.createInjector( + new PrivateModule() { + @Override public void configure() { + bind(C.class); + } + }, + new PrivateModule() { + @Override public void configure() { + bind(AB.class); + } + } + ); + fail(); + } catch (CreationException expected) { +// assertContains(expected.getMessage(), +// "1) No implementation for " + C.class.getName() + " was bound.", +// "at " + getClass().getName(), getDeclaringSourcePart(getClass()), +// "2) No implementation for " + String.class.getName(), "Named(value=a) was bound.", +// "for field at " + AB.class.getName() + ".a(PrivateModuleTest.java:", +// "3) No implementation for " + String.class.getName(), "Named(value=b) was bound.", +// "for field at " + AB.class.getName() + ".b(PrivateModuleTest.java:", +// "3 errors"); + } + } + + public void testNestedPrivateInjectors() { + Injector injector = Guice.createInjector(new PrivateModule() { + @Override public void configure() { + expose(String.class); + + install(new PrivateModule() { + @Override public void configure() { + bind(String.class).toInstance("nested"); + expose(String.class); + } + }); + } + }); + + assertEquals("nested", injector.getInstance(String.class)); + } + + public void testInstallingRegularModulesFromPrivateModules() { + Injector injector = Guice.createInjector(new PrivateModule() { + @Override public void configure() { + expose(String.class); + + install(new AbstractModule() { + @Override protected void configure() { + bind(String.class).toInstance("nested"); + } + }); + } + }); + + assertEquals("nested", injector.getInstance(String.class)); + } + + public void testNestedPrivateModulesWithSomeKeysUnexposed() { + Injector injector = Guice.createInjector(new PrivateModule() { + @Override public void configure() { + bind(String.class).annotatedWith(named("bound outer, exposed outer")).toInstance("boeo"); + expose(String.class).annotatedWith(named("bound outer, exposed outer")); + bind(String.class).annotatedWith(named("bound outer, exposed none")).toInstance("boen"); + expose(String.class).annotatedWith(named("bound inner, exposed both")); + + install(new PrivateModule() { + @Override public void configure() { + bind(String.class).annotatedWith(named("bound inner, exposed both")).toInstance("bieb"); + expose(String.class).annotatedWith(named("bound inner, exposed both")); + bind(String.class).annotatedWith(named("bound inner, exposed none")).toInstance("bien"); + } + }); + } + }); + + assertEquals("boeo", + injector.getInstance(Key.get(String.class, named("bound outer, exposed outer")))); + assertEquals("bieb", + injector.getInstance(Key.get(String.class, named("bound inner, exposed both")))); + + try { + injector.getInstance(Key.get(String.class, named("bound outer, exposed none"))); + fail(); + } catch (ConfigurationException expected) { + } + + try { + injector.getInstance(Key.get(String.class, named("bound inner, exposed none"))); + fail(); + } catch (ConfigurationException expected) { + } + } + + public void testDependenciesBetweenPrivateAndPublic() { + Injector injector = Guice.createInjector( + new PrivateModule() { + @Override protected void configure() {} + + @Provides @Exposed @Named("a") String provideA() { + return "A"; + } + + @Provides @Exposed @Named("abc") String provideAbc(@Named("ab") String ab) { + return ab + "C"; + } + }, + new AbstractModule() { + @Override protected void configure() {} + + @Provides @Named("ab") String provideAb(@Named("a") String a) { + return a + "B"; + } + + @Provides @Named("abcd") String provideAbcd(@Named("abc") String abc) { + return abc + "D"; + } + } + ); + + assertEquals("ABCD", injector.getInstance(Key.get(String.class, named("abcd")))); + } + + public void testDependenciesBetweenPrivateAndPublicWithPublicEagerSingleton() { + Injector injector = Guice.createInjector( + new PrivateModule() { + @Override protected void configure() {} + + @Provides @Exposed @Named("a") String provideA() { + return "A"; + } + + @Provides @Exposed @Named("abc") String provideAbc(@Named("ab") String ab) { + return ab + "C"; + } + }, + new AbstractModule() { + @Override protected void configure() { + bind(String.class).annotatedWith(named("abcde")).toProvider(new Provider() { + @Inject @Named("abcd") String abcd; + + public String get() { + return abcd + "E"; + } + }).asEagerSingleton(); + } + + @Provides @Named("ab") String provideAb(@Named("a") String a) { + return a + "B"; + } + + @Provides @Named("abcd") String provideAbcd(@Named("abc") String abc) { + return abc + "D"; + } + } + ); + + assertEquals("ABCDE", injector.getInstance(Key.get(String.class, named("abcde")))); + } + + public void testDependenciesBetweenPrivateAndPublicWithPrivateEagerSingleton() { + Injector injector = Guice.createInjector( + new AbstractModule() { + @Override protected void configure() {} + + @Provides @Named("ab") String provideAb(@Named("a") String a) { + return a + "B"; + } + + @Provides @Named("abcd") String provideAbcd(@Named("abc") String abc) { + return abc + "D"; + } + }, + new PrivateModule() { + @Override protected void configure() { + bind(String.class).annotatedWith(named("abcde")).toProvider(new Provider() { + @Inject @Named("abcd") String abcd; + + public String get() { + return abcd + "E"; + } + }).asEagerSingleton(); + expose(String.class).annotatedWith(named("abcde")); + } + + @Provides @Exposed @Named("a") String provideA() { + return "A"; + } + + @Provides @Exposed @Named("abc") String provideAbc(@Named("ab") String ab) { + return ab + "C"; + } + } + ); + + assertEquals("ABCDE", injector.getInstance(Key.get(String.class, named("abcde")))); + } + + static class AB { + @Inject @Named("a") String a; + @Inject @Named("b") String b; + } + + interface C {} + + public void testSpiAccess() { + Injector injector = Guice.createInjector(new PrivateModule() { + @Override public void configure() { + bind(String.class).annotatedWith(named("a")).toInstance("private"); + bind(String.class).annotatedWith(named("b")).toInstance("exposed"); + expose(String.class).annotatedWith(named("b")); + } + }); + + ExposedBinding binding + = (ExposedBinding) injector.getBinding(Key.get(String.class, Names.named("b"))); +// assertEquals(ImmutableSet..", +// "It was already configured on one or more child injectors or private modules", +// "bound at " + FailingPrivateModule.class.getName() + ".configure(", +// asModuleChain(ManyPrivateModules.class, FailingPrivateModule.class), +// "bound at " + SecondFailingPrivateModule.class.getName() + ".configure(", +// asModuleChain(ManyPrivateModules.class, SecondFailingPrivateModule.class), +// "If it was in a PrivateModule, did you forget to expose the binding?", +// "while locating com.google.inject.Provider"); + } + } + + public void testParentBindingToPrivateJitBinding() { + Injector injector = Guice.createInjector(new ManyPrivateModules()); + try { + injector.getBinding(PrivateFoo.class); + fail(); + } catch(ConfigurationException expected) { + assertEquals(1, expected.getErrorMessages().size()); +// assertContains(expected.toString(), +// "Unable to create binding for " + PrivateFoo.class.getName(), +// "It was already configured on one or more child injectors or private modules", +// "(bound by a just-in-time binding)", +// "If it was in a PrivateModule, did you forget to expose the binding?", +// "while locating " + PrivateFoo.class.getName()); + } + } + + private static class FailingModule extends AbstractModule { + @Override protected void configure() { + bind(Collection.class).to(List.class); + install(new ManyPrivateModules()); + } + } + + private static class ManyPrivateModules extends AbstractModule { + @Override protected void configure() { + // make sure duplicate sources are collapsed + install(new FailingPrivateModule()); + install(new FailingPrivateModule()); + // but additional sources are listed + install(new SecondFailingPrivateModule()); + } + } + + private static class FailingPrivateModule extends PrivateModule { + @Override protected void configure() { + bind(List.class).toInstance(new ArrayList()); + + // Add the Provider binding, created just-in-time, + // to make sure our linked JIT bindings have the correct source. + getProvider(Key.get(Types.providerOf(List.class))); + + // Request a JIT binding for PrivateFoo, which can only + // be created in the private module because it depends + // on List. + getProvider(PrivateFoo.class); + } + } + + /** A second class, so we can see another name in the source list. */ + private static class SecondFailingPrivateModule extends PrivateModule { + @Override protected void configure() { + bind(List.class).toInstance(new ArrayList()); + + // Add the Provider binding, created just-in-time, + // to make sure our linked JIT bindings have the correct source. + getProvider(Key.get(Types.providerOf(List.class))); + + // Request a JIT binding for PrivateFoo, which can only + // be created in the private module because it depends + // on List. + getProvider(PrivateFoo.class); + } + } + + private static class PrivateFoo { + @Inject List list; + } +} diff --git a/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/AmazonDynamoDB.java b/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/AmazonDynamoDB.java new file mode 100644 index 0000000..e489c6e --- /dev/null +++ b/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/AmazonDynamoDB.java @@ -0,0 +1,14 @@ +package guice.relearn_2019_09._9_inject_the_same_object_in_two_modules; + +public class AmazonDynamoDB { + /** + * This is a dummy class since AWS DynamoDB Maven depdency cannot be resolved in my local. + */ + private final String awsRegion; + private final String ddbEndPoint; + + public AmazonDynamoDB(String awsRegion, String ddbEndPoint) { + this.awsRegion = awsRegion; + this.ddbEndPoint = ddbEndPoint; + } +} diff --git a/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/ClassA.java b/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/ClassA.java new file mode 100644 index 0000000..54cb795 --- /dev/null +++ b/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/ClassA.java @@ -0,0 +1,10 @@ +package guice.relearn_2019_09._9_inject_the_same_object_in_two_modules; + +import com.google.inject.Inject; +import lombok.AllArgsConstructor; + +@AllArgsConstructor(onConstructor = @__(@Inject)) +public class ClassA { + private final CustomerDbDao customerDbDao; + private static final String message = "This is from ClassA!"; +} diff --git a/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/ClassB.java b/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/ClassB.java new file mode 100644 index 0000000..4e28135 --- /dev/null +++ b/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/ClassB.java @@ -0,0 +1,10 @@ +package guice.relearn_2019_09._9_inject_the_same_object_in_two_modules; + +import com.google.inject.Inject; +import lombok.AllArgsConstructor; + +@AllArgsConstructor(onConstructor = @__(@Inject)) +public class ClassB { + private final CustomerDbDao customerDbDao; + private static final String message = "This is from ClassB!"; +} diff --git a/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/CustomerDbDao.java b/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/CustomerDbDao.java new file mode 100644 index 0000000..311cca0 --- /dev/null +++ b/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/CustomerDbDao.java @@ -0,0 +1,19 @@ +package guice.relearn_2019_09._9_inject_the_same_object_in_two_modules; + +import com.google.inject.Inject; +import com.google.inject.name.Named; + +public class CustomerDbDao { + public static final String CUSTOMER_DDB = "Customer.DDB"; + + private final DynamoDBMapper dynamoDBMapper; + + @Inject + public CustomerDbDao(@Named(CUSTOMER_DDB) DynamoDBMapper dynamoDBMapper) { + this.dynamoDBMapper = dynamoDBMapper; + } + + public void work() { + System.out.println("CustomerDbDao object is talking to Amazon DynamoDB and doing its work!"); + } +} diff --git a/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/DynamoDBMapper.java b/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/DynamoDBMapper.java new file mode 100644 index 0000000..9deb89d --- /dev/null +++ b/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/DynamoDBMapper.java @@ -0,0 +1,13 @@ +package guice.relearn_2019_09._9_inject_the_same_object_in_two_modules; + +public class DynamoDBMapper { + /** + * This is a dummy class since AWS DynamoDB Maven depdency cannot be resolved in my local. + */ + + private final AmazonDynamoDB dynamodb; + + public DynamoDBMapper(AmazonDynamoDB dynamodb) { + this.dynamodb = dynamodb; + } +} diff --git a/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/MainApp.java b/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/MainApp.java new file mode 100644 index 0000000..5e87ba5 --- /dev/null +++ b/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/MainApp.java @@ -0,0 +1,20 @@ +package guice.relearn_2019_09._9_inject_the_same_object_in_two_modules; + +import com.google.inject.Guice; +import com.google.inject.Injector; + +public class MainApp { + + public static void main(String... args) { + try { + Injector injector = Guice.createInjector(new WorkersModule()); + System.out.println("created injector: " + injector); + WorkersRunner workersRunner = injector.getInstance(WorkersRunner.class); + System.out.println("got workersRunner: " + workersRunner); + workersRunner.start(); + workersRunner.shutdown(); + } catch (Exception e) { + System.out.println("caught exception, e: " + e); + } + } +} diff --git a/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/Worker.java b/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/Worker.java new file mode 100644 index 0000000..72eefb7 --- /dev/null +++ b/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/Worker.java @@ -0,0 +1,7 @@ +package guice.relearn_2019_09._9_inject_the_same_object_in_two_modules; + +public interface Worker { + void start(); + + void shutdown(); +} diff --git a/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/Worker1.java b/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/Worker1.java new file mode 100644 index 0000000..cc44d66 --- /dev/null +++ b/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/Worker1.java @@ -0,0 +1,26 @@ +package guice.relearn_2019_09._9_inject_the_same_object_in_two_modules; + +import com.google.inject.Inject; +import com.google.inject.name.Named; + +import static guice.relearn_2019_09._9_inject_the_same_object_in_two_modules.Worker1Module.WORKER1; + +public class Worker1 implements Worker { + private final CustomerDbDao customerDbDao; + + @Inject + public Worker1(@Named(WORKER1) CustomerDbDao customerDbDao) { + this.customerDbDao = customerDbDao; + } + + @Override + public void start() { + System.out.println("Worker1 started working!"); + } + + @Override + public void shutdown() { + System.out.println("Worker1 has shut down!"); + } + +} diff --git a/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/Worker1Module.java b/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/Worker1Module.java new file mode 100644 index 0000000..d2ef13e --- /dev/null +++ b/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/Worker1Module.java @@ -0,0 +1,47 @@ +package guice.relearn_2019_09._9_inject_the_same_object_in_two_modules; + +import com.google.inject.PrivateModule; +import com.google.inject.Provides; +import com.google.inject.Singleton; +import com.google.inject.multibindings.Multibinder; +import com.google.inject.name.Named; +import com.google.inject.name.Names; + +import static guice.relearn_2019_09._9_inject_the_same_object_in_two_modules.CustomerDbDao.CUSTOMER_DDB; + +public class Worker1Module extends PrivateModule { + + public static final String WORKER1 = "Worker1"; + private static final String DDB_END_POINT = "dynamodb.us-west-2.amazonaws.com"; + private static final String AWS_REGION = "us-west-2"; + + @Override + protected void configure() { + final Multibinder multibinder = Multibinder.newSetBinder(binder(), Worker.class); + multibinder.addBinding().to(Worker1.class); + + bind(String.class).annotatedWith(Names.named(AWS_REGION)).toInstance("cool"); + bind(String.class).annotatedWith(Names.named(DDB_END_POINT)).toInstance("cool1"); + } + + @Provides + @Singleton + @Named(WORKER1) + public CustomerDbDao providesCustomerDbDao(@Named(CUSTOMER_DDB) DynamoDBMapper dynamoDBMapper) { + return new CustomerDbDao(dynamoDBMapper); + } + + @Provides + @Singleton + @Named(CUSTOMER_DDB) + public DynamoDBMapper provideDynamoDBMapper(@Named(CUSTOMER_DDB) AmazonDynamoDB dynamodb) { + return new DynamoDBMapper(dynamodb); + } + + @Provides + @Singleton + @Named(CUSTOMER_DDB) + public AmazonDynamoDB provideDynamoDBClient(final @Named(AWS_REGION) String awsRegion, final @Named(DDB_END_POINT) String ddbEndPoint) { + return new AmazonDynamoDB(awsRegion, ddbEndPoint); + } +} diff --git a/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/Worker2.java b/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/Worker2.java new file mode 100644 index 0000000..78ef7bf --- /dev/null +++ b/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/Worker2.java @@ -0,0 +1,23 @@ +package guice.relearn_2019_09._9_inject_the_same_object_in_two_modules; + +import com.google.inject.Inject; +import com.google.inject.name.Named; + +public class Worker2 implements Worker { + private final CustomerDbDao customerDbDao; + + @Inject + public Worker2(@Named("Worker2") CustomerDbDao customerDbDao) { + this.customerDbDao = customerDbDao; + } + + @Override + public void start() { + System.out.println("Worker2 started working!"); + } + + @Override + public void shutdown() { + System.out.println("Worker2 has shut down!"); + } +} diff --git a/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/Worker2Module.java b/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/Worker2Module.java new file mode 100644 index 0000000..473a041 --- /dev/null +++ b/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/Worker2Module.java @@ -0,0 +1,46 @@ +package guice.relearn_2019_09._9_inject_the_same_object_in_two_modules; + +import com.google.inject.PrivateModule; +import com.google.inject.Provides; +import com.google.inject.Singleton; +import com.google.inject.multibindings.Multibinder; +import com.google.inject.name.Named; +import com.google.inject.name.Names; + +import static guice.relearn_2019_09._9_inject_the_same_object_in_two_modules.CustomerDbDao.CUSTOMER_DDB; + +public class Worker2Module extends PrivateModule { + + public static final String WORKER2 = "Worker2"; + private static final String DDB_END_POINT = "dynamodb.us-west-2.amazonaws.com"; + private static final String AWS_REGION = "us-west-2"; + + @Override + protected void configure() { +// final Multibinder multibinder = Multibinder.newSetBinder(binder(), Worker.class); +// multibinder.addBinding().to(Worker2.class); +// bind(String.class).annotatedWith(Names.named(AWS_REGION)).toInstance("cool"); +// bind(String.class).annotatedWith(Names.named(DDB_END_POINT)).toInstance("cool1"); + } + + @Provides + @Singleton + @Named(WORKER2) + public CustomerDbDao providesCustomerDbDao(@Named(CUSTOMER_DDB) DynamoDBMapper dynamoDBMapper) { + return new CustomerDbDao(dynamoDBMapper); + } + + @Provides + @Singleton + @Named(CUSTOMER_DDB) + public DynamoDBMapper provideDynamoDBMapper(@Named(CUSTOMER_DDB) AmazonDynamoDB dynamodb) { + return new DynamoDBMapper(dynamodb); + } + + @Provides + @Singleton + @Named(CUSTOMER_DDB) + public AmazonDynamoDB provideDynamoDBClient(final @Named(AWS_REGION) String awsRegion, final @Named(DDB_END_POINT) String ddbEndPoint) { + return new AmazonDynamoDB(awsRegion, ddbEndPoint); + } +} diff --git a/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/WorkersModule.java b/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/WorkersModule.java new file mode 100644 index 0000000..e3213b0 --- /dev/null +++ b/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/WorkersModule.java @@ -0,0 +1,12 @@ +package guice.relearn_2019_09._9_inject_the_same_object_in_two_modules; + +import com.google.inject.AbstractModule; + +public class WorkersModule extends AbstractModule { + + @Override + protected void configure() { + install(new Worker1Module()); +// install(new Worker2Module()); + } +} diff --git a/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/WorkersRunner.java b/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/WorkersRunner.java new file mode 100644 index 0000000..898ed33 --- /dev/null +++ b/src/main/java/guice/relearn_2019_09/_9_inject_the_same_object_in_two_modules/WorkersRunner.java @@ -0,0 +1,38 @@ +package guice.relearn_2019_09._9_inject_the_same_object_in_two_modules; + +import lombok.extern.slf4j.Slf4j; +import lombok.val; + +import javax.inject.Inject; +import java.util.Set; +import java.util.stream.Collectors; + +@Slf4j +public class WorkersRunner { + + @Inject + private Set workers; + + public void start() { + log.info("Starting up Background Workers: " + workers.stream() + .map((w) -> w.getClass().getSimpleName()) + .collect(Collectors.joining(","))); + + val now = System.currentTimeMillis(); + + workers.forEach((w) -> { + log.info("Starting up " + w.getClass().getName() + "..."); + w.start(); + log.info("Start up took " + (System.currentTimeMillis() - now) + " ms"); + }); + } + + /** + * Shutdown workers gracefully + */ + public void shutdown() { + workers.forEach((w) -> { + w.shutdown(); + }); + } +} From beea7f5a0a3c702002e84e733c42f8b1096d8a29 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Mon, 18 Nov 2019 08:56:39 -0800 Subject: [PATCH 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 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 @@ org.projectlombok lombok - 1.16.12 + 1.18.2 provided From 58a76df8fc784239eb9481ffc3ac6d19846832d0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Jul 2020 17:41:40 +0000 Subject: [PATCH 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] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index faa1ff1..f0f5123 100644 --- a/pom.xml +++ b/pom.xml @@ -31,7 +31,7 @@ org.apache.logging.log4j log4j-core - 2.7 + 2.13.2 From 06066bd785d55a8a553e224e353244de29b5d595 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 12 Oct 2020 17:58:42 +0000 Subject: [PATCH 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] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index f0f5123..1d44c89 100644 --- a/pom.xml +++ b/pom.xml @@ -44,7 +44,7 @@ junit junit - 4.11 + 4.13.1 From 3154ae30d2827c1d39309c510dc5bee42633a2f4 Mon Sep 17 00:00:00 2001 From: Steve Sun Date: Mon, 17 May 2021 11:47:53 -0700 Subject: [PATCH 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 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 @@ 1.11.253 + + + org.apache.spark + spark-core_2.12 + 3.1.1 + + + + org.apache.spark + spark-sql_2.12 + 3.0.1 + provided + + com.google.inject guice diff --git a/src/main/java/java8_for_the_really_impatient/Chapter3.java b/src/main/java/java8_for_the_really_impatient/Chapter3.java deleted file mode 100644 index b196363..0000000 --- a/src/main/java/java8_for_the_really_impatient/Chapter3.java +++ /dev/null @@ -1,51 +0,0 @@ -package java8_for_the_really_impatient; - -import java.util.function.BiFunction; -import javafx.application.Application; -import javafx.scene.Scene; -import javafx.scene.image.Image; -import javafx.scene.image.ImageView; -import javafx.scene.image.WritableImage; -import javafx.scene.layout.HBox; -import javafx.scene.paint.Color; -import javafx.stage.Stage; - -public class Chapter3 extends Application { - - /** - * 3.4 Returning functions instead of just simple values in Java - * - * Exercise 6 - */ - public static Image transform(Image in, BiFunction f, T arg) { - int width = (int) in.getWidth(); - int height = (int) in.getHeight(); - WritableImage out = new WritableImage(width, height); - for (int x = 0; x < width; x++) { - for (int y = 0; y < height; y++) { - out.getPixelWriter().setColor(x, y, - f.apply(in.getPixelReader().getColor(x, y), arg)); - } - } - return out; - } - - @Override - public void start(Stage stage) throws Exception { - Image image = new Image("queen-mary.png"); - Image newImage = transform(image, - (c, factor) -> c.deriveColor(0, 1, factor, 1), 0.05 - ); - stage.setScene(new Scene(new HBox(new ImageView(image), new ImageView(newImage)))); - stage.show(); - } - - - public static void main(String... args) { - Application.launch(args); - } - - - /** 3.5 Composition: saves the storage of an intermediate stage. */ - -} diff --git a/src/main/java/sparkExamples/Input1.txt b/src/main/java/sparkExamples/Input1.txt new file mode 100644 index 0000000..42f3bbc --- /dev/null +++ b/src/main/java/sparkExamples/Input1.txt @@ -0,0 +1,5 @@ +A wonderful king is Hadoop. +The elephant plays well with Sqoop. +But what helps him to thrive +Are Impala, and Hive, +And HDFS in the group. \ No newline at end of file diff --git a/src/main/java/sparkExamples/SparkExample1.java b/src/main/java/sparkExamples/SparkExample1.java new file mode 100644 index 0000000..4281c0b --- /dev/null +++ b/src/main/java/sparkExamples/SparkExample1.java @@ -0,0 +1,44 @@ +package sparkExamples; + +import org.apache.spark.api.java.JavaPairRDD; +import org.apache.spark.api.java.JavaRDD; +import org.apache.spark.sql.SparkSession; +import scala.Tuple2; + +import java.util.Arrays; +import java.util.regex.Pattern; + +public class SparkExample1 { + /** + * How to run this program: + * 1. mvn compile + * 2. mvn exec:java -Dexec.mainClass=sparkExamples.SparkExample1 -Dexec.args="sparkExamples/File1.txt sparkExamples/Output1.txt" + *

+ * TODO: right now, it throws java.lang.NoClassDefFoundError: org/apache/spark/sql/SparkSession, fix it. + */ + + private static final Pattern SPACE = Pattern.compile(" "); + + public static void main(String[] args) { + System.out.println("Hello world!"); + System.out.println("args.length:" + args.length); + if (args.length < 2) { + System.err.println("Usage: JavaWordCount "); + System.exit(1); + } + + SparkSession spark = SparkSession + .builder() + .appName("SparkJob") + .getOrCreate(); + + JavaRDD textFile = spark.read().textFile(args[0]).toJavaRDD(); + + JavaPairRDD counts = textFile + .flatMap(s -> Arrays.asList(SPACE.split(s)).iterator()) + .mapToPair(s -> new Tuple2<>(s, 1)) + .reduceByKey((a, b) -> a + b); + + counts.saveAsTextFile(args[1]); + } +} From 2a366ec27cbd06f2bfe4353baf7a10755a6e2990 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Tue, 18 May 2021 09:50:45 -0700 Subject: [PATCH 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 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 @@ org.apache.spark spark-sql_2.12 3.0.1 - provided diff --git a/src/main/java/sparkExamples/SparkExample1.java b/src/main/java/sparkExamples/SparkExample1.java index 4281c0b..61d64ac 100644 --- a/src/main/java/sparkExamples/SparkExample1.java +++ b/src/main/java/sparkExamples/SparkExample1.java @@ -11,10 +11,7 @@ public class SparkExample1 { /** * How to run this program: - * 1. mvn compile - * 2. mvn exec:java -Dexec.mainClass=sparkExamples.SparkExample1 -Dexec.args="sparkExamples/File1.txt sparkExamples/Output1.txt" - *

- * TODO: right now, it throws java.lang.NoClassDefFoundError: org/apache/spark/sql/SparkSession, fix it. + * mvn compile && mvn exec:java -Dexec.mainClass=sparkExamples.SparkExample1 -Dexec.args="sparkExamples/File1.txt sparkExamples/Output1.txt" */ private static final Pattern SPACE = Pattern.compile(" "); @@ -26,6 +23,7 @@ public static void main(String[] args) { System.err.println("Usage: JavaWordCount "); System.exit(1); } + System.out.println("args.[0]:" + args[0] + ", args[1]: " + args[1]); SparkSession spark = SparkSession .builder() From 79fc9fa71b66e227c34de4f2ca77d20720c11b27 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Tue, 18 May 2021 10:25:00 -0700 Subject: [PATCH 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 textFile = spark.read().textFile(args[0]).toJavaRDD(); From 6c5a27ec5085e3135e5b0320dbf466a61a392b5a Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Tue, 18 May 2021 10:35:36 -0700 Subject: [PATCH 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 textFile = spark.read().textFile(args[0]).toJavaRDD(); - - JavaPairRDD counts = textFile - .flatMap(s -> Arrays.asList(SPACE.split(s)).iterator()) - .mapToPair(s -> new Tuple2<>(s, 1)) - .reduceByKey((a, b) -> a + b); - - counts.saveAsTextFile(args[1]); + try { + SparkSession spark = SparkSession + .builder() + .appName("SparkJob") + .config("spark.master", "local") + .getOrCreate(); + System.out.println("SparkSession is initated."); + + JavaRDD textFile = spark.read().textFile(args[0]).toJavaRDD(); + System.out.println("Finished reading this textFile: " + args[0]); + + JavaPairRDD counts = textFile + .flatMap(s -> Arrays.asList(SPACE.split(s)).iterator()) + .mapToPair(s -> new Tuple2<>(s, 1)) + .reduceByKey((a, b) -> a + b); + System.out.println("Finished doing MapReduce option on this textFile: " + args[0]); + + counts.saveAsTextFile(args[1]); + System.out.println("Finished saving output to this textFile: " + args[1]); + } catch (Exception e) { + System.out.println("Caught exception when processing: " + e); + } } } From 3a39f9e35677ff490d9cfffa8eb999e2893713ee Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Tue, 18 May 2021 11:23:30 -0700 Subject: [PATCH 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 list = new ArrayList<>(n); + for (int i = 0; i < n; i++) { + list.add(i); + } + System.out.println("Got list.size() is: " + list.size()); + + JavaRDD dataSet = jsc.parallelize(list, slices); + System.out.println("dataSet.count() is: " + dataSet.count()); + + int count = dataSet.map(new Function() { + @Override + public Integer call(Integer integer) { + double x = Math.random() * 2 - 1; + double y = Math.random() * 2 - 1; + return (x * x + y * y < 1) ? 1 : 0; + } + }).reduce(new Function2() { + @Override + public Integer call(Integer integer, Integer integer2) { + return integer + integer2; + } + }); + + System.out.println("Pi is roughly " + 4.0 * count / n); + + jsc.stop(); + } +} + From 3277ab10e823c7984f2e436f16f60ec42c56dac8 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Tue, 18 May 2021 14:46:53 -0700 Subject: [PATCH 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 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 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 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 @@ LATEST + + org.slf4j + slf4j-simple + 1.7.30 + From 9da1addd0396b75e6df83e7e08ce62beb46dda58 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Tue, 18 May 2021 16:28:31 -0700 Subject: [PATCH 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 parquetFileDF = spark.read().parquet(args[0]); + JavaRDD rdd = parquetFileDF.toJavaRDD(); + rdd.saveAsTextFile(args[1]); + } catch (Exception e) { + System.out.println("Caught exception when processing: " + e); + } + + } +} From 9d7c244b3a2f3c4ac3ad7a3b46fcb9cd6c9280ce Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Fri, 16 Jul 2021 10:39:27 -0700 Subject: [PATCH 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 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 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 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 threadLocal = new ThreadLocal(); + private ThreadLocal threadLocal = new ThreadLocal<>(); @Override public void run() { From e3d1353dc75602f46a9db8fa173dc3bd202143d4 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Sun, 1 Aug 2021 08:43:16 -0700 Subject: [PATCH 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. - * + *

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

* private ThreadLocal myThreadLocal = new ThreadLocal() { - * @Override - * protected String initialValue() { return "This is the initial value"; } + * + * @Override protected String initialValue() { return "This is the initial value"; } * }; */ public class ThreadLocalExample { - public static class MyRunnable implements Runnable { - - private ThreadLocal threadLocal = new ThreadLocal<>(); - - @Override - public void run() { - threadLocal.set((int) (Math.random() * 100D)); - try { - Thread.sleep(2000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - System.out.println("threadLocal.get() is: " + threadLocal.get()); - } - - public static void main(String... args) { - MyRunnable sharedRunnableInstance = new MyRunnable(); - Thread t1 = new Thread(sharedRunnableInstance); - Thread t2 = new Thread(sharedRunnableInstance); - - t1.start(); - t2.start(); - } - } + public static class MyRunnable implements Runnable { + + private ThreadLocal threadLocal = new ThreadLocal<>(); + + @Override + public void run() { + Integer value = (int) (Math.random() * 100D); + System.out.println("value = " + value); + threadLocal.set(value); + try { + Thread.sleep(2000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + System.out.println("threadLocal.get() is: " + threadLocal.get()); + } + + public static void main(String... args) { + System.out.println("Program started."); + MyRunnable sharedRunnableInstance = new MyRunnable(); + Thread t1 = new Thread(sharedRunnableInstance); + Thread t2 = new Thread(sharedRunnableInstance); + t1.start(); + t2.start(); + System.out.println("Program finished."); + } + } } From 5e2987cf0d0a316dda541211a73ced6ce6891553 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Fri, 6 Aug 2021 00:56:49 -0700 Subject: [PATCH 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 shareholders; + + public DistributeProceedsServiceImpl(List shareholders) { + this.shareholders = shareholders; + } + + public DistributionResponse distributeProceeds(Double proceed) { + Double totalClassBFunds = 0.0; + int totalClassBUnits = 0; + int totalUnits = 0; + for (Person person : shareholders) { + Map assumedRolesToShareCount = person.getAssumedRolesToShareCount(); + for (Role role : assumedRolesToShareCount.keySet()) { + if (role.name.equals(GENERAL_PARTNER)) { + totalClassBFunds += ((GeneralPartner) role).initInvestment; + totalClassBUnits += assumedRolesToShareCount.get(role); + } + totalUnits += assumedRolesToShareCount.get(role); + } + } + Double remaining = 0.0; + Double totalClassBProceeds; + if (proceed > totalClassBFunds) { + remaining = proceed - totalClassBFunds; + totalClassBProceeds = totalClassBFunds; + } else { + totalClassBProceeds = proceed; + } + //distribute to ClassB holders first + for (Person person : shareholders) { + Map assumedRolesToShareCount = person.getAssumedRolesToShareCount(); + for (Role role : assumedRolesToShareCount.keySet()) { + if (role.getName().equals(GENERAL_PARTNER)) { + Double percentage = assumedRolesToShareCount.get(role) * 1.0 / totalClassBUnits; + double classBProceed = percentage * totalClassBProceeds; + Map assumedRolesAndProceeds = person.getAssumedRolesAndProceeds(); + assumedRolesAndProceeds.put(role, classBProceed); + person.setAssumedRolesAndProceeds(assumedRolesAndProceeds); + break; + } + } + } + Double totalClassAProceeds = 0.0; + Double totalClassCProceeds = 0.0; + if (remaining > 0) { + //distribute among all classes if there's any remaining + for (Person person : shareholders) { + Map assumedRolesToShareCount = person.getAssumedRolesToShareCount(); + for (Role role : assumedRolesToShareCount.keySet()) { + Double percentage = assumedRolesToShareCount.get(role) * 1.0 / totalUnits; + Double classProceeds = 0.0; + if (role.getName().equals(ASSOCIATE)) { + classProceeds = percentage * remaining; + totalClassAProceeds += classProceeds; + } else if (role.getName().equals(MANAGING_PARTNER)) { + classProceeds = percentage * remaining; + totalClassCProceeds += classProceeds; + } else if (role.getName().equals(GENERAL_PARTNER)) { + classProceeds = percentage * remaining; + totalClassBProceeds += classProceeds; + } + Map assumedRolesAndProceeds = person.getAssumedRolesAndProceeds(); + assumedRolesAndProceeds.put(role, assumedRolesAndProceeds.getOrDefault(role, 0.0) + classProceeds); + person.setAssumedRolesAndProceeds(assumedRolesAndProceeds); + } + } + } + + List payOutAndShareClassList = Arrays.asList( + new PayOutAndShareClass(Math.round(totalClassAProceeds * 100) / 100.0, "Class A"), + new PayOutAndShareClass(Math.round(totalClassBProceeds * 100) / 100.0, "Class B"), + new PayOutAndShareClass(Math.round(totalClassCProceeds * 100) / 100.0, "Class C")); + List payoutAndPersonList = shareholders.stream().map(person -> new PayoutAndPerson(person.getName(), person.getTotalPayout())).collect(Collectors.toList()); + DistributionResponse distributionResponse = new DistributionResponse( + new PayoutByPerson(payoutAndPersonList), new PayoutByShareclass(payOutAndShareClassList)); + return distributionResponse; + } + +} diff --git a/src/main/java/interviewQuestions/distributeProceeds/DistributionResponse.java b/src/main/java/interviewQuestions/distributeProceeds/DistributionResponse.java new file mode 100644 index 0000000..750eeee --- /dev/null +++ b/src/main/java/interviewQuestions/distributeProceeds/DistributionResponse.java @@ -0,0 +1,11 @@ +package interviewQuestions.distributeProceeds; + +public class DistributionResponse { + public DistributionResponse(PayoutByPerson payoutByPerson, PayoutByShareclass payoutByShareclass) { + this.payoutByPerson = payoutByPerson; + this.payoutByShareclass = payoutByShareclass; + } + + PayoutByPerson payoutByPerson; + PayoutByShareclass payoutByShareclass; +} diff --git a/src/main/java/interviewQuestions/distributeProceeds/EntryClass.java b/src/main/java/interviewQuestions/distributeProceeds/EntryClass.java new file mode 100644 index 0000000..e82ba5b --- /dev/null +++ b/src/main/java/interviewQuestions/distributeProceeds/EntryClass.java @@ -0,0 +1,44 @@ +package interviewQuestions.distributeProceeds; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +public class EntryClass { + + public static void main(String... args) { + EntryClass entryClass = new EntryClass(); + List shareholders = entryClass.initShareholders(); + DistributeProceedsService distributeProceedsService = new DistributeProceedsServiceImpl(shareholders); + if (args.length > 0) { + System.out.println(args[0]); + System.out.println(distributeProceedsService.distributeProceeds(Double.parseDouble(args[0]))); + } + DistributionResponse response = distributeProceedsService.distributeProceeds(1000.0); + List payoutAndPersonList = response.payoutByPerson.payoutAndPersonList; + System.out.println(payoutAndPersonList.toString()); + List payOutAndShareClassList = response.payoutByShareclass.payOutAndShareClassList; + System.out.println(payOutAndShareClassList.toString()); + System.out.println("Finished running the program."); + } + + private List initShareholders() { + Person alex = new Person("Alex"); + Map alexRoles = alex.getAssumedRolesToShareCount(); + alexRoles.put(new GeneralPartner(250l), 10); + alex.setAssumedRoles(alexRoles); + + Person becky = new Person("Becky"); + Map beckyRoles = becky.getAssumedRolesToShareCount(); + beckyRoles.put(new GeneralPartner(250l), 10); + beckyRoles.put(new ManagingPartner(), 5); + becky.setAssumedRoles(beckyRoles); + + Person david = new Person("David"); + Map davidRoles = david.getAssumedRolesToShareCount(); + davidRoles.put(new Associate(), 10); + david.setAssumedRoles(davidRoles); + + return Arrays.asList(alex, becky, david); + } +} diff --git a/src/main/java/interviewQuestions/distributeProceeds/GeneralPartner.java b/src/main/java/interviewQuestions/distributeProceeds/GeneralPartner.java new file mode 100644 index 0000000..81348f8 --- /dev/null +++ b/src/main/java/interviewQuestions/distributeProceeds/GeneralPartner.java @@ -0,0 +1,12 @@ +package interviewQuestions.distributeProceeds; + +public class GeneralPartner extends Role { + public static final String GENERAL_PARTNER = "GENERAL_PARTNER"; + + public GeneralPartner(Long initInvestment) { + this.initInvestment = initInvestment; + this.name = GENERAL_PARTNER; + } + + Long initInvestment; +} diff --git a/src/main/java/interviewQuestions/distributeProceeds/ManagingPartner.java b/src/main/java/interviewQuestions/distributeProceeds/ManagingPartner.java new file mode 100644 index 0000000..7a47abe --- /dev/null +++ b/src/main/java/interviewQuestions/distributeProceeds/ManagingPartner.java @@ -0,0 +1,9 @@ +package interviewQuestions.distributeProceeds; + +public class ManagingPartner extends Role { + public static final String MANAGING_PARTNER = "MANAGING_PARTNER"; + + public ManagingPartner() { + this.name = MANAGING_PARTNER; + } +} diff --git a/src/main/java/interviewQuestions/distributeProceeds/PayOutAndShareClass.java b/src/main/java/interviewQuestions/distributeProceeds/PayOutAndShareClass.java new file mode 100644 index 0000000..e56d7a3 --- /dev/null +++ b/src/main/java/interviewQuestions/distributeProceeds/PayOutAndShareClass.java @@ -0,0 +1,19 @@ +package interviewQuestions.distributeProceeds; + +public class PayOutAndShareClass { + Double payoutAmount; + String shareClass; + + public PayOutAndShareClass(Double payoutAmount, String shareClass) { + this.payoutAmount = payoutAmount; + this.shareClass = shareClass; + } + + @Override + public String toString() { + return "PayOutAndShareClass{" + + "payoutAmount=" + payoutAmount + + ", shareClass='" + shareClass + '\'' + + '}'; + } +} diff --git a/src/main/java/interviewQuestions/distributeProceeds/PayoutAndPerson.java b/src/main/java/interviewQuestions/distributeProceeds/PayoutAndPerson.java new file mode 100644 index 0000000..b0ae0b2 --- /dev/null +++ b/src/main/java/interviewQuestions/distributeProceeds/PayoutAndPerson.java @@ -0,0 +1,19 @@ +package interviewQuestions.distributeProceeds; + +public class PayoutAndPerson { + String name; + Double payoutAmount; + + public PayoutAndPerson(String name, Double payoutAmount) { + this.name = name; + this.payoutAmount = payoutAmount; + } + + @Override + public String toString() { + return "PayoutAndPerson{" + + "name='" + name + '\'' + + ", payoutAmount=" + payoutAmount + + '}'; + } +} diff --git a/src/main/java/interviewQuestions/distributeProceeds/PayoutByPerson.java b/src/main/java/interviewQuestions/distributeProceeds/PayoutByPerson.java new file mode 100644 index 0000000..259c107 --- /dev/null +++ b/src/main/java/interviewQuestions/distributeProceeds/PayoutByPerson.java @@ -0,0 +1,11 @@ +package interviewQuestions.distributeProceeds; + +import java.util.List; + +public class PayoutByPerson { + List payoutAndPersonList; + + public PayoutByPerson(List payoutAndPersonList) { + this.payoutAndPersonList = payoutAndPersonList; + } +} diff --git a/src/main/java/interviewQuestions/distributeProceeds/PayoutByShareclass.java b/src/main/java/interviewQuestions/distributeProceeds/PayoutByShareclass.java new file mode 100644 index 0000000..5151e87 --- /dev/null +++ b/src/main/java/interviewQuestions/distributeProceeds/PayoutByShareclass.java @@ -0,0 +1,11 @@ +package interviewQuestions.distributeProceeds; + +import java.util.List; + +public class PayoutByShareclass { + List payOutAndShareClassList; + + public PayoutByShareclass(List payOutAndShareClassList) { + this.payOutAndShareClassList = payOutAndShareClassList; + } +} diff --git a/src/main/java/interviewQuestions/distributeProceeds/Person.java b/src/main/java/interviewQuestions/distributeProceeds/Person.java new file mode 100644 index 0000000..dd1fa52 --- /dev/null +++ b/src/main/java/interviewQuestions/distributeProceeds/Person.java @@ -0,0 +1,45 @@ +package interviewQuestions.distributeProceeds; + +import java.util.HashMap; +import java.util.Map; + +public class Person { + + private String name; + private Map assumedRolesAndShareCount; + private Map assumedRolesAndProceeds; + + public void setAssumedRolesAndProceeds(Map assumedRolesAndProceeds) { + this.assumedRolesAndProceeds = assumedRolesAndProceeds; + } + + public String getName() { + return name; + } + + public Map getAssumedRolesAndProceeds() { + return this.assumedRolesAndProceeds; + } + + public void setAssumedRoles(Map assumedRoles) { + this.assumedRolesAndShareCount = assumedRoles; + } + + public Map getAssumedRolesToShareCount() { + return this.assumedRolesAndShareCount; + } + + public Person(String name) { + this.name = name; + this.assumedRolesAndShareCount = new HashMap<>(); + this.assumedRolesAndProceeds = new HashMap<>(); + } + + public Double getTotalPayout() { + Double total = 0.0; + for (Role role : this.assumedRolesAndProceeds.keySet()) { + total += assumedRolesAndProceeds.get(role); + } + return Math.round(total * 100) / 100.0; + } +} diff --git a/src/main/java/interviewQuestions/distributeProceeds/Role.java b/src/main/java/interviewQuestions/distributeProceeds/Role.java new file mode 100644 index 0000000..7dc17f6 --- /dev/null +++ b/src/main/java/interviewQuestions/distributeProceeds/Role.java @@ -0,0 +1,9 @@ +package interviewQuestions.distributeProceeds; + +public abstract class Role { + public String name; + + public String getName() { + return this.name; + } +} From 03f2fd42e13ed0cf70976b46cc063b34e7dfa980 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 14 Dec 2021 20:28:02 +0000 Subject: [PATCH 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] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 37d654f..e7f02a6 100644 --- a/pom.xml +++ b/pom.xml @@ -26,7 +26,7 @@ org.apache.logging.log4j log4j-api - 2.7 + 2.16.0 org.apache.logging.log4j From 5e4180925eca27fc686f0b1592697cac1ef35b27 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 14 Dec 2021 21:05:17 +0000 Subject: [PATCH 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] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 37d654f..138e06e 100644 --- a/pom.xml +++ b/pom.xml @@ -31,7 +31,7 @@ org.apache.logging.log4j log4j-core - 2.13.2 + 2.16.0 From c369d1b89d7ae56b9ed2e769aa5c1ee5ce4dfe61 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 18 Dec 2021 18:02:31 +0000 Subject: [PATCH 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] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 1673951..950f150 100644 --- a/pom.xml +++ b/pom.xml @@ -26,7 +26,7 @@ org.apache.logging.log4j log4j-api - 2.16.0 + 2.17.0 org.apache.logging.log4j From d8229a0ad525a82f000361948e49096c1ca5a7f0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 18 Dec 2021 18:03:28 +0000 Subject: [PATCH 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] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 1673951..6f6c9fb 100644 --- a/pom.xml +++ b/pom.xml @@ -31,7 +31,7 @@ org.apache.logging.log4j log4j-core - 2.16.0 + 2.17.0 From 60c729158ef12c6b73ac4fd56c96245b8635fd07 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 4 Jan 2022 16:30:46 +0000 Subject: [PATCH 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] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 683614b..d8ad7b9 100644 --- a/pom.xml +++ b/pom.xml @@ -31,7 +31,7 @@ org.apache.logging.log4j log4j-core - 2.17.0 + 2.17.1 From 1e6912a4860eccb266fd05fc3b7a4fb96cd32338 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 4 Jan 2022 16:30:56 +0000 Subject: [PATCH 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] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 683614b..b4fed04 100644 --- a/pom.xml +++ b/pom.xml @@ -26,7 +26,7 @@ org.apache.logging.log4j log4j-api - 2.17.0 + 2.17.1 org.apache.logging.log4j From c701d40ed8c735907b0262a8258462b60fe990ad Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 31 Mar 2022 18:34:55 +0000 Subject: [PATCH 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] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 41767bb..2fcdca3 100644 --- a/pom.xml +++ b/pom.xml @@ -68,7 +68,7 @@ org.springframework spring-webmvc - 4.1.6.RELEASE + 5.3.18 org.springframework @@ -170,6 +177,12 @@ 1.5.1 test + + org.testng + testng + RELEASE + test + diff --git a/src/main/java/guice/relearn_2019_09/_8_already_configured_exception/PrivateModuleTest.java b/src/main/java/guice/relearn_2019_09/_8_already_configured_exception/PrivateModuleTest.java index 4cc0551..9a69a98 100644 --- a/src/main/java/guice/relearn_2019_09/_8_already_configured_exception/PrivateModuleTest.java +++ b/src/main/java/guice/relearn_2019_09/_8_already_configured_exception/PrivateModuleTest.java @@ -1,32 +1,18 @@ package guice.relearn_2019_09._8_already_configured_exception; -import static com.google.inject.name.Names.named; - -import com.google.inject.AbstractModule; -import com.google.inject.ConfigurationException; -import com.google.inject.CreationException; -import com.google.inject.Exposed; -import com.google.inject.Guice; -import com.google.inject.Inject; -import com.google.inject.Injector; -import com.google.inject.Key; -import com.google.inject.PrivateBinder; -import com.google.inject.PrivateModule; -import com.google.inject.Provider; -import com.google.inject.Provides; +import com.google.inject.*; import com.google.inject.name.Named; import com.google.inject.name.Names; -import com.google.inject.spi.Dependency; import com.google.inject.spi.ExposedBinding; -import com.google.inject.spi.PrivateElements; import com.google.inject.util.Types; - import junit.framework.TestCase; import java.util.ArrayList; import java.util.Collection; import java.util.List; +import static com.google.inject.name.Names.named; + public class PrivateModuleTest extends TestCase { public void testBasicUsage() { diff --git a/src/test/b2SdkExamples/B2JsonTest.java b/src/test/b2SdkExamples/B2JsonTest.java index b8e645b..3181255 100644 --- a/src/test/b2SdkExamples/B2JsonTest.java +++ b/src/test/b2SdkExamples/B2JsonTest.java @@ -5,7 +5,7 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; import org.json.JSONException; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.skyscreamer.jsonassert.JSONAssert; import java.math.BigDecimal; @@ -13,8 +13,8 @@ import java.time.LocalDateTime; import java.util.*; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThrows; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; /** * Reference: https://github.com/Backblaze/b2-sdk-java/blob/0ecd68df94691cbba5a6af363246b7193aead234/core/src/test/java/com/backblaze/b2/json/B2JsonTest.java From 61a75bac35f33704eb96ede7cc41fbf8b1419f1c Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Sat, 3 Jun 2023 15:23:48 -0700 Subject: [PATCH 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 @@ org.junit.jupiter junit-jupiter-engine - 5.9.1 - test + 5.9.2 + + + + org.junit.jupiter + junit-jupiter-params + 5.9.0 diff --git a/src/test/junit5/Junit5Test.java b/src/test/junit5/Junit5Test.java new file mode 100644 index 0000000..ff12e84 --- /dev/null +++ b/src/test/junit5/Junit5Test.java @@ -0,0 +1,77 @@ +package junit5; + +import org.apache.logging.log4j.util.Strings; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.stream.Stream; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +public class Junit5Test { + @BeforeAll + static void setup() { + System.out.println("@BeforeAll - executes once before all test methods in this class"); + } + + @BeforeEach + void init() { + System.out.println("@BeforeEach - executes before each test method in this class"); + } + + @DisplayName("Single test successful") + @Test + void testSingleSuccessTest() { + System.out.println("Success"); + assertEquals(5 + 2, 7); + } + + @Test + void shouldThrowException() { + Throwable exception = assertThrows(UnsupportedOperationException.class, () -> { + throw new UnsupportedOperationException("Not supported"); + }); + assertEquals("Not supported", exception.getMessage()); + } + + @Test + void assertThrowsException() { + String str = null; + assertThrows(IllegalArgumentException.class, () -> { + Integer.valueOf(str); + }); + } + + @ParameterizedTest + @MethodSource("data") + public void parameterizedTest(String input, boolean expected) { + assertEquals(expected, Strings.isBlank(input)); + } + + private static Stream data() { + return Stream.of( + Arguments.of(null, true), + Arguments.of("", true), + Arguments.of(" ", true), + Arguments.of("not blank", false) + ); + } + + @AfterEach + void tearDown() { + System.out.println("@AfterEach - executed after each test method."); + } + + @AfterAll + static void done() { + System.out.println("@AfterAll - executed after all test methods."); + } +} From f90ad28aed39556f560a4fa45aa7df85e66a5d6a Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Sun, 4 Jun 2023 09:31:25 -0700 Subject: [PATCH 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 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 buckets = b2ListBucketsResponse.getBuckets(); System.out.println("buckets.size() is: " + buckets.size()); for (B2Bucket b2Bucket : buckets) { From 25b6b82469da997ee9a352d19d69c41e2b30e20f Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Sun, 30 Jul 2023 16:21:34 -0700 Subject: [PATCH 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 buckets = b2ListBucketsResponse.getBuckets(); - System.out.println("buckets.size() is: " + buckets.size()); - for (B2Bucket b2Bucket : buckets) { - System.out.println("this bucket info is: " + b2Bucket.getBucketInfo()); - System.out.println("this bucket getBucketName is: " + b2Bucket.getBucketName()); + try (B2StorageClient b2StorageClient = B2StorageClientFactory.createDefaultFactory().create(APPLICATION_KEY_ID, APPLICATION_KEY, USER_AGENT)) { + b2ListBucketsResponse = b2StorageClient.listBuckets(); + List buckets = b2ListBucketsResponse.getBuckets(); + System.out.println("buckets.size() is: " + buckets.size()); + for (B2Bucket b2Bucket : buckets) { + System.out.println("this bucket info is: " + b2Bucket.getBucketInfo()); + System.out.println("this bucket getBucketName is: " + b2Bucket.getBucketName()); + } + String b2AccountId = b2StorageClient.getAccountId(); + System.out.println("b2AccountId is: " + b2AccountId); } System.out.println("Finished running in main method."); } From cbfb342a3397e508f7f1f63927f3e82d82e00de4 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Sun, 6 Aug 2023 16:51:56 -0700 Subject: [PATCH 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 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> list = new ArrayList>(); + List> list = new ArrayList<>(); Callable callable = new Task(userId); From 5a7cc87e57231ad71857b699e978e462d76c88e8 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Sat, 19 Aug 2023 20:22:47 -0700 Subject: [PATCH 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> list = new ArrayList>(); - - Callable callable = new Task(userId); - - for(int i = 0; i < 10; i++) { - Future future = executor.submit(callable); - list.add(future); - } - - for(Future future : list){ - try { - System.out.println(new Date() + " " + future.get()); - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); - } - } - System.out.println("That's the end of the executeAsynchronous method!"); - executor.shutdown(); - } -} diff --git a/src/main/java/java_async_method_example/async/method/MainApp.java b/src/main/java/java_async_method_example/async/method/MainApp.java index f8ad438..a470ae1 100644 --- a/src/main/java/java_async_method_example/async/method/MainApp.java +++ b/src/main/java/java_async_method_example/async/method/MainApp.java @@ -1,18 +1,8 @@ package java_async_method_example.async.method; -/**This package was used to demo the difference between sync and async methods, but right now, there's really no difference between the impl of SyncClientImpl and AsyncClientImpl classes, - * I need to rewrite them to deepen my understanding!*/ public class MainApp { - public static void main(String... args) { - SyncClient syncClient = new SyncClientImpl(); - - syncClient.executeSynchronous("this is executing synchronous method!"); - - AsyncClient asyncClient = new AsyncClientImpl(); - asyncClient - .executeAsynchronous("this is executing Asynchronous method!"); - - System.out.println("That's the end of MainApp!"); - } + public static void main(String... args) { + System.out.println("That's the end of MainApp!"); + } } diff --git a/src/main/java/java_async_method_example/async/method/SyncClient.java b/src/main/java/java_async_method_example/async/method/SyncClient.java deleted file mode 100644 index 97418ad..0000000 --- a/src/main/java/java_async_method_example/async/method/SyncClient.java +++ /dev/null @@ -1,6 +0,0 @@ -package java_async_method_example.async.method; - -public interface SyncClient { - // for synchronous - void executeSynchronous(final String userId); -} diff --git a/src/main/java/java_async_method_example/async/method/SyncClientImpl.java b/src/main/java/java_async_method_example/async/method/SyncClientImpl.java deleted file mode 100644 index bf1e722..0000000 --- a/src/main/java/java_async_method_example/async/method/SyncClientImpl.java +++ /dev/null @@ -1,36 +0,0 @@ -package java_async_method_example.async.method; - -import java.util.ArrayList; -import java.util.Date; -import java.util.List; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; - -public class SyncClientImpl implements SyncClient { - ExecutorService executor = Executors.newFixedThreadPool(3); - - @Override - public void executeSynchronous(String userId) { - List> list = new ArrayList<>(); - - Callable callable = new Task(userId); - - for(int i = 0; i < 10; i++) { - Future future = executor.submit(callable); - list.add(future); - } - - for(Future future : list){ - try { - System.out.println(new Date() + " " + future.get()); - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); - } - } - executor.shutdown(); - System.out.println("That's the end of the executeSynchronous method!"); - } -} diff --git a/src/main/java/java_async_method_example/async/method/Task.java b/src/main/java/java_async_method_example/async/method/Task.java deleted file mode 100644 index 9517d41..0000000 --- a/src/main/java/java_async_method_example/async/method/Task.java +++ /dev/null @@ -1,19 +0,0 @@ -package java_async_method_example.async.method; - -import java.util.concurrent.Callable; - -public class Task implements Callable { - - private final String userId; - - public Task(String userId) { - this.userId = userId; - } - - @Override - public String call() throws Exception { - Thread.sleep(1500); - return Thread.currentThread().getName() + " " + userId; - } - -} diff --git a/src/main/java/java_async_method_example/future/MainApp.java b/src/main/java/java_async_method_example/future/MainApp.java index cd94c55..c4e2692 100644 --- a/src/main/java/java_async_method_example/future/MainApp.java +++ b/src/main/java/java_async_method_example/future/MainApp.java @@ -17,10 +17,10 @@ public static void main(String... args) { // Executors.newSingleThreadExecutor() // Executors.newCachedThreadPool() Executors.newScheduledThreadPool(15); - /**thread pool account could be a bottleneck when it's smaller than 10 which is the max in the below for loop. + /**thread pool count could be a bottleneck when it's smaller than 10 which is the max in the below for loop. * so when I changed the ThreadPool size to 15, then ALL Future objects got returned at the same time! Cool!*/ - List> list = new ArrayList>(); + List> list = new ArrayList<>(); Callable callable = new MyCallable(); From 0a5b06a3cd6c1017ffd2b76a740d718a30c480ed Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Sun, 20 Aug 2023 14:31:58 -0700 Subject: [PATCH 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 futures = new ArrayList<>(); + for (int i = 0; i < TOTAL_TASKS; i++) { + Runnable worker = new Worker("Worker" + i); + Future future = executorService.submit(worker); + futures.add(future); + } + executorService.shutdown(); + while (!executorService.isTerminated()) { + } + long end = System.currentTimeMillis(); + System.out.println("Multi-threaded app finished, it took " + (end - start) / 1000 + + " seconds for a thread pool of size " + THREAD_POOL_SIZE + " to finish " + + TOTAL_TASKS + " tasks, with each task takes " + MILLISECONDS_TO_FINISH_A_TASK / 1000 + " seconds."); + executorService.shutdown(); + } + + static class Worker implements Runnable { + private String workerName; + + public Worker(String workerName) { + this.workerName = workerName; + } + + @Override + public void run() { + System.out.println(Thread.currentThread().getName() + " starting worker: " + workerName); + doWork(); + System.out.println(Thread.currentThread().getName() + " ended for worker: " + workerName); + } + + private void doWork() { + try { + Thread.sleep(MILLISECONDS_TO_FINISH_A_TASK); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + } + +} diff --git a/src/main/java/multithread/singlevsmultiplethreads/SingleThreadedApp.java b/src/main/java/multithread/singlevsmultiplethreads/SingleThreadedApp.java new file mode 100644 index 0000000..189f575 --- /dev/null +++ b/src/main/java/multithread/singlevsmultiplethreads/SingleThreadedApp.java @@ -0,0 +1,31 @@ +package multithread.singlevsmultiplethreads; + +public class SingleThreadedApp { + + private static final int TOTAL_TASKS = 10; + private static final int MILLISECONDS_TO_FINISH_A_TASK = 1000; + + public static void main(String[] args) throws InterruptedException { + long start = System.currentTimeMillis(); + work(TOTAL_TASKS); + long end = System.currentTimeMillis(); + System.out.println("Single-threaded app took " + (end - start) / 1000 + + " seconds to finish a total of " + TOTAL_TASKS + + " tasks, with each task takes " + MILLISECONDS_TO_FINISH_A_TASK / 1000 + " seconds."); + } + + private static void work(int n) { + for (int i = 0; i < n; i++) { + doWork(i); + } + } + + private static void doWork(int workNumber) { + System.out.println("Task " + workNumber + " is being worked on."); + try { + Thread.sleep(MILLISECONDS_TO_FINISH_A_TASK); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } +} From 8658182c25260edd74752dfd2efa621f79c96a83 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Sun, 20 Aug 2023 18:10:47 -0700 Subject: [PATCH 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 completableFuture = calculateAsync(); + String result = completableFuture.get(); + assertEquals("Hello", result); + } + + private static Future calculateAsync() { + CompletableFuture completableFuture = new CompletableFuture<>(); + + Executors.newCachedThreadPool().submit(() -> { + Thread.sleep(1000); + System.out.println("Doing some work in the thread now.."); + completableFuture.complete("Hello"); + return null; + }); + + return completableFuture; + } + + static class Worker implements Runnable { + private String workerName; + + public Worker(String workerName) { + this.workerName = workerName; + } + + @Override + public void run() { + System.out.println(Thread.currentThread().getName() + " starting worker: " + workerName); + doWork(); + System.out.println(Thread.currentThread().getName() + " ended for worker: " + workerName); + } + + private void doWork() { + try { + Thread.sleep(MILLISECONDS_TO_FINISH_A_TASK); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + } +} From 3e3882a948337b218ef381b63211615e2e4faa19 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Sun, 20 Aug 2023 18:18:18 -0700 Subject: [PATCH 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> futureList = new ArrayList<>(); + for (int i = 1; i <= NUMBER_OF_COMPUTATION_JOBS; i++) { + Future completableFuture = workerPool.executeAsync(i); + futureList.add(completableFuture); + } + for (Future future : futureList) { + String result = future.get(); + finalResult += Integer.parseInt(result); + } + long end = System.currentTimeMillis(); + System.out.println("It took " + (end - start) / 1000 + + " seconds to complete computation, final result: " + finalResult + + ", a total of " + NUMBER_OF_COMPUTATION_JOBS + " computation jobs " + + "have been completed, total pool worker size is: " + POOL_SIZE + + ", and each job took " + TIME_FOR_A_COMPUTATION_JOB_IN_MS / 1000 + " second(s)." + ); + System.out.println("Program ended."); + } + + static class WorkerPool { + static final long TIME_FOR_A_COMPUTATION_JOB_IN_MS = 1000l; + int poolSize; + ExecutorService executorService; + + public WorkerPool(int poolSize) { + this.poolSize = poolSize; + this.executorService = Executors.newFixedThreadPool(poolSize); + } + + public Future executeAsync(int input) { + final CompletableFuture completableFuture = new CompletableFuture<>(); + this.executorService.submit(() -> doWork(completableFuture, input)); + return completableFuture; + } + + private void doWork(CompletableFuture completableFuture, int input) { + int result = 0; + try { + System.out.println(Thread.currentThread().getName() + " is doing some real work now that'll take 1 second to complete."); + Thread.sleep(TIME_FOR_A_COMPUTATION_JOB_IN_MS); + result += input * 2; + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + completableFuture.complete("" + result); + } + } + +} From d4ab0c2e9e70eefdcb2afa7669c95fafa3c5dcb0 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Sun, 20 Aug 2023 20:58:26 -0700 Subject: [PATCH 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 converter = (from -> Integer.valueOf(from)); Integer converted = converter.convert("123"); System.out.println(converted); @@ -25,6 +26,72 @@ public static void main(String ... args) { converter = Integer::valueOf; converted = converter.convert("321"); System.out.println(converted); + + runAnotherFunctionInterfaceExample(); + } + + private static void runAnotherFunctionInterfaceExample() { + /**Function interface has a few methods that are often used: + * apply() + * andThen() + * compose() + * identity() + * */ + Function addFunction = a -> a + 3; + System.out.println(addFunction.apply(1)); + + Function multipleFunction = (a) -> a * 3; + System.out.println(multipleFunction.apply(1)); + + //a.compose(b) means b will be executed first and then a will execute + Function compositeFunction = addFunction.compose(multipleFunction); + System.out.println(compositeFunction.apply(1)); + + //a.andThen(b) means a will be executed first, and then function b executes. + Function andThenFunction = addFunction.andThen(multipleFunction); + System.out.println(andThenFunction.apply(1)); + + //Function.identity() is a static method of Function interface that returns a Function that always returns its input argument. i.e. f(x) = x + understandFunctionIdentity(); + } + + private static void understandFunctionIdentity() { + // Using String as Input for Function.identity() + Function stringFunction = Function.identity(); + System.out.println(stringFunction.apply("Alive is Awesome")); + + // Using Integer as input for Function.identity() + Function integerFunctionUsingFunctionIdentity = Function.identity(); + System.out.println(integerFunctionUsingFunctionIdentity.apply(8)); + + // Using lambda expression and String as input + Function stringFunctionUsingLambda = t -> t; + System.out.println(stringFunctionUsingLambda.apply("Be in present")); + + // Using lambda expression and Integer as input + Function integerFunctionUsingLambda = t -> t; + System.out.println(integerFunctionUsingLambda.apply(4)); + + Function func1 = Function.identity(); + Function func2 = Function.identity(); + Function func3 = Function.identity(); + + Function intFunc1 = t -> t; + Function intFunc2 = t -> t; + Function intFunc3 = t -> t; + + System.out.println(func1); + System.out.println(func2); + System.out.println(func3); + + System.out.println(intFunc1); + System.out.println(intFunc2); + System.out.println(intFunc3); + /** + * From the above output, we can conclude that Function.identity() + * method will always return the same instance + * whereas each occurrence of (t -> t) or identifier -> identifier + * will not only create its own instance but even have a distinct implementation class.*/ } } From 114583695318a9fbb41ce71f223e484d21448888 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Sun, 20 Aug 2023 20:59:54 -0700 Subject: [PATCH 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 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 doWorkStepTwoFunction) throws InterruptedException { + Thread.sleep(1000); + StringBuilder sb = new StringBuilder(message); + System.out.println("Spent 1 second doing work in Step Two Async function."); + sb.append(",aboutToCallDoWorkStepTwoFunction"); + String intermediateResult = doWorkStepTwoFunction.apply(sb.toString()); + return doWorkStepThreeAsync(intermediateResult, doWorkStepThreeFunction); + } + + String doWorkStepThreeAsync(String message, Function doWorkStepThreeFunction) throws InterruptedException { + Thread.sleep(1000); + StringBuilder sb = new StringBuilder(message); + System.out.println("Spent 1 second doing work in Step Three Async function."); + sb.append(",aboutToCallDoWorkStepThreeFunction"); + return doWorkStepThreeFunction.apply(sb.toString()); + } + + Function doWorkStepTwoFunction = s -> { + StringBuilder sb = new StringBuilder(s); + try { + Thread.sleep(1000); + System.out.println("Spent 1 second doing work in Step Two."); + sb.append(",stepTwoDone"); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + return sb.toString(); + }; + + Function doWorkStepThreeFunction = s -> { + StringBuilder sb = new StringBuilder(s); + try { + Thread.sleep(1000); + System.out.println("Spent 1 second doing work in Step Three."); + sb.append(",stepThreeDone"); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + return sb.toString(); + }; + +} From 3461c73ae962fb791535eef0fc05e213a3d0a00f Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Fri, 25 Aug 2023 07:22:20 -0700 Subject: [PATCH 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 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 @@ org.apache.maven.plugins maven-compiler-plugin - 9 - 9 + 16 + 16 From e06b0a9bb86aa18a804c9cb905b26834267f6095 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Tue, 12 Sep 2023 09:06:41 -0700 Subject: [PATCH 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 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 events, long nanos, long interval) { + events.add(nanos); + events.removeIf(aTime -> aTime < nanos - interval); + /* + //noinspection ConstantConditions + while (events.peekFirst() < nanos - interval) { + events.removeFirst(); + } + */ + return events.size(); + } + + public static void main(String[] args) throws IOException { + long start = System.nanoTime(); + int total = 100_000; + long interval = TimeUnit.MILLISECONDS.toNanos(100); + int[] count = new int[total]; + + Deque collection = new ArrayDeque<>(); + for (int counter = 0; counter < count.length; counter++) { + count[counter] = update(collection, System.nanoTime(), interval); + Path p = Paths.get("./a/b"); + Files.createDirectories(p); + /* + if (!Files.exists(p)) { + Files.createDirectories(p); + } + */ + } + long spent = System.nanoTime() - start; + + //noinspection OptionalGetWithoutIsPresent + System.out.println("Average count: " + (int) (Arrays.stream(count).average().getAsDouble()) + " op"); + System.out.println("Spent time: " + TimeUnit.NANOSECONDS.toMillis(spent) + " ms"); + } +} From 6961dabaf97f1fd36f4080e4161b588bb3dfca22 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Tue, 12 Sep 2023 15:18:11 -0700 Subject: [PATCH 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 events, long nanos, long interval) { events.add(nanos); @@ -24,6 +24,7 @@ public static int update(Deque events, long nanos, long interval) { } public static void main(String[] args) throws IOException { + System.out.println("Program started."); long start = System.nanoTime(); int total = 100_000; long interval = TimeUnit.MILLISECONDS.toNanos(100); @@ -45,5 +46,6 @@ public static void main(String[] args) throws IOException { //noinspection OptionalGetWithoutIsPresent System.out.println("Average count: " + (int) (Arrays.stream(count).average().getAsDouble()) + " op"); System.out.println("Spent time: " + TimeUnit.NANOSECONDS.toMillis(spent) + " ms"); + System.out.println("\nProgram finished."); } } From 4c45fad3b3299a108c80f7b35961865797cbb24c Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Sun, 15 Oct 2023 08:36:09 -0700 Subject: [PATCH 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 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 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 buckets = b2ListBucketsResponse.getBuckets(); System.out.println("buckets.size() is: " + buckets.size()); + B2Bucket bucketOne = null; for (B2Bucket b2Bucket : buckets) { System.out.println("this bucket info is: " + b2Bucket.getBucketInfo()); System.out.println("this bucket getBucketName is: " + b2Bucket.getBucketName()); + bucketOne = b2Bucket; + break; } - String b2AccountId = b2StorageClient.getAccountId(); + String b2AccountId = b2Client.getAccountId(); System.out.println("b2AccountId is: " + b2AccountId); + + B2FileVersion largeFile = b2Client.startLargeFile( + B2StartLargeFileRequest + .builder(bucketOne.getBucketId(), "this_is_a_large_test_file_jsun", "text/plain") + .build() + ); + B2UploadPartUrlResponse uploadPartUrl = b2Client.getUploadPartUrl(B2GetUploadPartUrlRequest.builder(largeFile.getFileId()).build()); + System.out.println("uploadPartUrl.getFileId() is: " + uploadPartUrl.getFileId()); + System.out.println("uploadPartUrl.getUploadUrl() is: " + uploadPartUrl.getUploadUrl()); +// example output: +// uploadPartUrl.getFileId() is: 4_zc0c2ee6e6dccd2d788960d17_f231f3059ce9d1672_d20231118_m042524_c004_v0402007_t0004_u01700281524855 +// uploadPartUrl.getUploadUrl() is: https://pod-040-2007-12.backblaze.com/b2api/v2/b2_upload_part/4_zc0c2ee6e6dccd2d788960d17_f231f3059ce9d1672_d20231118_m042524_c004_v0402007_t0004_u01700281524855/0014 + + final B2UploadFileRequest request = B2UploadFileRequest.builder( + bucketOne.getBucketId(), + "largeFile", + B2ContentTypes.TEXT_PLAIN, + B2ByteArrayContentSource.build(large_file_in_bytes) + ).build(); + ExecutorService executor = Executors.newScheduledThreadPool(15); + B2FileVersion uploaded = b2Client.uploadLargeFile(request, executor); + System.out.println("uploaded.getLargeFileSha1OrNull(): " + uploaded.getLargeFileSha1OrNull()); } System.out.println("Finished running in main method."); } From 571f0cfba00f9cf2efe0a0c34cfeba3f0522c869 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Fri, 17 Nov 2023 21:17:31 -0800 Subject: [PATCH 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 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 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 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 map = new HashMap<>(); + while (scanner.hasNext()) { + String city = scanner.next(); + map.put(city, map.getOrDefault(city, 0) + 1); + } + scanner.close(); + System.out.println("Unique city names are: "); + for (String city : map.keySet()) { + if (map.get(city) == 1) { + System.out.println(city); + } + } + } } diff --git a/src/test/resources/city_names.csv b/src/test/resources/city_names.csv new file mode 100644 index 0000000..2ee71fd --- /dev/null +++ b/src/test/resources/city_names.csv @@ -0,0 +1 @@ +NYC,NYC,NYC,Cedar Park,NYC,NYC,NYC,NYC,San Jose,San Jose,San Jose,San Jose,McKinney,San Jose,SF,LA,LA,LA,LA,LA,San Diego,San Diego,San Diego,Seattle,Portland,Portland,Portland,Boston,D.C,D.C,D.C,Miami,Dallas,Cedar Park,McKinney,Melissa,Sacramento,Sacramento \ No newline at end of file From b8a0c679f5894d30e91e11178cb26d2e8c5c4e9f Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Sat, 3 Feb 2024 11:03:24 -0800 Subject: [PATCH 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 names = Arrays.asList(new Person("Sophie", 27), new Person("Ada", 1), + new Person("Steve", 28), new Person("Eason", 26), new Person("Jenny", 31)); + + System.out.println("In sortInJava8_use_lamda_expressions_using_stream method."); + print(names, "Prior to sort: "); + + List sorted = names.stream().sorted(Comparator.comparing(Person::getAge)).collect(Collectors.toList()); + + print(sorted, "After sorting: "); + } + public static void main(String...args) { sortInPreJava8(); sortInJava8_use_lamda_expressions(); sortInJava8_use_lamda_expressions_shorter(); sortInJava8_use_lamda_expressions_shorter_even(); + sortInJava8_use_lamda_expressions_and_stream(); } } class Person { String name; + @Getter int age; public Person (String name, int age) { this.name = name; From 65d57ae2d293407dfa29b2dbef49babb7211db98 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Sat, 3 Feb 2024 11:23:49 -0800 Subject: [PATCH 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 completableFuture = calculateAsync(); + System.out.println("got completableFuture: " + completableFuture); + System.out.println("got completableFuture.isDone(): " + completableFuture.isDone()); String result = completableFuture.get(); + System.out.println("got completableFuture.isDone(): " + completableFuture.isDone()); assertEquals("Hello", result); } @@ -27,8 +30,9 @@ private static Future calculateAsync() { CompletableFuture completableFuture = new CompletableFuture<>(); Executors.newCachedThreadPool().submit(() -> { - Thread.sleep(1000); System.out.println("Doing some work in the thread now.."); + Thread.sleep(1000); + System.out.println("Almost done working in the thread now.."); completableFuture.complete("Hello"); return null; }); diff --git a/src/main/java/multithread/completablefutureexamples/CompletableFutureDemo2.java b/src/main/java/multithread/completablefutureexamples/CompletableFutureDemo2.java index 0efe944..88135b0 100644 --- a/src/main/java/multithread/completablefutureexamples/CompletableFutureDemo2.java +++ b/src/main/java/multithread/completablefutureexamples/CompletableFutureDemo2.java @@ -23,6 +23,7 @@ public static void main(String... args) throws ExecutionException, InterruptedEx List> futureList = new ArrayList<>(); for (int i = 1; i <= NUMBER_OF_COMPUTATION_JOBS; i++) { Future completableFuture = workerPool.executeAsync(i); + System.out.println("i = " + i + " and completableFuture.isDone() is: " + completableFuture.isDone()); futureList.add(completableFuture); } for (Future future : futureList) { @@ -30,8 +31,8 @@ public static void main(String... args) throws ExecutionException, InterruptedEx finalResult += Integer.parseInt(result); } long end = System.currentTimeMillis(); - System.out.println("end: " + end); - System.out.println("start: " + start); + System.out.println("end time in millis: " + end); + System.out.println("start time in millis: " + start); System.out.println("It took " + (end - start) / 1000 + " seconds to complete computation, final result: " + finalResult + ", a total of " + NUMBER_OF_COMPUTATION_JOBS + " computation jobs " From 4d9dbe7a99cde9a040cc1428a4602652e6502351 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Sat, 3 Feb 2024 11:58:38 -0800 Subject: [PATCH 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 { + String taskName; + long input1; + int input2; + + CallableTask(String name, long v1, int v2) { + taskName = name; + input1 = v1; + input2 = v2; + } + + public CalcResult call() { + System.out.println("Task " + taskName + " started -----"); + for (int i = 0; i < input2; i++) { + try { + Thread.sleep(200); + } catch (InterruptedException e) { + System.out.println("Task " + taskName + " interrupted !! "); + e.printStackTrace(); + } + input1 += i; + } + System.out.println("Task " + taskName + " completed."); + return new CalcResult(input1); + } + + } + + public void test() { + ExecutorService executorService = Executors.newFixedThreadPool(3); + CompletionService completionService = new ExecutorCompletionService<>(executorService); + + int submittedTasks = 5; + for (int i = 0; i < submittedTasks; i++) { + completionService.submit(new CallableTask( + String.valueOf(i), + (i * 10), + ((i * 10) + 10) + )); + System.out.println("Task " + i + " submitted"); + } + for (int tasksHandled = 0; tasksHandled < submittedTasks; tasksHandled++) { + try { + System.out.println("trying to take from Completion service"); + Future result = completionService.take(); + System.out.println("result for a task available in queue. Trying to get() now"); + // above call blocks till atleast one task is completed and results availble for it + // but we don't have to worry which one + + // process the result here by doing result.get() + CalcResult l = result.get(); + System.out.println("Task " + tasksHandled + " completed - results obtained : " + l.result); + + } catch (InterruptedException e) { + // Something went wrong with a task submitted + System.out.println("Error Interrupted exception"); + e.printStackTrace(); + } catch (ExecutionException e) { + // Something went wrong with the result + e.printStackTrace(); + System.out.println("Error get() threw exception"); + } + } + } + + public static void main(String... args) { + CompletionServiceDemo demo = new CompletionServiceDemo(); + demo.test(); + System.out.println("\n\nProgram finished.\n"); + } +} From 12cd5578b55cf1f2a9c17ce032a7686e1209d571 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Sun, 4 Feb 2024 11:06:16 -0800 Subject: [PATCH 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 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 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 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 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 names = Arrays.asList(new Person("Sophie", 27), new Person("Ada", 1), + new Person("Steve", 28), new Person("Eason", 26), new Person("Jenny", 31)); + + System.out.println("In sortInJava8_use_lamda_expressions_and_stream_and_filter method."); + + names.stream().distinct().forEach(System.out::println); + names.stream().map(person -> person.name.charAt(0)).distinct().forEach(System.out::println); + } + public static void main(String...args) { sortInPreJava8(); sortInJava8_use_lamda_expressions(); sortInJava8_use_lamda_expressions_shorter(); sortInJava8_use_lamda_expressions_shorter_even(); sortInJava8_use_lamda_expressions_and_stream(); + sortInJava8_use_lamda_expressions_and_stream_and_filter(); } } From 9ad20f89422fd7631eef2118e16facdc1d9d0e00 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Sun, 4 Feb 2024 20:40:17 -0800 Subject: [PATCH 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 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 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 for storing map entries. That means each entry in hashMap is a Node. + * 2. Internally HashMap uses a hashCode of the key Object and this hashCode is further used by the hash function to find the index of the bucket where the new entry can be added. + * 3. HashMap uses multiple buckets and each bucket points to a Singly Linked List where the entries (nodes) are stored. + * 4. Once the bucket is identified by the hash function using hashcode, then hashCode is used to check if there is already a key with the same hashCode or not in the bucket (I mean corresponding singly linked list). + * If there already exists a key with the same hashCode, then the equals() method is used on the keys. + * If the equals method returns true, that means there is already a node with the same key and hence the value against that key is overwritten in the entry (node), + * otherwise, a new node is created and added to this Singly Linked List of that bucket. + * If there is no key with the same hashCode in the bucket found by the hash function then the new Node is added to the bucket found. + * 5. There's a threshold after which is reached, HashMap will change from using singly linked list to use a self-balancing BST, static final int TREEIFY_THRESHOLD = 8; + * the motive for this change is that it could take O(n) worst case for look up with linked list, however, with a self-balancing BST, e.g. red-black tree, we could get O(logn) lookup time; + * + * To have a high-performance hashMap we need good implementation of hashCode() and equals() method along with hash function. + * */ + Map map = new HashMap<>(); + for (int i = 0; i < NUMBER_OF_MAP_ENTRIES; i++) { + map.put("key" + i, "value" + i); + } + map.put("key1", "value_new"); + System.out.println("this method finishes."); + } +} From f95987aff72bf6d0d53cf434c060173bc448ebb2 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Mon, 5 Feb 2024 08:31:17 -0800 Subject: [PATCH 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 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 map = new HashMap<>(); + Map map = new java.util.HashMap<>(); for (int i = 0; i < NUMBER_OF_MAP_ENTRIES; i++) { map.put("key" + i, "value" + i); } From 3c615de6c4f678f4a9bea6f9b0f9c090c019d1f3 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Mon, 5 Feb 2024 08:35:14 -0800 Subject: [PATCH 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 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 set = new HashSet<>(); + for (int i = 0; i < NUMBER_OF_SET_ENTRIES; i++) { + set.add(i + ""); + } + System.out.println("Method finishes."); + } +} From a38ef41c0f7ea516a10956801b59dbf492a69e3c Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Mon, 5 Feb 2024 08:59:33 -0800 Subject: [PATCH 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 listOfNumbers = Arrays.asList(1, 2, 3, 4); + listOfNumbers.stream().forEach(number -> + System.out.println(number + " from this thread: " + Thread.currentThread().getName()) + ); + } + + private static void parallelStreams() { + /** + * Any stream in Java can easily be transformed from sequential to parallel. + * We can achieve this by adding the parallel method to a sequential stream or by creating a stream using the parallelStream method of a collection: + * */ + List listOfNumbers = Arrays.asList(5, 6, 7, 8); + listOfNumbers.parallelStream().forEach(number -> + System.out.println(number + " from this thread: " + Thread.currentThread().getName()) + ); + /** + * Parallel streams enable us to execute code in parallel on separate cores. + * The final result is the combination of each individual outcome. + * However, the order of execution is out of our control.*/ + + /** + * Parallel streams make use of the fork-join framework and its common pool of worker threads. + * The fork-join framework was added to java.util.concurrent in Java 7 to handle task management between multiple threads.*/ + } +} From 0022483f0218d6cb9ef08f9928568a0f35c6ea9d Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Sat, 24 Feb 2024 13:33:25 -0800 Subject: [PATCH 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 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 list) { + // Return sum of list values + int result = list.stream() + .mapToInt(Integer::intValue) + .sum(); + System.out.println("Sum of list values: " + result); + } + + public static void main(String[] args) { + // Referring method to String type Consumer interface + Consumer consumer1 = ConsumerInterfaceExample::printMessage; + consumer1.accept("John"); // Calling Consumer method + // Referring method to Integer type Consumer interface + Consumer consumer2 = ConsumerInterfaceExample::printValue; + consumer2.accept(12); // Calling Consumer method + + // Creating a list and adding values + List list = new ArrayList<>(); + list.add(10); + list.add(20); + list.add(30); + list.add(40); + // Referring method to String type Consumer interface + Consumer> consumer = ConsumerInterfaceExample::addList; + consumer.accept(list); // Calling Consumer method + } +} diff --git a/src/main/java/javaConsumerInterfaceExamples/MainApp.java b/src/main/java/javaConsumerInterfaceExamples/MainApp.java new file mode 100644 index 0000000..f6baf1f --- /dev/null +++ b/src/main/java/javaConsumerInterfaceExamples/MainApp.java @@ -0,0 +1,10 @@ +package javaConsumerInterfaceExamples; + +import java.util.function.Consumer; + +public class MainApp { + public static void main(String... args) { + Consumer print = x -> System.out.println(x); + print.accept("java 8 consumer interface"); // java + } +} From e29bbac5b4de19498fb6e5bb08ccc6fb6ba5251e Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Thu, 4 Jul 2024 12:06:22 -0700 Subject: [PATCH 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 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: StackOverflow + */ + + private static String salt; + private static int iterations = 65536; + private static int keySize = 256; + private static byte[] ivBytes; + + private static SecretKey secretKey; + + public static void main(String[] args) throws Exception { + System.out.println("Program started."); + salt = getSalt(); + System.out.println("salt is: " + salt); + char[] message = "PasswordToEncrypt".toCharArray(); + System.out.println("Message: " + String.valueOf(message)); + System.out.println("Encrypted: " + encrypt(message)); + System.out.println("Decrypted: " + decrypt(encrypt(message).toCharArray())); + System.out.println("Program ended."); + } + + public static String encrypt(char[] plaintext) throws Exception { + byte[] saltBytes = salt.getBytes(); + + SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); + PBEKeySpec spec = new PBEKeySpec(plaintext, saltBytes, iterations, keySize); + secretKey = secretKeyFactory.generateSecret(spec); + SecretKeySpec secretSpec = new SecretKeySpec(secretKey.getEncoded(), "AES"); + + Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); + cipher.init(Cipher.ENCRYPT_MODE, secretSpec); + AlgorithmParameters algorithmParameters = cipher.getParameters(); + ivBytes = algorithmParameters.getParameterSpec(IvParameterSpec.class).getIV(); + byte[] encryptedTextBytes = cipher.doFinal(String.valueOf(plaintext).getBytes("UTF-8")); + + return DatatypeConverter.printBase64Binary(encryptedTextBytes); + } + + public static String decrypt(char[] encryptedText) throws Exception { + byte[] encryptedTextBytes = DatatypeConverter.parseBase64Binary(new String(encryptedText)); + SecretKeySpec secretSpec = new SecretKeySpec(secretKey.getEncoded(), "AES"); + + Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); + cipher.init(Cipher.DECRYPT_MODE, secretSpec, new IvParameterSpec(ivBytes)); + + byte[] decryptedTextBytes = null; + + try { + decryptedTextBytes = cipher.doFinal(encryptedTextBytes); + } catch (IllegalBlockSizeException e) { + e.printStackTrace(); + } catch (BadPaddingException e) { + e.printStackTrace(); + } + + return new String(decryptedTextBytes); + + } + + public static String getSalt() throws Exception { + //https://docs.oracle.com/en/java/javase/22/docs/specs/security/standard-names.html + SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");//this is the default algorithm, so can be omitted + byte[] salt = new byte[20]; + secureRandom.nextBytes(salt); + return new String(salt); + } +} From d2b859a3829a56ac62d0c35f4ef321e5bff3865f Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Sun, 7 Jul 2024 12:13:43 -0700 Subject: [PATCH 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 @@ test + + org.springframework.security + spring-security-crypto + 6.3.1 + + diff --git a/src/main/java/encryption/SpringSecurityCryptoModule.java b/src/main/java/encryption/SpringSecurityCryptoModule.java new file mode 100644 index 0000000..71ba681 --- /dev/null +++ b/src/main/java/encryption/SpringSecurityCryptoModule.java @@ -0,0 +1,23 @@ +package encryption; + +import org.springframework.security.crypto.keygen.BytesKeyGenerator; +import org.springframework.security.crypto.keygen.KeyGenerators; + +public class SpringSecurityCryptoModule { + /** + * Reference: https://docs.spring.io/spring-security/site/docs/3.1.x/reference/crypto.html + */ + public static void main(String... args) { +// BytesEncryptor encryptor = Encryptors.standard("password", "salt"); + + String salt = KeyGenerators.string().generateKey(); // generates a random 8-byte salt that is then hex-encoded + System.out.println("salt is: " + salt); + +// TextEncryptor textEncryptor = Encryptors.text("password", "salt"); + + BytesKeyGenerator generator = KeyGenerators.secureRandom(); + byte[] key = generator.generateKey(); + System.out.println("key is: " + key); + + } +} From 7bc9a32a4c016a7b308e9d77e56e5470ca9a17a0 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Mon, 9 Sep 2024 08:24:46 -0700 Subject: [PATCH 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 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 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 baseSet = readAllFieldNames(BASE_FILE); + Set updateFileSet = readAllFieldNames(UPDATE_FILE); + Set baseSetCopy = new HashSet<>(baseSet); + baseSetCopy.removeAll(updateFileSet); + System.out.println("baseSetCopy size after removing updateFileSet is: " + baseSetCopy.size()); + + Set linesOnlyExistInBaseSet = readLinesMatchingSet(BASE_FILE, baseSetCopy); +// linesOnlyExistInBaseSet.forEach(System.out::println); + System.out.println("Found a total of " + linesOnlyExistInBaseSet.size() + " matches."); + + appendLinesToFile(UPDATE_FILE, linesOnlyExistInBaseSet); + + System.out.println("Program finished."); + } + + private static void appendLinesToFile(String updateFile, Set linesToBeAppended) throws IOException { + BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(updateFile, true)); + bufferedWriter.append("\n\n\n"); + bufferedWriter.append("#Added below fields from base file ---------\n"); + for (String str : linesToBeAppended) { + bufferedWriter.append(str); + bufferedWriter.append("\n"); + } + bufferedWriter.close(); + } + + private static Set readLinesMatchingSet(String filePath, Set set) throws FileNotFoundException { + if (filePath.isEmpty()) { + System.out.println("No file to read, exit."); + return null; + } + Scanner scanner = new Scanner(new File(filePath)); + scanner.useDelimiter("\n"); + Set lines = new HashSet<>(); + int i = 0; + while (scanner.hasNext()) { + String line = scanner.next(); + i++; + if (!line.isEmpty() && Character.isAlphabetic(line.charAt(0))) { + String[] parts = line.split("="); + if (set.contains(parts[0])) { + lines.add(line); + } + } + } + scanner.close(); + System.out.println("A total of " + i + " lines were gone through, and found a total of " + lines.size() + " matches."); + return lines; + } + + public static Set readAllFieldNames(String filePath) throws IOException { + if (filePath.isEmpty()) { + System.out.println("No file to read, exit."); + return null; + } + Scanner scanner = new Scanner(new File(filePath)); + scanner.useDelimiter("\n"); + + assertTrue(scanner.hasNext()); + int i = 0; + int nonEmptyLines = 0; + Set fields = new HashSet<>(); + while (scanner.hasNext()) { + String line = scanner.next(); + i++; + if (!line.isEmpty() && Character.isAlphabetic(line.charAt(0))) { + String[] parts = line.split("="); + fields.add(parts[0]); + nonEmptyLines++; + } + } + System.out.println("For this file: " + filePath + ": A total of " + i + " lines, in which " + nonEmptyLines + " are non empty."); + + scanner.close(); + return fields; + } +} From a1cbc7fde7da1dc012473dd6cefa3ff723c57a43 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Sat, 12 Oct 2024 15:13:58 -0700 Subject: [PATCH 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 @@ org.apache.maven.plugins maven-compiler-plugin - 16 - 16 + 17 + 17 @@ -37,7 +37,7 @@ org.projectlombok lombok - 1.18.2 + 1.18.20 provided From bd5486acd709e40e1ef4100b85f755e507f257c4 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Sat, 12 Oct 2024 15:17:19 -0700 Subject: [PATCH 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 data() { - return Stream.of( - Arguments.of(null, true), - Arguments.of("", true), - Arguments.of(" ", true), - Arguments.of("not blank", false) - ); - } - @AfterEach void tearDown() { System.out.println("@AfterEach - executed after each test method."); diff --git a/src/test/junit5/ParameterizedTestExampleTest.java b/src/test/junit5/ParameterizedTestExampleTest.java new file mode 100644 index 0000000..e856e13 --- /dev/null +++ b/src/test/junit5/ParameterizedTestExampleTest.java @@ -0,0 +1,28 @@ +package junit5; + +import org.apache.logging.log4j.util.Strings; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.stream.Stream; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class ParameterizedTestExampleTest { + @ParameterizedTest + @MethodSource("data") + public void parameterizedTest(String input, boolean expected) { + System.out.println("input is: " + input + ", expected is: " + expected); + assertEquals(expected, Strings.isBlank(input)); + } + + private static Stream data() { + return Stream.of( + Arguments.of(null, true), + Arguments.of("", true), + Arguments.of(" ", true), + Arguments.of("not blank", false) + ); + } +} From 66629b68acef10abe23e4e098acc86cdc9f83fec Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Fri, 18 Oct 2024 11:56:29 -0700 Subject: [PATCH 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 data() { + return Stream.of(Arguments.of("string1")); + } + + @ParameterizedTest + @MethodSource("data") + public void test1() { + assertNull(this.field2); + } +} From d75ef5a51eb67ed1327dff1b118c37049a60e3f9 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Sun, 20 Oct 2024 09:51:25 -0700 Subject: [PATCH 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 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 @@ 1.0-SNAPSHOT + + com.opencsv + opencsv + 5.9 + org.apache.logging.log4j diff --git a/src/main/java/randomExamples/OpenCSVExample.java b/src/main/java/randomExamples/OpenCSVExample.java new file mode 100644 index 0000000..6879c1f --- /dev/null +++ b/src/main/java/randomExamples/OpenCSVExample.java @@ -0,0 +1,31 @@ +package randomExamples; + +import com.opencsv.CSVReader; +import com.opencsv.exceptions.CsvValidationException; + +import java.io.FileReader; +import java.io.IOException; + +public class OpenCSVExample { + /** + * This is a good example to show that this popular CSV library that can handle fields that contain comma in CSV files well. + * Look at this file: values_with_comma_inside.csv, some fields have comma in them, which are enclosed with double quotes, + * if you use string.split(","), that field will be broken into parts which is wrong, + * whereas using this library will help take care of this case very well. + */ + public static void main(String[] args) throws CsvValidationException { + String file = "src/test/resources/values_with_comma_inside.csv"; + try (CSVReader reader = new CSVReader(new FileReader(file))) { + String[] nextLine; + while ((nextLine = reader.readNext()) != null) { + System.out.println("nextLine.length is: " + nextLine.length); + for (int i = 0; i < nextLine.length; i++) { + System.out.println("nextLine[" + i + "] is: " + nextLine[i]); + } + System.out.println(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/src/test/resources/values_with_comma_inside.csv b/src/test/resources/values_with_comma_inside.csv new file mode 100644 index 0000000..977ea75 --- /dev/null +++ b/src/test/resources/values_with_comma_inside.csv @@ -0,0 +1,6 @@ +9130348058430616,FixIT LLC +1376819470,"JACKSON ABC, LLC. " +1313034490,Campers Cove LLC +123145734316537,"Nice Corp, LLC" +9130347434882146,FORCE COLLIDE LLC +539967725,"Watson Group, LLC. " \ No newline at end of file From 24895517ae852d992a0587af45bce635e4c61602 Mon Sep 17 00:00:00 2001 From: Fisher Coder Date: Thu, 19 Dec 2024 19:28:59 -0800 Subject: [PATCH 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