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 13cd9fd6..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/Chapter02/P55_JDK13_SwitchExpression/nbactions.xml b/Chapter02/P55_JDK13_SwitchExpression/nbactions.xml new file mode 100644 index 00000000..5eeab2ce --- /dev/null +++ b/Chapter02/P55_JDK13_SwitchExpression/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 + + + --enable-preview -agentlib:jdwp=transport=dt_socket,server=n,address=${jpda.address} -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/P55_JDK13_SwitchExpression/pom.xml b/Chapter02/P55_JDK13_SwitchExpression/pom.xml new file mode 100644 index 00000000..f57f835e --- /dev/null +++ b/Chapter02/P55_JDK13_SwitchExpression/pom.xml @@ -0,0 +1,28 @@ + + + 4.0.0 + modern.challenge + P55_JDK13_SwitchExpression + 1.0 + jar + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.3 + + + --enable-preview + + + + + + + UTF-8 + 13 + 13 + + P55_JDK13_SwitchExpression + \ No newline at end of file diff --git a/Chapter02/P55_JDK13_SwitchExpression/src/main/java/modern/challenge/FootballPlayer.java b/Chapter02/P55_JDK13_SwitchExpression/src/main/java/modern/challenge/FootballPlayer.java new file mode 100644 index 00000000..73962dbc --- /dev/null +++ b/Chapter02/P55_JDK13_SwitchExpression/src/main/java/modern/challenge/FootballPlayer.java @@ -0,0 +1,4 @@ +package modern.challenge; + +public class FootballPlayer extends Player { +} diff --git a/Chapter02/P55_JDK13_SwitchExpression/src/main/java/modern/challenge/Main.java b/Chapter02/P55_JDK13_SwitchExpression/src/main/java/modern/challenge/Main.java new file mode 100644 index 00000000..78044d88 --- /dev/null +++ b/Chapter02/P55_JDK13_SwitchExpression/src/main/java/modern/challenge/Main.java @@ -0,0 +1,91 @@ +package modern.challenge; + +public class Main { + + public enum PlayerTypes { + TENNIS, + FOOTBALL, + SNOOKER, + UNKNOWN + } + + public static void main(String[] args) { + // switch statement + Player playerSwitchStatementUgly = createPlayerSwitchStatementUgly(PlayerTypes.TENNIS); + Player playerSwitchStatementNice = createPlayerSwitchStatementNice(PlayerTypes.TENNIS); + + // switch expression + Player playerSwitchExpression = createPlayerSwitchExpression(PlayerTypes.TENNIS); + Player playerSwitchExpressionYield = createPlayerSwitchExpressionBreak(PlayerTypes.TENNIS); + } + + private static Player createPlayerSwitchStatementUgly(PlayerTypes playerType) { + + Player player = null; + + switch (playerType) { + case TENNIS: + player = new TennisPlayer(); + break; + case FOOTBALL: + player = new FootballPlayer(); + break; + case SNOOKER: + player = new SnookerPlayer(); + break; + case UNKNOWN: + throw new UnknownPlayerException("Player type is unknown"); + default: + throw new IllegalArgumentException("Invalid player type: " + playerType); + } + + return player; + } + + private static Player createPlayerSwitchStatementNice(PlayerTypes playerType) { + switch (playerType) { + case TENNIS: + return new TennisPlayer(); + case FOOTBALL: + return new FootballPlayer(); + case SNOOKER: + return new SnookerPlayer(); + case UNKNOWN: + throw new UnknownPlayerException("Player type is unknown"); + default: + throw new IllegalArgumentException("Invalid player type: " + playerType); + } + } + + private static Player createPlayerSwitchExpression(PlayerTypes playerType) { + return switch (playerType) { + case TENNIS-> + new TennisPlayer(); + case FOOTBALL-> + new FootballPlayer(); + case SNOOKER-> + new SnookerPlayer(); + case UNKNOWN-> + throw new UnknownPlayerException("Player type is unknown"); + // default is not mandatory + default-> + throw new IllegalArgumentException("Invalid player type: " + playerType); + }; + } + + private static Player createPlayerSwitchExpressionBreak(PlayerTypes playerType) { + return switch (playerType) { + case TENNIS: + yield new TennisPlayer(); + case FOOTBALL: + yield new FootballPlayer(); + case SNOOKER: + yield new SnookerPlayer(); + case UNKNOWN: + throw new UnknownPlayerException("Player type is unknown"); + // default is not mandatory + default: + throw new IllegalArgumentException("Invalid player type: " + playerType); + }; + } +} diff --git a/Chapter07/P159_InvokeInstanceMethod/src/modern/challenge/Slice.java b/Chapter02/P55_JDK13_SwitchExpression/src/main/java/modern/challenge/Player.java similarity index 52% rename from Chapter07/P159_InvokeInstanceMethod/src/modern/challenge/Slice.java rename to Chapter02/P55_JDK13_SwitchExpression/src/main/java/modern/challenge/Player.java index f6898043..88317dd2 100644 --- a/Chapter07/P159_InvokeInstanceMethod/src/modern/challenge/Slice.java +++ b/Chapter02/P55_JDK13_SwitchExpression/src/main/java/modern/challenge/Player.java @@ -1,4 +1,4 @@ package modern.challenge; -public class Slice { +public class Player { } diff --git a/Chapter02/P55_JDK13_SwitchExpression/src/main/java/modern/challenge/SnookerPlayer.java b/Chapter02/P55_JDK13_SwitchExpression/src/main/java/modern/challenge/SnookerPlayer.java new file mode 100644 index 00000000..62337313 --- /dev/null +++ b/Chapter02/P55_JDK13_SwitchExpression/src/main/java/modern/challenge/SnookerPlayer.java @@ -0,0 +1,4 @@ +package modern.challenge; + +public class SnookerPlayer extends Player { +} diff --git a/Chapter02/P55_JDK13_SwitchExpression/src/main/java/modern/challenge/TennisPlayer.java b/Chapter02/P55_JDK13_SwitchExpression/src/main/java/modern/challenge/TennisPlayer.java new file mode 100644 index 00000000..a18f05bc --- /dev/null +++ b/Chapter02/P55_JDK13_SwitchExpression/src/main/java/modern/challenge/TennisPlayer.java @@ -0,0 +1,4 @@ +package modern.challenge; + +public class TennisPlayer extends Player{ +} diff --git a/Chapter02/P55_JDK13_SwitchExpression/src/main/java/modern/challenge/UnknownPlayerException.java b/Chapter02/P55_JDK13_SwitchExpression/src/main/java/modern/challenge/UnknownPlayerException.java new file mode 100644 index 00000000..670b2f2b --- /dev/null +++ b/Chapter02/P55_JDK13_SwitchExpression/src/main/java/modern/challenge/UnknownPlayerException.java @@ -0,0 +1,22 @@ +package modern.challenge; + +public class UnknownPlayerException extends RuntimeException { + + private static final long serialVersionUID = 1L; + + public UnknownPlayerException() { + super(); + } + + public UnknownPlayerException(String message) { + super(message); + } + + public UnknownPlayerException(Throwable cause) { + super(cause); + } + + public UnknownPlayerException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/Chapter02/P57_JDK13_StatementBlocks/nbactions.xml b/Chapter02/P57_JDK13_StatementBlocks/nbactions.xml new file mode 100644 index 00000000..5eeab2ce --- /dev/null +++ b/Chapter02/P57_JDK13_StatementBlocks/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 + + + --enable-preview -agentlib:jdwp=transport=dt_socket,server=n,address=${jpda.address} -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/P57_JDK13_StatementBlocks/pom.xml b/Chapter02/P57_JDK13_StatementBlocks/pom.xml new file mode 100644 index 00000000..9043210c --- /dev/null +++ b/Chapter02/P57_JDK13_StatementBlocks/pom.xml @@ -0,0 +1,28 @@ + + + 4.0.0 + modern.challenge + P57_JDK13_StatementBlocks + 1.0 + jar + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.3 + + + --enable-preview + + + + + + + UTF-8 + 13 + 13 + + P57_JDK13_StatementBlocks + \ No newline at end of file diff --git a/Chapter02/P57_JDK13_StatementBlocks/src/main/java/modern/challenge/FootballPlayer.java b/Chapter02/P57_JDK13_StatementBlocks/src/main/java/modern/challenge/FootballPlayer.java new file mode 100644 index 00000000..73962dbc --- /dev/null +++ b/Chapter02/P57_JDK13_StatementBlocks/src/main/java/modern/challenge/FootballPlayer.java @@ -0,0 +1,4 @@ +package modern.challenge; + +public class FootballPlayer extends Player { +} diff --git a/Chapter02/P57_JDK13_StatementBlocks/src/main/java/modern/challenge/Main.java b/Chapter02/P57_JDK13_StatementBlocks/src/main/java/modern/challenge/Main.java new file mode 100644 index 00000000..4fbc498c --- /dev/null +++ b/Chapter02/P57_JDK13_StatementBlocks/src/main/java/modern/challenge/Main.java @@ -0,0 +1,33 @@ +package modern.challenge; + +public class Main { + + public enum PlayerTypes { + TENNIS, + FOOTBALL, + SNOOKER + } + + public static void main(String[] args) { + Player player = createPlayer(PlayerTypes.SNOOKER); + } + + private static Player createPlayer(PlayerTypes playerType) { + return switch (playerType) { + case TENNIS-> { + System.out.println("Creating a TennisPlayer ..."); + yield new TennisPlayer(); + } + case FOOTBALL-> { + System.out.println("Creating a FootballPlayer ..."); + yield new FootballPlayer(); + } + case SNOOKER-> { + System.out.println("Creating a SnookerPlayer ..."); + yield new SnookerPlayer(); + } + default-> + throw new IllegalArgumentException("Invalid player type: " + playerType); + }; + } +} diff --git a/Chapter02/P57_JDK13_StatementBlocks/src/main/java/modern/challenge/Player.java b/Chapter02/P57_JDK13_StatementBlocks/src/main/java/modern/challenge/Player.java new file mode 100644 index 00000000..88317dd2 --- /dev/null +++ b/Chapter02/P57_JDK13_StatementBlocks/src/main/java/modern/challenge/Player.java @@ -0,0 +1,4 @@ +package modern.challenge; + +public class Player { +} diff --git a/Chapter02/P57_JDK13_StatementBlocks/src/main/java/modern/challenge/SnookerPlayer.java b/Chapter02/P57_JDK13_StatementBlocks/src/main/java/modern/challenge/SnookerPlayer.java new file mode 100644 index 00000000..62337313 --- /dev/null +++ b/Chapter02/P57_JDK13_StatementBlocks/src/main/java/modern/challenge/SnookerPlayer.java @@ -0,0 +1,4 @@ +package modern.challenge; + +public class SnookerPlayer extends Player { +} diff --git a/Chapter02/P57_JDK13_StatementBlocks/src/main/java/modern/challenge/TennisPlayer.java b/Chapter02/P57_JDK13_StatementBlocks/src/main/java/modern/challenge/TennisPlayer.java new file mode 100644 index 00000000..a18f05bc --- /dev/null +++ b/Chapter02/P57_JDK13_StatementBlocks/src/main/java/modern/challenge/TennisPlayer.java @@ -0,0 +1,4 @@ +package modern.challenge; + +public class TennisPlayer extends Player{ +} diff --git a/Chapter02/P57_JDK13_StatementBlocks/src/main/java/modern/challenge/UnknownPlayerException.java b/Chapter02/P57_JDK13_StatementBlocks/src/main/java/modern/challenge/UnknownPlayerException.java new file mode 100644 index 00000000..670b2f2b --- /dev/null +++ b/Chapter02/P57_JDK13_StatementBlocks/src/main/java/modern/challenge/UnknownPlayerException.java @@ -0,0 +1,22 @@ +package modern.challenge; + +public class UnknownPlayerException extends RuntimeException { + + private static final long serialVersionUID = 1L; + + public UnknownPlayerException() { + super(); + } + + public UnknownPlayerException(String message) { + super(message); + } + + public UnknownPlayerException(Throwable cause) { + super(cause); + } + + public UnknownPlayerException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/Chapter02/README.md b/Chapter02/README.md index e547470a..ffa7152c 100644 --- a/Chapter02/README.md +++ b/Chapter02/README.md @@ -1,2 +1,2 @@ # Objects, immutability and switch expressions -This chapter includes 18 problems that involves objects, immutability and switch expressions. The chapter starts with several problems about dealing with null references. It continues with problems regarding checking indexes, **equals()** and **hashCode()**, and immutability (e.g., writing immutable classes, passing/returning mutable objects from immutable classes). The last part of the chapter deals with cloning objects and JDK 12 switch expressions. +This chapter includes 18 problems that involves objects, immutability and switch expressions. The chapter starts with several problems about dealing with null references. It continues with problems regarding checking indexes, **equals()** and **hashCode()**, and immutability (e.g., writing immutable classes, passing/returning mutable objects from immutable classes). The last part of the chapter deals with cloning objects and JDK 12 switch expressions. 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 55e31a7b..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/Chapter04/README.md b/Chapter04/README.md index 1afa8090..c2814a0b 100644 --- a/Chapter04/README.md +++ b/Chapter04/README.md @@ -1,4 +1,4 @@ # Type inference This chapter includes 21 problems that involves JEP 286, Java Local Variable Type Inference (LVTI), or shortly, the **var** type. These problems has been carefully crafted to reveal the best practices and common mistakes involved in using **var**. -At the end of this chapter, you will have under the tool belt everything you need to know about **var** to push it in production. +At the end of this chapter, you will have under the tool belt everything you need to know about **var** to push it in production. 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/Chapter05/README.md b/Chapter05/README.md index 2e63f1fa..2e2a6468 100644 --- a/Chapter05/README.md +++ b/Chapter05/README.md @@ -1,2 +1,2 @@ # Arrays, collections and data structures -This chapter includes 30 problems that involve arrays, collections, and several data structures. The aim is to provide solutions to a category of problems encountered in a wide range of applications such as, sorting, finding, comparing, ordering, reversing, filling, merging, copying, replacing and so on and forth. The provided solutions are implemented in Java 8-12 and they can be used as the base for solving other related problems as well. +This chapter includes 30 problems that involve arrays, collections, and several data structures. The aim is to provide solutions to a category of problems encountered in a wide range of applications such as, sorting, finding, comparing, ordering, reversing, filling, merging, copying, replacing and so on and forth. The provided solutions are implemented in Java 8-12 and they can be used as the base for solving other related problems as well. 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/P140_SearchInBigFiles/src/modern/challenge/TextFiles.java b/Chapter06/P140_SearchInBigFiles/src/modern/challenge/TextFiles.java index caea98f5..f5ab6a8f 100644 --- a/Chapter06/P140_SearchInBigFiles/src/modern/challenge/TextFiles.java +++ b/Chapter06/P140_SearchInBigFiles/src/modern/challenge/TextFiles.java @@ -15,7 +15,7 @@ public final class TextFiles { - private static final int MAP_SIZE = 5242880; // 5 MB in bytes + private static final long MAP_SIZE = 5242880; // 5 MB in bytes private TextFiles() { throw new AssertionError("Cannot be instantiated"); @@ -109,7 +109,7 @@ public static long countOccurrencesV4(Path path, String text, Charset ch) throws return count; } - public static int countOccurrencesV5(Path path, String text) throws IOException { + public static long countOccurrencesV5(Path path, String text) throws IOException { if (path == null || text == null) { throw new IllegalArgumentException("Path/text cannot be null"); @@ -121,20 +121,20 @@ public static int countOccurrencesV5(Path path, String text) throws IOException final byte[] texttofind = text.getBytes(StandardCharsets.UTF_8); - int count = 0; + long count = 0; try (FileChannel fileChannel = FileChannel.open(path, StandardOpenOption.READ)) { - int position = 0; + long position = 0; long length = fileChannel.size(); while (position < length) { long remaining = length - position; - int bytestomap = (int) Math.min(MAP_SIZE, remaining); + long bytestomap = (long) Math.min(MAP_SIZE, remaining); MappedByteBuffer mbBuffer = fileChannel.map(MapMode.READ_ONLY, position, bytestomap); - int limit = mbBuffer.limit(); - int lastSpace = -1; - int firstChar = -1; + long limit = mbBuffer.limit(); + long lastSpace = -1; + long firstChar = -1; while (mbBuffer.hasRemaining()) { boolean isFirstChar = false; diff --git a/Chapter06/README.md b/Chapter06/README.md index 8a3c5bf4..8eb91c42 100644 --- a/Chapter06/README.md +++ b/Chapter06/README.md @@ -1,2 +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/Chapter07/README.md b/Chapter07/README.md index f9b92c7f..7746ad88 100644 --- a/Chapter07/README.md +++ b/Chapter07/README.md @@ -1,2 +1,2 @@ # Java Reflection Classes, interfaces, constructors, methods and fields -This chapter includes 17 problems that involve the Java Reflection API. From classical topics, such as inspecting and instantiating Java artifacts (e.g., modules, packages, classes, interfaces, super-classes, constructors, methods, annotations, arrays, etc), to synthetic and bridge constructs or nest-based access control (JDK 11), this chapter provides solid coverage of the Java Reflection API. +This chapter includes 17 problems that involve the Java Reflection API. From classical topics, such as inspecting and instantiating Java artifacts (e.g., modules, packages, classes, interfaces, super-classes, constructors, methods, annotations, arrays, etc), to synthetic and bridge constructs or nest-based access control (JDK 11), this chapter provides solid coverage of the Java Reflection API. diff --git a/Chapter08/README.md b/Chapter08/README.md index 00cae2b7..6006e80b 100644 --- a/Chapter08/README.md +++ b/Chapter08/README.md @@ -3,5 +3,5 @@ Chapter 8 and 9 includes 33 problems that involve Java functional style programm complete journey from 0 to functional interfaces. It continues with a suite of design patterns from GoF interpreted in Java functional style. Next, we focus on several problems that involves classical operations encountered in streams (e.g., filter, map, etc), we discuss infinite streams, null-safe streams and default methods. A comprehensive list of problems covers grouping, partitioning, and collectors, -including JDK 12 **teeing()** collector and writing a custom collector. In addition, **takeWhile()**, **dropWhile()**, composing functions, predicates +including JDK 12 **teeing()** collector and writing a custom collector. In addition, **takeWhile()**, **dropWhile()**, composing functions, predicates and comparators, testing and debugging lambdas, and other cool topics are discussed as well. 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/Chapter09/README.md b/Chapter09/README.md index 7b751c9e..854c459d 100644 --- a/Chapter09/README.md +++ b/Chapter09/README.md @@ -1,4 +1,4 @@ -# Functional style programming - Deep dive +# Functional style programming - Deep dive Chapter 8 and 9 includes 33 problems that involve Java functional style programming. The chapter starts with a problem meant to provide a complete journey from 0 to functional interfaces. It continues with a suite of design patterns from GoF interpreted in Java functional style. Next, we focus on several problems that involves classical operations encountered in streams (e.g., filter, map, etc), we discuss diff --git a/Chapter10/README.md b/Chapter10/README.md index 13891a49..eea1e59c 100644 --- a/Chapter10/README.md +++ b/Chapter10/README.md @@ -1,4 +1,4 @@ -# Concurrency - Thread pools, Callables and Synchronizers +# Concurrency - Thread pools, Callables and Synchronizers Chapters 10 and 11 includes 27 problems that involve Java concurrency. It starts with fundamental problems about threads lifecycle and object/class level locking. It continues with a bunch of problems about thread pools in Java including JDK 8 work-stealing thread pool. Afterwards, we have problems dedicated to **Callable**, **Future** and **CompletableFuture**. Next, we dedicate several problems to Java synchronizers (e.g., barrier, diff --git a/Chapter11/README.md b/Chapter11/README.md index 82bdaf69..8c1b977c 100644 --- a/Chapter11/README.md +++ b/Chapter11/README.md @@ -3,4 +3,4 @@ Chapters 10 and 11 includes 27 problems that involve Java concurrency. It starts level locking. It continues with a bunch of problems about thread pools in Java including JDK 8 work-stealing thread pool. Afterwards, we have problems dedicated to **Callable**, **Future** and **CompletableFuture**. Next, we dedicate several problems to Java synchronizers (e.g., barrier, semaphore, exchanger, etc). Finally, we have problems for fork/join framework, **ReentrantLock**, **ReentrantReadWriteLock**, **StampedLock**, atomic - variables, tasks cancellation, interruptible methods, and deadlocks. + variables, tasks cancellation, interruptible methods, and deadlocks. diff --git a/Chapter12/README.md b/Chapter12/README.md index c9b097f2..db142d5c 100644 --- a/Chapter12/README.md +++ b/Chapter12/README.md @@ -1,6 +1,6 @@ -# Optional +# Optional This chapter includes 24 problems meant to draw several rules for working with **Optional**. The problems and solutions presented in this section -are based on the Brian Goetz (Java’s language architect) definition: *Optional is intended to provide a limited mechanism for library method -return types where there needed to be a clear way to represent “no result," and using null for such was overwhelmingly likely to cause errors.* +are based on the Brian Goetz (Java’s language architect) definition: *Optional is intended to provide a limited mechanism for library method +return types where there needed to be a clear way to represent “no result," and using null for such was overwhelmingly likely to cause errors.* But, where there are rules there are exceptions as well. Therefore, do not conclude that the rules (or practices) presented here should be -followed (or avoided) at all costs. Like always, it’s an it depends problem that requires to evaluate the situation and weight pros and cons. +followed (or avoided) at all costs. Like always, it’s an it depends problem that requires to evaluate the situation and weight pros and cons. diff --git a/Chapter13/README.md b/Chapter13/README.md index a003d4eb..379e1d5b 100644 --- a/Chapter13/README.md +++ b/Chapter13/README.md @@ -1,4 +1,4 @@ -# The HTTP Client and WebSocket APIs +# The HTTP Client and WebSocket APIs This chapter includes 20 problems that are meant to cover the HTTP Client and WebSocket APIs. Do you remember `HttpUrlConnection`? Well, JDK 11 comes with the HTTP Client API as a reinvention of `HttpUrlConnection`. diff --git a/README.md b/README.md index 423b5990..aab522f6 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,77 @@ -# The-Modern-Java-Challenge -The Modern Java Challenge, published by Packt Publishing + + + +# 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. + +**Improve your Java Programming skills by solving real-world coding challenges** + +## What is this book about? +* Adopt the latest JDK 8 - JDK 13 features in your applications +* Solve cutting-edge problems relating to collections and data structures +* Get to grips with functional-style programming using lambdas +* Perform asynchronous communication and parallel data processing +* Solve strings and number problems using the latest Java APIs +* Become familiar with different aspects of object immutability in Java +* Implement the correct practices and clean code techniques + +This book covers the following exciting features: + + +If you feel this book is for you, get your [copy](https://www.amazon.com/dp/1789801419) today! + + + +## Instructions and Navigations +All of the code is organized into folders. For example, Chapter02. + +The code will look like the following: +``` +public Map countDuplicateCharacters(String str) { + + Map result = new HashMap<>(); + + // or use for(char ch: str.toCharArray()) { ... } + for (int i = 0; i (v == null) ? 1 : ++v); + } + + return result; +} +``` + +**Following is what you need for this book:** +If you are a Java developer who wants to level-up by solving real-world problems, then this book is for you. Working knowledge of Java is required to get the most out of this book. + +With the following software and hardware list you can run all code files present in the book (Chapter 1-13). +### Software and Hardware List +| Chapter | Software required | OS required | +| -------- | ------------------------------------ | ----------------------------------- | +| 1-13 | JDK | Windows, Mac OS X, and Linux (Any) | + +We also provide a PDF file that has color images of the screenshots/diagrams used in this book. [Click here to download it](https://static.packt-cdn.com/downloads/9781789801415_ColorImages.pdf). + +### Related products +* Learn Java 12 Programming [[Packt]](https://www.packtpub.com/in/application-development/learn-java-12-programming?utm_source=github&utm_medium=repository&utm_campaign=) [[Amazon]](https://www.amazon.com/dp/1789957052) + +* Java 11 and 12 - New Features [[Packt]](https://www.packtpub.com/application-development/java-11-and-12-new-features?utm_source=github&utm_medium=repository&utm_campaign=) [[Amazon]](https://www.amazon.com/dp/1789133270) + +## Get to Know the Author +**Anghel Leonard** +is a Chief Technology Strategist with more than 20 years of experience in the Java ecosystem. In his daily work, he is focused on architecting and developing Java distributed applications that empower robust architectures, clean code, and high performance. He is also passionate about coaching, mentoring, and technical leadership. + +He is the author of several books, videos, and dozens of articles related to Java technologies. + +### Suggestions and Feedback +[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