diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..0036b29a --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +/Chapter01/P01_CountDuplicateCharacters/target/ +/Chapter01/P03_ReverseWords/target/ +/Chapter01/P05_CountVowelsAndConsonants/target/ +/Chapter01/P05_CountVowelsAndConsonants1/target/ +/Chapter01/P02_TextBlockDelimiters/target/ diff --git a/Chapter01/.gitignore b/Chapter01/.gitignore index 00fb5c21..237f864c 100644 --- a/Chapter01/.gitignore +++ b/Chapter01/.gitignore @@ -2,4 +2,4 @@ build/ dist/ nbproject/ build.xml -manifest.mf \ No newline at end of file +manifest.mf diff --git a/Chapter01/P01_CountDuplicateCharacters/src/modern/challenge/Strings.java b/Chapter01/P01_CountDuplicateCharacters/src/modern/challenge/Strings.java index 291b65e1..f52fbf06 100644 --- a/Chapter01/P01_CountDuplicateCharacters/src/modern/challenge/Strings.java +++ b/Chapter01/P01_CountDuplicateCharacters/src/modern/challenge/Strings.java @@ -51,7 +51,7 @@ public static Map countDuplicateCharactersVCP1(String str) { // or, like this (this code produce the same result as the commented code above int cp = str.codePointAt(i); String ch = String.valueOf(Character.toChars(cp)); - if(Character.charCount(cp) == 2) { // 2 means a suroggate pair + if(Character.charCount(cp) == 2) { // 2 means a surrogate pair i++; } diff --git a/Chapter01/P19_DeclareMultilineStrings/src/modern/challenge/Main.java b/Chapter01/P19_DeclareMultilineStrings/src/modern/challenge/Main.java index 1a658d71..c9389362 100644 --- a/Chapter01/P19_DeclareMultilineStrings/src/modern/challenge/Main.java +++ b/Chapter01/P19_DeclareMultilineStrings/src/modern/challenge/Main.java @@ -39,15 +39,13 @@ public static void main(String[] args) { System.out.println("Text 4:" + LS + text4); System.out.println("--------------------------------------------"); - // JDK 13 text blocks - /* + // JDK 13 text blocks String text5 = """My high school, the Illinois Mathematics and Science Academy, showed me that anything is possible and that you're never too young to think big."""; System.out.println("Text 5:" + LS + text5); - System.out.println("--------------------------------------------"); - */ + System.out.println("--------------------------------------------"); } } diff --git a/Chapter01/README.md b/Chapter01/README.md index 52da82e9..c4381bb0 100644 --- a/Chapter01/README.md +++ b/Chapter01/README.md @@ -1,2 +1,2 @@ # Strings, numbers & math problems -This chapter includes 39 problems that involves strings, numbers and mathematical operations. The chapter starts with a bunch of classical problems for strings such as counting duplicates, reversing a string, removing whitespaces and so on and forth. The chapter continue with problems dedicated to numbers and mathematical operations such as summing two large numbers and operation overflow, comparing two unsigned numbers, compute the floor of a division and modulus, etc. Each problem is passed through several solutions including Java 8 functional style. Moreover, the chapter covers through problems the futures added in JDK 9, 10, 11 and 12. +This chapter includes 39 problems that involves strings, numbers and mathematical operations. The chapter starts with a bunch of classical problems for strings such as counting duplicates, reversing a string, removing whitespaces and so on and forth. The chapter continue with problems dedicated to numbers and mathematical operations such as summing two large numbers and operation overflow, comparing two unsigned numbers, compute the floor of a division and modulus, etc. Each problem is passed through several solutions including Java 8 functional style. Moreover, the chapter covers through problems the futures added in JDK 9, 10, 11 and 12. diff --git a/Chapter02/BONUS_1_SpringAndJavaRecords/README.md b/Chapter02/BONUS_1_SpringAndJavaRecords/README.md new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/Chapter02/BONUS_1_SpringAndJavaRecords/README.md @@ -0,0 +1 @@ + diff --git a/Chapter02/BONUS_1_SpringAndJavaRecords/nbactions.xml b/Chapter02/BONUS_1_SpringAndJavaRecords/nbactions.xml new file mode 100644 index 00000000..9629cad8 --- /dev/null +++ b/Chapter02/BONUS_1_SpringAndJavaRecords/nbactions.xml @@ -0,0 +1,46 @@ + + + + run + + jar + + + process-classes + org.codehaus.mojo:exec-maven-plugin:1.5.0:exec + + + --enable-preview -classpath %classpath ${packageClassName} + java + + + + debug + + jar + + + process-classes + org.codehaus.mojo:exec-maven-plugin:1.5.0:exec + + + -agentlib:jdwp=transport=dt_socket,server=n,address=${jpda.address} --enable-preview -classpath %classpath ${packageClassName} + java + true + + + + profile + + jar + + + process-classes + org.codehaus.mojo:exec-maven-plugin:1.5.0:exec + + + --enable-preview -classpath %classpath ${packageClassName} + java + + + diff --git a/Chapter02/BONUS_1_SpringAndJavaRecords/pom.xml b/Chapter02/BONUS_1_SpringAndJavaRecords/pom.xml new file mode 100644 index 00000000..8ad18627 --- /dev/null +++ b/Chapter02/BONUS_1_SpringAndJavaRecords/pom.xml @@ -0,0 +1,70 @@ + + + 4.0.0 + + com.jpa + BONUS_1_SpringAndJavaRecords + 1.0 + jar + + BONUS_1_SpringAndJavaRecords + JPA project for Spring Boot + + + org.springframework.boot + spring-boot-starter-parent + 2.2.6.RELEASE + + + + + UTF-8 + UTF-8 + 1.8 + 14 + 14 + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + 14 + + --enable-preview + + true + true + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.0.0-M3 + + --enable-preview + + + + + diff --git a/Chapter02/BONUS_1_SpringAndJavaRecords/src/main/java/modern/challenge/MainApplication.java b/Chapter02/BONUS_1_SpringAndJavaRecords/src/main/java/modern/challenge/MainApplication.java new file mode 100644 index 00000000..06dbfcee --- /dev/null +++ b/Chapter02/BONUS_1_SpringAndJavaRecords/src/main/java/modern/challenge/MainApplication.java @@ -0,0 +1,12 @@ +package modern.challenge; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class MainApplication { + + public static void main(String[] args) { + SpringApplication.run(MainApplication.class, args); + } +} diff --git a/Chapter02/BONUS_1_SpringAndJavaRecords/src/main/java/modern/challenge/controller/BookstoreController.java b/Chapter02/BONUS_1_SpringAndJavaRecords/src/main/java/modern/challenge/controller/BookstoreController.java new file mode 100644 index 00000000..fcd7e7f1 --- /dev/null +++ b/Chapter02/BONUS_1_SpringAndJavaRecords/src/main/java/modern/challenge/controller/BookstoreController.java @@ -0,0 +1,26 @@ +package modern.challenge.controller; + +import java.util.List; +import modern.challenge.service.BookstoreService; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +import modern.challenge.record.Author; + +@RestController +public class BookstoreController { + + private final BookstoreService bookstoreService; + + public BookstoreController(BookstoreService bookstoreService) { + this.bookstoreService = bookstoreService; + } + + @GetMapping("/authors") + public List fetchAuthors() { + + return bookstoreService.fetchAuthors(); + } + +} diff --git a/Chapter02/BONUS_1_SpringAndJavaRecords/src/main/java/modern/challenge/record/Author.java b/Chapter02/BONUS_1_SpringAndJavaRecords/src/main/java/modern/challenge/record/Author.java new file mode 100644 index 00000000..0169507c --- /dev/null +++ b/Chapter02/BONUS_1_SpringAndJavaRecords/src/main/java/modern/challenge/record/Author.java @@ -0,0 +1,8 @@ +package modern.challenge.record; + +import java.util.List; +import com.fasterxml.jackson.annotation.JsonProperty; + +public record Author(@JsonProperty("name") String name, +@JsonProperty("genre") String genre, +@JsonProperty("books") List books) {} diff --git a/Chapter02/BONUS_1_SpringAndJavaRecords/src/main/java/modern/challenge/record/Book.java b/Chapter02/BONUS_1_SpringAndJavaRecords/src/main/java/modern/challenge/record/Book.java new file mode 100644 index 00000000..687cadb9 --- /dev/null +++ b/Chapter02/BONUS_1_SpringAndJavaRecords/src/main/java/modern/challenge/record/Book.java @@ -0,0 +1,6 @@ +package modern.challenge.record; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public record Book(@JsonProperty("title") String title, +@JsonProperty("isbn") String isbn) {} diff --git a/Chapter02/BONUS_1_SpringAndJavaRecords/src/main/java/modern/challenge/service/BookstoreService.java b/Chapter02/BONUS_1_SpringAndJavaRecords/src/main/java/modern/challenge/service/BookstoreService.java new file mode 100644 index 00000000..ad6f19de --- /dev/null +++ b/Chapter02/BONUS_1_SpringAndJavaRecords/src/main/java/modern/challenge/service/BookstoreService.java @@ -0,0 +1,27 @@ +package modern.challenge.service; + +import java.util.List; +import org.springframework.stereotype.Service; + +import modern.challenge.record.Author; +import modern.challenge.record.Book; + +@Service +public class BookstoreService { + + public List fetchAuthors() { + + List authors = List.of( + new Author("Joana Nimar", "History", List.of( + new Book("History of a day", "JN-001"), + new Book("Prague history", "JN-002") + )), + new Author("Mark Janel", "Horror", List.of( + new Book("Carrie", "MJ-001"), + new Book("House of pain", "MJ-002") + ) + )); + + return authors; + } +} diff --git a/Chapter02/BONUS_1_SpringAndJavaRecords/src/main/resources/application.properties b/Chapter02/BONUS_1_SpringAndJavaRecords/src/main/resources/application.properties new file mode 100644 index 00000000..e69de29b diff --git a/Chapter02/BONUS_2_SpringAndJavaRecordsInjection/README.md b/Chapter02/BONUS_2_SpringAndJavaRecordsInjection/README.md new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/Chapter02/BONUS_2_SpringAndJavaRecordsInjection/README.md @@ -0,0 +1 @@ + diff --git a/Chapter02/BONUS_2_SpringAndJavaRecordsInjection/nbactions.xml b/Chapter02/BONUS_2_SpringAndJavaRecordsInjection/nbactions.xml new file mode 100644 index 00000000..9629cad8 --- /dev/null +++ b/Chapter02/BONUS_2_SpringAndJavaRecordsInjection/nbactions.xml @@ -0,0 +1,46 @@ + + + + run + + jar + + + process-classes + org.codehaus.mojo:exec-maven-plugin:1.5.0:exec + + + --enable-preview -classpath %classpath ${packageClassName} + java + + + + debug + + jar + + + process-classes + org.codehaus.mojo:exec-maven-plugin:1.5.0:exec + + + -agentlib:jdwp=transport=dt_socket,server=n,address=${jpda.address} --enable-preview -classpath %classpath ${packageClassName} + java + true + + + + profile + + jar + + + process-classes + org.codehaus.mojo:exec-maven-plugin:1.5.0:exec + + + --enable-preview -classpath %classpath ${packageClassName} + java + + + diff --git a/Chapter02/BONUS_2_SpringAndJavaRecordsInjection/pom.xml b/Chapter02/BONUS_2_SpringAndJavaRecordsInjection/pom.xml new file mode 100644 index 00000000..acb79127 --- /dev/null +++ b/Chapter02/BONUS_2_SpringAndJavaRecordsInjection/pom.xml @@ -0,0 +1,70 @@ + + + 4.0.0 + + com.jpa + BONUS_2_SpringAndJavaRecordsInjection + 1.0 + jar + + BONUS_2_SpringAndJavaRecordsInjection + JPA project for Spring Boot + + + org.springframework.boot + spring-boot-starter-parent + 2.2.6.RELEASE + + + + + UTF-8 + UTF-8 + 1.8 + 14 + 14 + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + 14 + + --enable-preview + + true + true + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.0.0-M3 + + --enable-preview + + + + + diff --git a/Chapter02/BONUS_2_SpringAndJavaRecordsInjection/src/main/java/modern/challenge/MainApplication.java b/Chapter02/BONUS_2_SpringAndJavaRecordsInjection/src/main/java/modern/challenge/MainApplication.java new file mode 100644 index 00000000..06dbfcee --- /dev/null +++ b/Chapter02/BONUS_2_SpringAndJavaRecordsInjection/src/main/java/modern/challenge/MainApplication.java @@ -0,0 +1,12 @@ +package modern.challenge; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class MainApplication { + + public static void main(String[] args) { + SpringApplication.run(MainApplication.class, args); + } +} diff --git a/Chapter02/BONUS_2_SpringAndJavaRecordsInjection/src/main/java/modern/challenge/controller/BookstoreController.java b/Chapter02/BONUS_2_SpringAndJavaRecordsInjection/src/main/java/modern/challenge/controller/BookstoreController.java new file mode 100644 index 00000000..895ac4ea --- /dev/null +++ b/Chapter02/BONUS_2_SpringAndJavaRecordsInjection/src/main/java/modern/challenge/controller/BookstoreController.java @@ -0,0 +1,20 @@ +package modern.challenge.controller; + +import java.util.List; +import modern.challenge.service.BookstoreService; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +import modern.challenge.record.Author; + +@RestController +public record BookstoreController(BookstoreService bookstoreService) { + + @GetMapping("/authors") + public List fetchAuthors() { + + return bookstoreService.fetchAuthors(); + } + +} diff --git a/Chapter02/BONUS_2_SpringAndJavaRecordsInjection/src/main/java/modern/challenge/record/Author.java b/Chapter02/BONUS_2_SpringAndJavaRecordsInjection/src/main/java/modern/challenge/record/Author.java new file mode 100644 index 00000000..0169507c --- /dev/null +++ b/Chapter02/BONUS_2_SpringAndJavaRecordsInjection/src/main/java/modern/challenge/record/Author.java @@ -0,0 +1,8 @@ +package modern.challenge.record; + +import java.util.List; +import com.fasterxml.jackson.annotation.JsonProperty; + +public record Author(@JsonProperty("name") String name, +@JsonProperty("genre") String genre, +@JsonProperty("books") List books) {} diff --git a/Chapter02/BONUS_2_SpringAndJavaRecordsInjection/src/main/java/modern/challenge/record/Book.java b/Chapter02/BONUS_2_SpringAndJavaRecordsInjection/src/main/java/modern/challenge/record/Book.java new file mode 100644 index 00000000..687cadb9 --- /dev/null +++ b/Chapter02/BONUS_2_SpringAndJavaRecordsInjection/src/main/java/modern/challenge/record/Book.java @@ -0,0 +1,6 @@ +package modern.challenge.record; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public record Book(@JsonProperty("title") String title, +@JsonProperty("isbn") String isbn) {} diff --git a/Chapter02/BONUS_2_SpringAndJavaRecordsInjection/src/main/java/modern/challenge/service/BookstoreService.java b/Chapter02/BONUS_2_SpringAndJavaRecordsInjection/src/main/java/modern/challenge/service/BookstoreService.java new file mode 100644 index 00000000..25816110 --- /dev/null +++ b/Chapter02/BONUS_2_SpringAndJavaRecordsInjection/src/main/java/modern/challenge/service/BookstoreService.java @@ -0,0 +1,27 @@ +package modern.challenge.service; + +import java.util.List; +import org.springframework.stereotype.Service; + +import modern.challenge.record.Author; +import modern.challenge.record.Book; + +@Service +public class BookstoreService { + + public List fetchAuthors() { + + List authors = List.of( + new Author("Joana Nimar", "History", List.of( + new Book("History of a day", "JN-001"), + new Book("Prague history", "JN-002") + )), + new Author("Mark Janel", "Horror", List.of( + new Book("Carrie", "MJ-001"), + new Book("House of pain", "MJ-002") + ) + )); + + return authors; + } +} diff --git a/Chapter02/BONUS_2_SpringAndJavaRecordsInjection/src/main/resources/application.properties b/Chapter02/BONUS_2_SpringAndJavaRecordsInjection/src/main/resources/application.properties new file mode 100644 index 00000000..e69de29b diff --git a/Chapter02/P53_CloningObjects/src/main/java/modern/challenge/Main.java b/Chapter02/P53_CloningObjects/src/main/java/modern/challenge/Main.java index 255eb375..9623b7c9 100644 --- a/Chapter02/P53_CloningObjects/src/main/java/modern/challenge/Main.java +++ b/Chapter02/P53_CloningObjects/src/main/java/modern/challenge/Main.java @@ -7,6 +7,8 @@ import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; +import java.util.Arrays; +import modern.challenge.shallow.copy.matrix.Matrices; import org.apache.commons.lang3.SerializationUtils; public class Main { @@ -14,7 +16,7 @@ public class Main { public static void main(String[] args) throws CloneNotSupportedException { // shallow copy via manual copy - System.out.println("Shallow copy via manual copy:"); + System.out.println("\nShallow copy via manual copy:"); modern.challenge.shallow.copy.manually.Point point1 = new modern.challenge.shallow.copy.manually.Point(5, 5); @@ -159,6 +161,44 @@ public static void main(String[] args) throws CloneNotSupportedException { System.out.println("Clone 7, (x, y, Radius start, Radius end): " + clone7.getX() + ", " + clone7.getY() + ", " + clone7.getRadius().getStart() + ", " + clone7.getRadius().getEnd()); + + int[][] source = {{3, 1, 5}, {3, 6, 7}}; + + // shallow copy of matrix (1) + System.out.println("\nShallow copy of matrix via manual copy (1):"); + int[][] target1 = Matrices.cloneArrayOfInt1(source); + target1[0][0] = 0; + System.out.println("Original array:"); + printMatrix(source); + System.out.println("Cloned and modified array:"); + printMatrix(target1); + + // shallow copy of matrix (2) + System.out.println("\nShallow copy of matrix via manual copy (2):"); + int[][] target2 = Matrices.cloneArrayOfInt2(source); + target2[0][0] = 0; + System.out.println("Original array:"); + printMatrix(source); + System.out.println("Cloned and modified array:"); + printMatrix(target2); + + // shallow copy of matrix (3) + System.out.println("\nShallow copy of matrix via manual copy (3):"); + int[][] target3 = Matrices.cloneArrayOfInt3(source); + target3[0][0] = 0; + System.out.println("Original array:"); + printMatrix(source); + System.out.println("Cloned and modified array:"); + printMatrix(target3); + + // shallow copy of matrix (4) + System.out.println("\nShallow copy of matrix via manual copy (4):"); + int[][] target4 = Matrices.cloneArrayOfInt4(source); + target4[0][0] = 0; + System.out.println("Original array:"); + printMatrix(source); + System.out.println("Cloned and modified array:"); + printMatrix(target4); } @SuppressWarnings("unchecked") @@ -182,4 +222,14 @@ private static T cloneThroughSerialization(T t) { return t; } } + + // helper method to display a matrix + private static void printMatrix(int[][] matrix) { + for (int i = 0; i < matrix.length; i++) { + for (int j = 0; j < matrix[0].length; j++) { + System.out.print(matrix[i][j] + " "); + } + System.out.println(); + } + } } diff --git a/Chapter02/P53_CloningObjects/src/main/java/modern/challenge/shallow/copy/matrix/Matrices.java b/Chapter02/P53_CloningObjects/src/main/java/modern/challenge/shallow/copy/matrix/Matrices.java new file mode 100644 index 00000000..3921b0df --- /dev/null +++ b/Chapter02/P53_CloningObjects/src/main/java/modern/challenge/shallow/copy/matrix/Matrices.java @@ -0,0 +1,61 @@ +package modern.challenge.shallow.copy.matrix; + +import java.util.Arrays; + +public final class Matrices { + + private Matrices() { + throw new AssertionError("Cannot be instantiated"); + } + + public static int[][] cloneArrayOfInt1(int[][] source) { + + if (source == null) { + throw new IllegalArgumentException("The given array cannot be null"); + } + + int length = source.length; + int[][] target = new int[length][source[0].length]; + + for (int i = 0; i < length; i++) { + target[i] = source[i].clone(); + } + + return target; + } + + public static int[][] cloneArrayOfInt2(int[][] source) { + + if (source == null) { + throw new IllegalArgumentException("The given array cannot be null"); + } + + int length = source.length; + int[][] target = new int[length][source[0].length]; + for (int i = 0; i < length; i++) { + System.arraycopy(source[i], 0, target[i], 0, source[i].length); + } + return target; + } + + public static int[][] cloneArrayOfInt3(int[][] source) { + + if (source == null) { + throw new IllegalArgumentException("The given array cannot be null"); + } + + int length = source.length; + int[][] target = new int[length][]; + for (int i = 0; i < length; i++) { + target[i] = Arrays.copyOf(source[i], source[i].length); + } + return target; + } + + public static int[][] cloneArrayOfInt4(int[][] source) { + return Arrays.stream(source) + .map(int[]::clone) + .toArray(int[][]::new); + } + +} diff --git a/Chapter03/BONUS_1_ConvertYearMonthToDate/README.md b/Chapter03/BONUS_1_ConvertYearMonthToDate/README.md new file mode 100644 index 00000000..d654d971 --- /dev/null +++ b/Chapter03/BONUS_1_ConvertYearMonthToDate/README.md @@ -0,0 +1,2 @@ +# Converting `Date` to `YearMonth` +Write a program that converts an `Date` to `YearMonth` and vice-versa. diff --git a/Chapter03/BONUS_1_ConvertYearMonthToDate/pom.xml b/Chapter03/BONUS_1_ConvertYearMonthToDate/pom.xml new file mode 100644 index 00000000..fd4c512d --- /dev/null +++ b/Chapter03/BONUS_1_ConvertYearMonthToDate/pom.xml @@ -0,0 +1,14 @@ + + + 4.0.0 + com.app + BONUS_1_ConvertYearMonthToDate + 1.0-SNAPSHOT + jar + + UTF-8 + 13 + 13 + + BONUS_1_ConvertYearMonthToDate + \ No newline at end of file diff --git a/Chapter03/BONUS_1_ConvertYearMonthToDate/src/main/java/modern/challenge/Converters.java b/Chapter03/BONUS_1_ConvertYearMonthToDate/src/main/java/modern/challenge/Converters.java new file mode 100644 index 00000000..29ccc9c0 --- /dev/null +++ b/Chapter03/BONUS_1_ConvertYearMonthToDate/src/main/java/modern/challenge/Converters.java @@ -0,0 +1,33 @@ +package modern.challenge; + +import java.time.YearMonth; +import java.time.ZoneId; +import java.util.Date; + +public class Converters { + + private Converters() { + throw new AssertionError("Cannot be instantiatied"); + } + + public static YearMonth toYearMonth(Date date) { + + if (date == null) { + throw new IllegalArgumentException("The given date cannot be null"); + } + + return YearMonth.from(date.toInstant() + .atZone(ZoneId.systemDefault()) + .toLocalDate()); + } + + public static Date toDate(YearMonth ym) { + + if (ym == null) { + throw new IllegalArgumentException("The given year-month cannot be null"); + } + + return Date.from(ym.atDay(1) + .atStartOfDay(ZoneId.systemDefault()).toInstant()); + } +} diff --git a/Chapter03/BONUS_1_ConvertYearMonthToDate/src/main/java/modern/challenge/MainApplication.java b/Chapter03/BONUS_1_ConvertYearMonthToDate/src/main/java/modern/challenge/MainApplication.java new file mode 100644 index 00000000..f4b019e3 --- /dev/null +++ b/Chapter03/BONUS_1_ConvertYearMonthToDate/src/main/java/modern/challenge/MainApplication.java @@ -0,0 +1,13 @@ +package modern.challenge; + +import java.time.YearMonth; +import java.util.Date; + +public class MainApplication { + + public static void main(String[] args) { + + System.out.println("Date to YearMonth: " + Converters.toYearMonth(new Date())); + System.out.println("YearMonth to Date: " + Converters.toDate(YearMonth.now())); + } +} diff --git a/Chapter03/README.md b/Chapter03/README.md index 0a01b76a..9e889c5d 100644 --- a/Chapter03/README.md +++ b/Chapter03/README.md @@ -1,2 +1,2 @@ # Working with date and time -This chapter includes 20 problems that involves date and time. These problems are meant to cover a wide range of topics (e.g., converting, formatting, adding, subtracting, defining periods/durations, computing, etc) via **Date**, **Calendar**, **LocalDate**, **LocalTime**, **LocalDateTime**, **ZoneDateTime**, **OffsetDateTime**, **OffsetTime**, **Instant** and so on. +This chapter includes 20 problems that involves date and time. These problems are meant to cover a wide range of topics (e.g., converting, formatting, adding, subtracting, defining periods/durations, computing, etc) via **Date**, **Calendar**, **LocalDate**, **LocalTime**, **LocalDateTime**, **ZoneDateTime**, **OffsetDateTime**, **OffsetTime**, **Instant** and so on. diff --git a/Chapter05/BONUS_1_ChunkList/README.md b/Chapter05/BONUS_1_ChunkList/README.md new file mode 100644 index 00000000..910eb521 --- /dev/null +++ b/Chapter05/BONUS_1_ChunkList/README.md @@ -0,0 +1,23 @@ +**[How To Efficiently Chunk A Java List](https://github.com/AnghelLeonard/Hibernate-SpringBoot/tree/master/ChunkList)** + +If you prefer to read it as a blog-post containing the relevant snippets of code then check this post + +**Description:** Is a common scenario to have a big `List` and to need to chunk it in multiple smaller `List` of a given size. For example, if we want to employ a concurrent batch implementation we need to give each thread a sublist of items. Chunking a list can be done via Google Guava, `Lists.partition(List list, int size)` [method](https://guava.dev/releases/22.0/api/docs/com/google/common/collect/Lists.html#partition-java.util.List-int-) or Apache Commons Collections, `ListUtils.partition(List list, int size)` [method](https://commons.apache.org/proper/commons-collections/apidocs/org/apache/commons/collections4/ListUtils.html#partition(java.util.List,%20int)). But, it can be implemented in plain Java as well. This application exposes 6 ways to do it. The trade-off is between the speed of implementation and speed of execution. For example, while the implementation relying on grouping collectors is not performing very well, it is quite simple and fast to write it. + +**Key points:** +- the fastest execution is provided by `Chunk.java` class which relies on the built-in `List.subList()` method + +**Time-performance trend graphic for chunking 500, 1_000_000, 10_000_000 and 20_000_000 items in lists of 5 items:**\ +![](https://github.com/AnghelLeonard/Hibernate-SpringBoot/blob/master/ChunkList/head-to-head.png) + +----------------------------------------------------------------------------------------------------------------------- + + +
If you need a deep dive into the performance recipes exposed in this repository then I am sure that you will love my book "Spring Boot Persistence Best Practices"If you need a hand of tips and illustrations of 100+ Java persistence performance issues then "Java Persistence Performance Illustrated Guide" is for you.
+

+
+

+
+ +----------------------------------------------------------------------------------------------------------------------- + diff --git a/Chapter05/BONUS_1_ChunkList/head-to-head.png b/Chapter05/BONUS_1_ChunkList/head-to-head.png new file mode 100644 index 00000000..e3dc84d1 Binary files /dev/null and b/Chapter05/BONUS_1_ChunkList/head-to-head.png differ diff --git a/Chapter05/BONUS_1_ChunkList/pom.xml b/Chapter05/BONUS_1_ChunkList/pom.xml new file mode 100644 index 00000000..1230c71e --- /dev/null +++ b/Chapter05/BONUS_1_ChunkList/pom.xml @@ -0,0 +1,14 @@ + + + 4.0.0 + com.app + BONUS_1_ChunkList + 1.0-SNAPSHOT + jar + + UTF-8 + 13 + 13 + + BONUS_1_ChunkList + \ No newline at end of file diff --git a/Chapter05/BONUS_1_ChunkList/src/main/java/modern/challenge/Chunk.java b/Chapter05/BONUS_1_ChunkList/src/main/java/modern/challenge/Chunk.java new file mode 100644 index 00000000..1abfb22b --- /dev/null +++ b/Chapter05/BONUS_1_ChunkList/src/main/java/modern/challenge/Chunk.java @@ -0,0 +1,38 @@ +package modern.challenge; + +import java.util.AbstractList; +import java.util.ArrayList; +import java.util.List; + +public final class Chunk extends AbstractList> { + + private final List list; + private final int chunkSize; + + public Chunk(List list, int chunkSize) { + this.list = new ArrayList<>(list); + this.chunkSize = chunkSize; + } + + public static Chunk ofSize(List list, int chunkSize) { + return new Chunk<>(list, chunkSize); + } + + @Override + public List get(int index) { + int start = index * chunkSize; + int end = Math.min(start + chunkSize, list.size()); + + if (start > end) { + throw new IndexOutOfBoundsException( + "Index should range: 0, " + (size() - 1)); + } + + return new ArrayList<>(list.subList(start, end)); + } + + @Override + public int size() { + return (int) Math.ceil((double) list.size() / (double) chunkSize); + } +} diff --git a/Chapter05/BONUS_1_ChunkList/src/main/java/modern/challenge/Lists.java b/Chapter05/BONUS_1_ChunkList/src/main/java/modern/challenge/Lists.java new file mode 100644 index 00000000..24da88ff --- /dev/null +++ b/Chapter05/BONUS_1_ChunkList/src/main/java/modern/challenge/Lists.java @@ -0,0 +1,128 @@ +package modern.challenge; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Collector; +import java.util.stream.Collectors; + +public final class Lists { + + private Lists() { + throw new AssertionError(); + } + + public static Collection> toChunkV1(List list, int chunkSize) { + + if (list == null || list.size() < 2) { + throw new IllegalArgumentException("The list must have at least 1 element"); + } + + if (chunkSize < 1) { + throw new IllegalArgumentException("Chunk size should be minimum 1"); + } + + AtomicInteger counter = new AtomicInteger(); + Collection> result = list.stream() + .collect(Collectors.groupingBy(c -> counter.getAndIncrement() / chunkSize)) + .values(); + + return result; + } + + public static Collection> toChunkV2(List list, int chunkSize) { + + if (list == null || list.size() < 2) { + throw new IllegalArgumentException("The list must have at least 1 element"); + } + + if (chunkSize < 1) { + throw new IllegalArgumentException("Chunk size should be minimum 1"); + } + + AtomicInteger counter = new AtomicInteger(); + Collection> result = list.parallelStream() + .collect(Collectors.groupingBy(c -> counter.getAndIncrement() / chunkSize)) + .values(); + + return result; + } + + public static List> toChunkV3(List list, int chunkSize) { + + if (list == null || list.size() < 2) { + throw new IllegalArgumentException("The list must have at least 1 element"); + } + + if (chunkSize < 1) { + throw new IllegalArgumentException("Chunk size should be minimum 1"); + } + + AtomicInteger counter = new AtomicInteger(); + List> result = new ArrayList<>(); + for (T item : list) { + if (counter.getAndIncrement() % chunkSize == 0) { + result.add(new ArrayList<>()); + } + result.get(result.size() - 1).add(item); + } + + return result; + } + + public static List> toChunkV4(List list, int chunkSize) { + + if (list == null || list.size() < 2) { + throw new IllegalArgumentException("The list must have at least 1 element"); + } + + if (chunkSize < 1) { + throw new IllegalArgumentException("Chunk size should be minimum 1"); + } + + List> result = list.stream() + .collect(chunkIt(chunkSize)); + + return result; + } + + public static List> toChunkV5(List list, int chunkSize) { + + if (list == null || list.size() < 2) { + throw new IllegalArgumentException("The list must have at least 1 element"); + } + + if (chunkSize < 1) { + throw new IllegalArgumentException("Chunk size should be minimum 1"); + } + + List> result = list.parallelStream() + .collect(chunkIt(chunkSize)); + + return result; + } + + public static List> toChunkV6(List list, int chunkSize) { + + if (list == null || list.size() < 2) { + throw new IllegalArgumentException("The list must have at least 1 element"); + } + + if (chunkSize < 1) { + throw new IllegalArgumentException("Chunk size should be minimum 1"); + } + + List> result = Chunk.ofSize(list, chunkSize); + + return result; + } + + private static Collector, List>> chunkIt(int chunkSize) { + return Collector.of(ArrayList::new, List::add, (x, y) -> { + x.addAll(y); + return x; + }, x -> Chunk.ofSize(x, chunkSize), Collector.Characteristics.UNORDERED + ); + } +} diff --git a/Chapter05/BONUS_1_ChunkList/src/main/java/modern/challenge/MainApplication.java b/Chapter05/BONUS_1_ChunkList/src/main/java/modern/challenge/MainApplication.java new file mode 100644 index 00000000..52782245 --- /dev/null +++ b/Chapter05/BONUS_1_ChunkList/src/main/java/modern/challenge/MainApplication.java @@ -0,0 +1,44 @@ +package modern.challenge; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.TimeUnit; + +public class MainApplication { + + public static void main(String[] args) { + List list = new ArrayList<>(); + for (int i = 1; i <= 1_000_000; i++) { + list.add(i); + } + + long startTimeV1 = System.nanoTime(); + Lists.toChunkV1(list, 5);//.forEach(System.out::println); + displayExecutionTime(System.nanoTime() - startTimeV1); + + long startTimeV2 = System.nanoTime(); + Lists.toChunkV2(list, 5);//.forEach(System.out::println); + displayExecutionTime(System.nanoTime() - startTimeV2); + + long startTimeV3 = System.nanoTime(); + Lists.toChunkV3(list, 5);//.forEach(System.out::println); + displayExecutionTime(System.nanoTime() - startTimeV3); + + long startTimeV4 = System.nanoTime(); + Lists.toChunkV4(list, 5);//.forEach(System.out::println); + displayExecutionTime(System.nanoTime() - startTimeV4); + + long startTimeV5 = System.nanoTime(); + Lists.toChunkV5(list, 5);//.forEach(System.out::println); + displayExecutionTime(System.nanoTime() - startTimeV5); + + long startTimeV6 = System.nanoTime(); + Lists.toChunkV6(list, 5);//.forEach(System.out::println); + displayExecutionTime(System.nanoTime() - startTimeV6); + } + + private static void displayExecutionTime(long time) { + System.out.println("Execution time: " + time + " ns" + " (" + + TimeUnit.MILLISECONDS.convert(time, TimeUnit.NANOSECONDS) + " ms)"); + } +} diff --git a/Chapter05/BONUS_2_ConvertIterableToList/README.md b/Chapter05/BONUS_2_ConvertIterableToList/README.md new file mode 100644 index 00000000..cf84b634 --- /dev/null +++ b/Chapter05/BONUS_2_ConvertIterableToList/README.md @@ -0,0 +1,2 @@ +# Converting `Iterable` to `List` +Write a program that converts an `Iterable` to `List`. diff --git a/Chapter05/BONUS_2_ConvertIterableToList/pom.xml b/Chapter05/BONUS_2_ConvertIterableToList/pom.xml new file mode 100644 index 00000000..ef363031 --- /dev/null +++ b/Chapter05/BONUS_2_ConvertIterableToList/pom.xml @@ -0,0 +1,14 @@ + + + 4.0.0 + com.app + BONUS_2_ConvertIterableToList + 1.0-SNAPSHOT + jar + + UTF-8 + 13 + 13 + + BONUS_2_ConvertIterableToList + \ No newline at end of file diff --git a/Chapter05/BONUS_2_ConvertIterableToList/src/main/java/modern/challenge/Converters.java b/Chapter05/BONUS_2_ConvertIterableToList/src/main/java/modern/challenge/Converters.java new file mode 100644 index 00000000..8fb4844d --- /dev/null +++ b/Chapter05/BONUS_2_ConvertIterableToList/src/main/java/modern/challenge/Converters.java @@ -0,0 +1,97 @@ +package modern.challenge; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.Spliterator; +import java.util.Spliterators; +import java.util.stream.Collectors; +import java.util.stream.StreamSupport; + +public class Converters { + + private Converters() { + throw new AssertionError("Cannot be instantiatied"); + } + + public static List iterableToList1(Iterable iterable) { + + if (iterable == null) { + return Collections.emptyList(); + } + + List result = new ArrayList<>(); + iterable.forEach(result::add); + + return result; + } + + public static List iterableToList2(Iterable iterable) { + + if (iterable == null) { + return Collections.emptyList(); + } + + List result = StreamSupport.stream(iterable.spliterator(), false) + .collect(Collectors.toList()); + + return result; + } + + public static List iterableToList3(Iterable iterable) { + + if (iterable == null) { + return Collections.emptyList(); + } + + List result = new ArrayList<>(); + iterable.iterator().forEachRemaining(result::add); + + return result; + } + + public static List iterableToList4(Iterable iterable) { + + if (iterable == null) { + return Collections.emptyList(); + } + + List result + = StreamSupport.stream(Spliterators. + spliteratorUnknownSize(iterable.iterator(), Spliterator.ORDERED), false) + .collect(Collectors.toList()); + + return result; + } + + public static List iterableToList5(Iterable iterable) { + + if (iterable == null) { + return Collections.emptyList(); + } + + List result = new ArrayList<>(); + for (T elem : iterable) { + result.add(elem); + } + + return result; + } + + public static List iterableToList6(Iterable iterable) { + + if (iterable == null) { + return Collections.emptyList(); + } + + List result = new ArrayList<>(); + Iterator iterator = iterable.iterator(); + while (iterator.hasNext()) { + result.add(iterator.next()); + } + + return result; + } + +} diff --git a/Chapter05/BONUS_2_ConvertIterableToList/src/main/java/modern/challenge/MainApplication.java b/Chapter05/BONUS_2_ConvertIterableToList/src/main/java/modern/challenge/MainApplication.java new file mode 100644 index 00000000..a6252ed2 --- /dev/null +++ b/Chapter05/BONUS_2_ConvertIterableToList/src/main/java/modern/challenge/MainApplication.java @@ -0,0 +1,19 @@ +package modern.challenge; + +import java.util.Arrays; + +public class MainApplication { + + public static void main(String[] args) { + + // let's consider the next Iterable + Iterable iterable = Arrays.asList("ana", "george", "mark"); + + System.out.println("iterableToList1(): " + Converters.iterableToList1(iterable)); + System.out.println("iterableToList2(): " + Converters.iterableToList2(iterable)); + System.out.println("iterableToList3(): " + Converters.iterableToList3(iterable)); + System.out.println("iterableToList4(): " + Converters.iterableToList4(iterable)); + System.out.println("iterableToList5(): " + Converters.iterableToList5(iterable)); + System.out.println("iterableToList6(): " + Converters.iterableToList6(iterable)); + } +} diff --git a/Chapter05/BONUS_3_ConvertListVtoMapKListV/README.md b/Chapter05/BONUS_3_ConvertListVtoMapKListV/README.md new file mode 100644 index 00000000..9e830873 --- /dev/null +++ b/Chapter05/BONUS_3_ConvertListVtoMapKListV/README.md @@ -0,0 +1,3 @@ +# Convert `List` into `Map>` + +Write a program that converts `List` into `Map>`. diff --git a/Chapter05/BONUS_3_ConvertListVtoMapKListV/pom.xml b/Chapter05/BONUS_3_ConvertListVtoMapKListV/pom.xml new file mode 100644 index 00000000..bac0d2a9 --- /dev/null +++ b/Chapter05/BONUS_3_ConvertListVtoMapKListV/pom.xml @@ -0,0 +1,14 @@ + + + 4.0.0 + com.app + BONUS_3_ConvertListVtoMapKListV + 1.0-SNAPSHOT + jar + + UTF-8 + 13 + 13 + + BONUS_3_ConvertListVtoMapKListV + \ No newline at end of file diff --git a/Chapter05/BONUS_3_ConvertListVtoMapKListV/src/main/java/modern/challenge/Converters.java b/Chapter05/BONUS_3_ConvertListVtoMapKListV/src/main/java/modern/challenge/Converters.java new file mode 100644 index 00000000..562f7762 --- /dev/null +++ b/Chapter05/BONUS_3_ConvertListVtoMapKListV/src/main/java/modern/challenge/Converters.java @@ -0,0 +1,46 @@ +package modern.challenge; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.function.Supplier; +import java.util.stream.Collectors; + +public class Converters { + + private Converters() { + throw new AssertionError("Cannot be instantiatied"); + } + + public static Map> toMap(List list) { + + if (list == null || list.isEmpty()) { + return Collections.emptyMap(); + } + + return list.stream().collect( + Collectors.groupingBy(String::length, + HashMap::new, Collectors.toCollection(ArrayList::new)) + ); + } + + @SuppressWarnings("unchecked") + public static , M extends Map> M toMap( + List list, Function c, Supplier ms, Supplier cs) { + + if (list == null || c == null || ms == null || cs == null + || list.isEmpty()) { + + throw new IllegalArgumentException("Non of the arguments can be null or empty"); + } + + return list.stream().collect( + Collectors.groupingBy(c, ms, Collectors.toCollection(cs)) + ); + } + +} \ No newline at end of file diff --git a/Chapter05/BONUS_3_ConvertListVtoMapKListV/src/main/java/modern/challenge/MainApplication.java b/Chapter05/BONUS_3_ConvertListVtoMapKListV/src/main/java/modern/challenge/MainApplication.java new file mode 100644 index 00000000..e8f5dc42 --- /dev/null +++ b/Chapter05/BONUS_3_ConvertListVtoMapKListV/src/main/java/modern/challenge/MainApplication.java @@ -0,0 +1,26 @@ +package modern.challenge; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.List; + +public class MainApplication { + + public static void main(String[] args) { + + /* Convert List into Map> */ + // consider this list + List names + = List.of("joana", "mark", "adela", "leo", "stan", "marius", "kely"); + + HashMap> result1 + = Converters.toMap(names, String::length, HashMap::new, ArrayList::new); + System.out.println("HashMap>: " + result1); + + LinkedHashMap> result2 + = Converters.toMap(names, String::length, LinkedHashMap::new, LinkedList::new); + System.out.println("LinkedHashMap>: " + result2); + } +} diff --git a/Chapter05/P99_SortArray/src/modern/challenge/ArraySorts.java b/Chapter05/P99_SortArray/src/modern/challenge/ArraySorts.java index ed429e6e..b18603ce 100644 --- a/Chapter05/P99_SortArray/src/modern/challenge/ArraySorts.java +++ b/Chapter05/P99_SortArray/src/modern/challenge/ArraySorts.java @@ -437,7 +437,54 @@ void heapify(T[] arr, int n, int i, Comparator c) { } } - public static void bucketSort(int[] arr) { + /* Bucket sort - Scatter-Sort-Gather approach */ + public static void bucketSortSSG(int[] arr) { + + if (arr == null) { + throw new IllegalArgumentException("Array cannot be null"); + } + + int[] hashes = hash(arr); + + List[] buckets = new List[hashes[1]]; + for (int i = 0; i < hashes[1]; i++) { + buckets[i] = new ArrayList(); + } + + for (int e : arr) { + buckets[hash(e, hashes)].add(e); + } + + for (List bucket : buckets) { + Collections.sort(bucket); + } + + int p = 0; + for (List bucket : buckets) { + for (int j : bucket) { + arr[p++] = j; + } + } + } + + private static int[] hash(int[] arr) { + + int m = arr[0]; + for (int i = 1; i < arr.length; i++) { + if (m < arr[i]) { + m = arr[i]; + } + } + + return new int[]{m, (int) Math.sqrt(arr.length)}; + } + + private static int hash(int num, int[] hashes) { + return (int) ((double) num / hashes[0] * (hashes[1] - 1)); + } + + /* Bucket sort - Scatter-Gather approach */ + public static void bucketSortSG(int[] arr) { if (arr == null) { throw new IllegalArgumentException("Array cannot be null"); diff --git a/Chapter05/P99_SortArray/src/modern/challenge/Main.java b/Chapter05/P99_SortArray/src/modern/challenge/Main.java index d31641b7..676b8e17 100644 --- a/Chapter05/P99_SortArray/src/modern/challenge/Main.java +++ b/Chapter05/P99_SortArray/src/modern/challenge/Main.java @@ -151,7 +151,7 @@ public int compare(Melon melon1, Melon melon2) { System.out.println("\nSorting numbers ..."); int[] cloneIntegersBks = integers.clone(); long startTimeV13 = clock.millis(); - ArraySorts.bucketSort(cloneIntegersBks); + ArraySorts.bucketSortSG(cloneIntegersBks); // or call bucketSortSSG() displayExecutionTime(clock.millis() - startTimeV13); displayIntSortedArray(cloneIntegersBks); diff --git a/Chapter06/BONUS_1_GetCurrentProjectRootDirectory/README.md b/Chapter06/BONUS_1_GetCurrentProjectRootDirectory/README.md new file mode 100644 index 00000000..ae04a606 --- /dev/null +++ b/Chapter06/BONUS_1_GetCurrentProjectRootDirectory/README.md @@ -0,0 +1,2 @@ +# Current directory +Write a program that return the current project root directory diff --git a/Chapter06/BONUS_1_GetCurrentProjectRootDirectory/pom.xml b/Chapter06/BONUS_1_GetCurrentProjectRootDirectory/pom.xml new file mode 100644 index 00000000..db2d1fc8 --- /dev/null +++ b/Chapter06/BONUS_1_GetCurrentProjectRootDirectory/pom.xml @@ -0,0 +1,14 @@ + + + 4.0.0 + com.app + BONUS_1_GetCurrentProjectRootDirectory + 1.0-SNAPSHOT + jar + + UTF-8 + 13 + 13 + + BONUS_1_GetCurrentProjectRootDirectory + \ No newline at end of file diff --git a/Chapter06/BONUS_1_GetCurrentProjectRootDirectory/src/main/java/modern/challenge/MainApplication.java b/Chapter06/BONUS_1_GetCurrentProjectRootDirectory/src/main/java/modern/challenge/MainApplication.java new file mode 100644 index 00000000..dca8ec4e --- /dev/null +++ b/Chapter06/BONUS_1_GetCurrentProjectRootDirectory/src/main/java/modern/challenge/MainApplication.java @@ -0,0 +1,10 @@ +package modern.challenge; + +public class MainApplication { + + public static void main(String[] args) { + + System.out.println("The root directory of this project is:\n" + + Roots.getCurrentProjectRootDirectory()); + } +} diff --git a/Chapter06/BONUS_1_GetCurrentProjectRootDirectory/src/main/java/modern/challenge/Roots.java b/Chapter06/BONUS_1_GetCurrentProjectRootDirectory/src/main/java/modern/challenge/Roots.java new file mode 100644 index 00000000..82e892eb --- /dev/null +++ b/Chapter06/BONUS_1_GetCurrentProjectRootDirectory/src/main/java/modern/challenge/Roots.java @@ -0,0 +1,23 @@ +package modern.challenge; + +import java.nio.file.Path; +import java.nio.file.Paths; + +public class Roots { + + private Roots() { + throw new AssertionError("Cannot be instantiatied"); + } + + public static String getCurrentProjectRootDirectory() { + + String userDirectory = System.getProperty("user.dir"); + Path rootDirectory = Paths.get(".").normalize().toAbsolutePath(); + + if (rootDirectory.startsWith(userDirectory)) { + return rootDirectory.toString(); + } else { + throw new RuntimeException("Cannot find the current project root directory"); + } + } +} diff --git a/Chapter06/BONUS_2_CopyFileBenchmark/nb-configuration.xml b/Chapter06/BONUS_2_CopyFileBenchmark/nb-configuration.xml new file mode 100644 index 00000000..ec4540cb --- /dev/null +++ b/Chapter06/BONUS_2_CopyFileBenchmark/nb-configuration.xml @@ -0,0 +1,18 @@ + + + + + + none + + diff --git a/Chapter06/BONUS_2_CopyFileBenchmark/pom.xml b/Chapter06/BONUS_2_CopyFileBenchmark/pom.xml new file mode 100644 index 00000000..7eb5ecbf --- /dev/null +++ b/Chapter06/BONUS_2_CopyFileBenchmark/pom.xml @@ -0,0 +1,72 @@ + + + 4.0.0 + java.modern.challenge + BONUS_2_CopyFileBenchmark + 1.0 + jar + + UTF-8 + 20 + 20 + 3.8.0 + 1.35 + 3.10.1 + 3.1.0 + + BONUS_2_CopyFileBenchmark + + + org.openjdk.jmh + jmh-core + ${jmh.version} + + + org.openjdk.jmh + jmh-generator-annprocess + ${jmh.version} + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${oamp.version} + + + + org.openjdk.jmh + jmh-generator-annprocess + ${jmh.version} + + + + + + org.codehaus.mojo + exec-maven-plugin + ${ocm.version} + + + run-benchmarks + integration-test + + exec + + + test + java + + -classpath + + org.openjdk.jmh.Main + .* + + + + + + + + \ No newline at end of file diff --git a/Chapter06/BONUS_2_CopyFileBenchmark/rafa_copy/README.txt b/Chapter06/BONUS_2_CopyFileBenchmark/rafa_copy/README.txt new file mode 100644 index 00000000..ac6d0fc6 --- /dev/null +++ b/Chapter06/BONUS_2_CopyFileBenchmark/rafa_copy/README.txt @@ -0,0 +1 @@ +In this folder we copy the file used by benchmark. \ No newline at end of file diff --git a/Chapter06/BONUS_2_CopyFileBenchmark/rafa_org/Rafa Best Shots.mp4 b/Chapter06/BONUS_2_CopyFileBenchmark/rafa_org/Rafa Best Shots.mp4 new file mode 100644 index 00000000..166777eb Binary files /dev/null and b/Chapter06/BONUS_2_CopyFileBenchmark/rafa_org/Rafa Best Shots.mp4 differ diff --git a/Chapter06/BONUS_2_CopyFileBenchmark/results/benchmark.png b/Chapter06/BONUS_2_CopyFileBenchmark/results/benchmark.png new file mode 100644 index 00000000..e91d5bde Binary files /dev/null and b/Chapter06/BONUS_2_CopyFileBenchmark/results/benchmark.png differ diff --git a/Chapter06/BONUS_2_CopyFileBenchmark/src/main/java/modern/challenge/Main.java b/Chapter06/BONUS_2_CopyFileBenchmark/src/main/java/modern/challenge/Main.java new file mode 100644 index 00000000..3f8042d7 --- /dev/null +++ b/Chapter06/BONUS_2_CopyFileBenchmark/src/main/java/modern/challenge/Main.java @@ -0,0 +1,246 @@ +package modern.challenge; + +import java.nio.MappedByteBuffer; +import java.io.OutputStream; +import java.io.InputStream; +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.channels.FileChannel; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; +import java.util.EnumSet; +import static java.nio.file.LinkOption.NOFOLLOW_LINKS; +import java.util.Random; +import java.util.concurrent.TimeUnit; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; + +@OutputTimeUnit(TimeUnit.SECONDS) +@BenchmarkMode(Mode.AverageTime) +@Fork(value = 1, warmups = 1) //, jvmArgsPrepend = {"-Djdk.net.usePlainSocketImpl=true"}) +@Measurement(iterations = 1, time = 1) +@State(Scope.Benchmark) +public class Main { + + private static final Path COPY_FROM = Paths.get("rafa_org/Rafa Best Shots.mp4"); + private static final Path COPY_TO = Paths.get("rafa_copy/"); + private static final int BUFFER_SIZE_KB = 4; + private static final int BUFFER_SIZE = BUFFER_SIZE_KB * 1024; + + private static final Random rnd = new Random(); + + @Benchmark + public static void fileChannelIndirectBuffer() { + + System.out.println("Using FileChannel and non-direct buffer ..."); + + Path copyTo = COPY_TO.resolve("Rafa Best Shots " + rnd.nextInt() + ".mp4"); + try (FileChannel fileChannel_from = (FileChannel.open(COPY_FROM, EnumSet.of(StandardOpenOption.READ))); + FileChannel fileChannel_to = (FileChannel.open(copyTo, EnumSet.of(StandardOpenOption.CREATE_NEW, StandardOpenOption.WRITE)))) { + + // Allocate an non-direct ByteBuffer + ByteBuffer bytebuffer = ByteBuffer.allocate(BUFFER_SIZE); + + // Read data from file into ByteBuffer + while ((fileChannel_from.read(bytebuffer)) > 0) { + + //flip the buffer which set the limit to current position, and position to 0 + bytebuffer.flip(); + + //write data from ByteBuffer to file + fileChannel_to.write(bytebuffer); + + //for the next read + bytebuffer.clear(); + } + } catch (IOException ex) { + System.err.println(ex); + } + } + + @Benchmark + public static void fileChannelDirectBuffer() { + + System.out.println("Using FileChannel and direct buffer ..."); + + Path copyTo = COPY_TO.resolve("Rafa Best Shots " + rnd.nextInt() + ".mp4"); + try (FileChannel fileChannel_from = (FileChannel.open(COPY_FROM, EnumSet.of(StandardOpenOption.READ))); + FileChannel fileChannel_to = (FileChannel.open(copyTo, EnumSet.of(StandardOpenOption.CREATE_NEW, StandardOpenOption.WRITE)))) { + + // Allocate an direct ByteBuffer + ByteBuffer bytebuffer = ByteBuffer.allocateDirect(BUFFER_SIZE); + + // Read data from file into ByteBuffer + while ((fileChannel_from.read(bytebuffer)) > 0) { + + //flip the buffer which set the limit to current position, and position to 0 + bytebuffer.flip(); + + //write data from ByteBuffer to file + fileChannel_to.write(bytebuffer); + + //for the next read + bytebuffer.clear(); + } + } catch (IOException ex) { + System.err.println(ex); + } + } + + @Benchmark + public static void fileChannelTransferTo() { + + System.out.println("Using FileChannel.transferTo method ..."); + + Path copyTo = COPY_TO.resolve("Rafa Best Shots " + rnd.nextInt() + ".mp4"); + try (FileChannel fileChannel_from = (FileChannel.open( + COPY_FROM, EnumSet.of(StandardOpenOption.READ))); + FileChannel fileChannel_to = (FileChannel.open(copyTo, EnumSet.of( + StandardOpenOption.CREATE_NEW, StandardOpenOption.WRITE)))) { + + fileChannel_from.transferTo(0L, fileChannel_from.size(), fileChannel_to); + + } catch (IOException ex) { + System.err.println(ex); + } + } + + @Benchmark + public static void fileChannelTransferFrom() { + + System.out.println("Using FileChannel.transferFrom method ..."); + + Path copyTo = COPY_TO.resolve("Rafa Best Shots " + rnd.nextInt() + ".mp4"); + try (FileChannel fileChannel_from = (FileChannel.open( + COPY_FROM, EnumSet.of(StandardOpenOption.READ))); + FileChannel fileChannel_to = (FileChannel.open(copyTo, EnumSet.of( + StandardOpenOption.CREATE_NEW, StandardOpenOption.WRITE)))) { + + fileChannel_to.transferFrom(fileChannel_from, 0L, (int) fileChannel_from.size()); + } catch (IOException ex) { + System.err.println(ex); + } + } + + @Benchmark + public static void fileChannelMap() { + + System.out.println("Using FileChannel.map method ..."); + + Path copyTo = COPY_TO.resolve("Rafa Best Shots " + rnd.nextInt() + ".mp4"); + try (FileChannel fileChannel_from = (FileChannel.open(COPY_FROM, EnumSet.of(StandardOpenOption.READ))); + FileChannel fileChannel_to = (FileChannel.open(copyTo, EnumSet.of(StandardOpenOption.CREATE_NEW, StandardOpenOption.WRITE)))) { + + MappedByteBuffer buffer = fileChannel_from.map( + FileChannel.MapMode.READ_ONLY, 0, fileChannel_from.size()); + + fileChannel_to.write(buffer); + buffer.clear(); + + } catch (IOException ex) { + System.err.println(ex); + } + } + + @Benchmark + public static void bufferedStreamIO() { + + System.out.println("Using buffered streams and byte array ..."); + + Path copyTo = COPY_TO.resolve("Rafa Best Shots " + rnd.nextInt() + ".mp4"); + File inFileStr = COPY_FROM.toFile(); + File outFileStr = copyTo.toFile(); + + try (BufferedInputStream in = new BufferedInputStream( + new FileInputStream(inFileStr)); BufferedOutputStream out + = new BufferedOutputStream(new FileOutputStream(outFileStr))) { + + byte[] byteArray = new byte[BUFFER_SIZE]; + int bytesCount; + while ((bytesCount = in.read(byteArray)) != -1) { + out.write(byteArray, 0, bytesCount); + } + } catch (IOException ex) { + System.err.println(ex); + } + } + + @Benchmark + public static void bufferedStreamByteArray() { + + System.out.println("Using un-buffered streams and byte array ..."); + + Path copyTo = COPY_TO.resolve("Rafa Best Shots " + rnd.nextInt() + ".mp4"); + File inFileStr = COPY_FROM.toFile(); + File outFileStr = copyTo.toFile(); + + try (FileInputStream in = new FileInputStream(inFileStr); + FileOutputStream out = new FileOutputStream(outFileStr)) { + + byte[] byteArray = new byte[BUFFER_SIZE]; + int bytesCount; + while ((bytesCount = in.read(byteArray)) != -1) { + out.write(byteArray, 0, bytesCount); + } + } catch (IOException ex) { + System.err.println(ex); + } + } + + @Benchmark + public static void filesCopyPathToPath() { + + System.out.println("Using Files.copy (Path to Path) method ..."); + + Path copyTo = COPY_TO.resolve("Rafa Best Shots " + rnd.nextInt() + ".mp4"); + try { + Files.copy(COPY_FROM, copyTo, NOFOLLOW_LINKS); + } catch (IOException e) { + System.err.println(e); + } + } + + @Benchmark + public static void filesCopyIStreamToPath() { + + System.out.println("Using Files.copy (InputStream to Path) ..."); + + Path copyTo = COPY_TO.resolve("Rafa Best Shots " + rnd.nextInt() + ".mp4"); + try (InputStream is = new FileInputStream(COPY_FROM.toFile())) { + Files.copy(is, copyTo); + } catch (IOException e) { + System.err.println(e); + } + } + + @Benchmark + public static void filesCopyPathToOStream() { + + System.out.println("Using Files.copy (Path to OutputStream) ..."); + + Path copyTo = COPY_TO.resolve("Rafa Best Shots " + rnd.nextInt() + ".mp4"); + try (OutputStream os = new FileOutputStream(copyTo.toFile())) { + Files.copy(COPY_FROM, os); + } catch (IOException e) { + System.err.println(e); + } + } + + public static void main(String[] args) throws IOException { + + org.openjdk.jmh.Main.main(args); + } +} \ No newline at end of file diff --git a/Chapter06/README.md b/Chapter06/README.md index d66c8649..8eb91c42 100644 --- a/Chapter06/README.md +++ b/Chapter06/README.md @@ -1,3 +1,3 @@ -# Java I/O - Paths, files, buffers, scanning and formatting +# Java I/O - Paths, files, buffers, scanning and formatting This chapter includes 20 problems that involve Java I/O for files. From manipulating, walking and watching paths to streaming files and efficient ways for reading/writing text and binary files, we will cover a hand of problems that are a must in the arsenal of any Java developer. diff --git a/Chapter09/BONUS_1_ArrayToStreamAndBack/README.md b/Chapter09/BONUS_1_ArrayToStreamAndBack/README.md new file mode 100644 index 00000000..64dfb690 --- /dev/null +++ b/Chapter09/BONUS_1_ArrayToStreamAndBack/README.md @@ -0,0 +1,2 @@ +# Map a stream +Write a helper method that uses **Stream#map()** to convert **List< P >** in **List< Q >**. Write a heper method that does the same thing for arrays. diff --git a/Chapter09/BONUS_1_ArrayToStreamAndBack/pom.xml b/Chapter09/BONUS_1_ArrayToStreamAndBack/pom.xml new file mode 100644 index 00000000..342b55c6 --- /dev/null +++ b/Chapter09/BONUS_1_ArrayToStreamAndBack/pom.xml @@ -0,0 +1,14 @@ + + + 4.0.0 + coding.challenge + BONUS_1_ArrayToStreamAndBack + 1.0 + jar + + UTF-8 + 13 + 13 + + BONUS_1_ArrayToStreamAndBack + \ No newline at end of file diff --git a/Chapter09/BONUS_1_ArrayToStreamAndBack/src/main/java/modern/challenge/Convertors.java b/Chapter09/BONUS_1_ArrayToStreamAndBack/src/main/java/modern/challenge/Convertors.java new file mode 100644 index 00000000..4b43ef37 --- /dev/null +++ b/Chapter09/BONUS_1_ArrayToStreamAndBack/src/main/java/modern/challenge/Convertors.java @@ -0,0 +1,62 @@ +package modern.challenge; + +import java.util.Arrays; +import java.util.stream.IntStream; +import java.util.stream.Stream; + +public final class Convertors { + + private Convertors() { + throw new AssertionError("Cannot be instantiated"); + } + + // Convert array of T to stream via Arrays#stream() + public static Stream toStream1(T[] arr) { + + if (arr == null) { + throw new IllegalArgumentException("Inputs cannot be null"); + } + + return Arrays.stream(arr); + } + + // Convert array of T to stream via Stream#of() + public static Stream toStream2(T[] arr) { + + if (arr == null) { + throw new IllegalArgumentException("Inputs cannot be null"); + } + + return Stream.of(arr); + } + + // Convert array of T to stream via List#stream() + public static Stream toStream3(T[] arr) { + + if (arr == null) { + throw new IllegalArgumentException("Inputs cannot be null"); + } + + return Arrays.asList(arr).stream(); + } + + // Convert array of primitves (int) to stream via Arrays#stream() + public static IntStream toStream4(int[] arr) { + + if (arr == null) { + throw new IllegalArgumentException("Inputs cannot be null"); + } + + return Arrays.stream(arr); + } + + // Convert array of primitves (int) to stream via IntStream#of() + public static IntStream toStream5(int[] arr) { + + if (arr == null) { + throw new IllegalArgumentException("Inputs cannot be null"); + } + + return IntStream.of(arr); + } +} diff --git a/Chapter09/BONUS_1_ArrayToStreamAndBack/src/main/java/modern/challenge/Main.java b/Chapter09/BONUS_1_ArrayToStreamAndBack/src/main/java/modern/challenge/Main.java new file mode 100644 index 00000000..f4f2c3d8 --- /dev/null +++ b/Chapter09/BONUS_1_ArrayToStreamAndBack/src/main/java/modern/challenge/Main.java @@ -0,0 +1,35 @@ +package modern.challenge; + +public class Main { + + public static void main(String[] args) { + + Melon[] melons = { + new Melon("Gac", 1200), + new Melon("Hemi", 2300), + new Melon("Apollo", 3400) + }; + + int[] weights = {1200, 2300, 3400}; + + System.out.println("Array of melons to stream (toStream1()):"); + Convertors.toStream1(melons) + .forEach(System.out::println); + + System.out.println("\n\nArray of melons to stream (toStream2()):"); + Convertors.toStream2(melons) + .forEach(System.out::println); + + System.out.println("\n\nArray of melons to stream (toStream3()):"); + Convertors.toStream3(melons) + .forEach(System.out::println); + + System.out.println("\n\nArray of integers to stream (toStream4()):"); + Convertors.toStream4(weights) + .forEach(System.out::println); + + System.out.println("\n\nArray of integers to stream (toStream5()):"); + Convertors.toStream5(weights) + .forEach(System.out::println); + } +} diff --git a/Chapter09/BONUS_1_ArrayToStreamAndBack/src/main/java/modern/challenge/Melon.java b/Chapter09/BONUS_1_ArrayToStreamAndBack/src/main/java/modern/challenge/Melon.java new file mode 100644 index 00000000..283b6b4c --- /dev/null +++ b/Chapter09/BONUS_1_ArrayToStreamAndBack/src/main/java/modern/challenge/Melon.java @@ -0,0 +1,70 @@ +package modern.challenge; + +import java.util.Objects; + +public class Melon { + + private String type; + private int weight; + + public Melon(String type, int weight) { + this.type = type; + this.weight = weight; + } + + public String getType() { + return type; + } + + public int getWeight() { + return weight; + } + + public void setType(String type) { + this.type = type; + } + + public void setWeight(int weight) { + this.weight = weight; + } + + @Override + public String toString() { + return type + "(" + weight + "g)"; + } + + @Override + public int hashCode() { + int hash = 7; + hash = 37 * hash + Objects.hashCode(this.type); + hash = 37 * hash + this.weight; + return hash; + } + + @Override + public boolean equals(Object obj) { + + if (this == obj) { + return true; + } + + if (obj == null) { + return false; + } + + if (getClass() != obj.getClass()) { + return false; + } + + final Melon other = (Melon) obj; + if (this.weight != other.weight) { + return false; + } + + if (!Objects.equals(this.type, other.type)) { + return false; + } + return true; + } + +} diff --git a/Chapter09/P182_MapStreamHelpers/README.md b/Chapter09/P182_MapStreamHelpers/README.md new file mode 100644 index 00000000..64dfb690 --- /dev/null +++ b/Chapter09/P182_MapStreamHelpers/README.md @@ -0,0 +1,2 @@ +# Map a stream +Write a helper method that uses **Stream#map()** to convert **List< P >** in **List< Q >**. Write a heper method that does the same thing for arrays. diff --git a/Chapter09/P182_MapStreamHelpers/pom.xml b/Chapter09/P182_MapStreamHelpers/pom.xml new file mode 100644 index 00000000..95f8fb5f --- /dev/null +++ b/Chapter09/P182_MapStreamHelpers/pom.xml @@ -0,0 +1,14 @@ + + + 4.0.0 + coding.challenge + P182_MapStreamHelpers + 1.0 + jar + + UTF-8 + 13 + 13 + + P182_MapStreamHelpers + \ No newline at end of file diff --git a/Chapter09/P182_MapStreamHelpers/src/main/java/modern/challenge/Convertors.java b/Chapter09/P182_MapStreamHelpers/src/main/java/modern/challenge/Convertors.java new file mode 100644 index 00000000..74b63ec6 --- /dev/null +++ b/Chapter09/P182_MapStreamHelpers/src/main/java/modern/challenge/Convertors.java @@ -0,0 +1,38 @@ +package modern.challenge; + +import java.util.Arrays; +import java.util.List; +import java.util.function.Function; +import java.util.function.IntFunction; +import java.util.stream.Collectors; + +public final class Convertors { + + private Convertors() { + throw new AssertionError("Cannot be instantiated"); + } + + // converter for lists + public static List list(List

source, Function f) { + + if(source == null || f == null) { + throw new IllegalArgumentException("Inputs cannot be null"); + } + + return source.stream() + .map(f) + .collect(Collectors.toList()); + } + + // converter for arrays + public static Q[] array(P[] source, Function f, IntFunction generator) { + + if(source == null || f == null || generator == null) { + throw new IllegalArgumentException("Inputs cannot be null"); + } + + return Arrays.stream(source) + .map(f) + .toArray(generator); + } +} diff --git a/Chapter09/P182_MapStreamHelpers/src/main/java/modern/challenge/Main.java b/Chapter09/P182_MapStreamHelpers/src/main/java/modern/challenge/Main.java new file mode 100644 index 00000000..9c060a16 --- /dev/null +++ b/Chapter09/P182_MapStreamHelpers/src/main/java/modern/challenge/Main.java @@ -0,0 +1,22 @@ +package modern.challenge; + +import java.util.Arrays; +import java.util.List; + +public class Main { + + public static void main(String[] args) { + + System.out.println("Convert list of String to list of ints:"); + List strList = Arrays.asList("11", "22", "33"); + List intList = Convertors.list(strList, Integer::parseInt); + System.out.println("strList: " + strList); + System.out.println("intList: " + intList); + + System.out.println("\n\nConvert array of String to array of doubles:"); + String[] strArr = {"11", "22", "34"}; + Double[] doubleArr = Convertors.array(strArr, Double::parseDouble, Double[]::new); + System.out.println("strArr: " + Arrays.toString(strArr)); + System.out.println("doubleArr: " + Arrays.toString(doubleArr)); + } +} diff --git a/README.md b/README.md index 0f781169..aab522f6 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,9 @@ + + + # Java Coding Problems -Java Coding Problems +Java Coding Problems This is the code repository for [Java Coding Problems ](https://www.packtpub.com/programming/java-coding-problems?utm_source=github&utm_medium=repository&utm_campaign=), published by Packt. @@ -68,3 +71,7 @@ He is the author of several books, videos, and dozens of articles related to Jav [Click here](https://docs.google.com/forms/d/e/1FAIpQLSdy7dATC6QmEL81FIUuymZ0Wy9vH1jHkvpY57OiMeKGqib_Ow/viewform) if you have any feedback or suggestions. +### Download a free PDF + + If you have already purchased a print or Kindle version of this book, you can get a DRM-free PDF version at no cost.
Simply click on the link to claim your free PDF.
+

https://packt.link/free-ebook/9781789801415