diff --git a/.classpath b/.classpath
deleted file mode 100644
index e6bcceb..0000000
--- a/.classpath
+++ /dev/null
@@ -1,65 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/.factorypath b/.factorypath
deleted file mode 100644
index bd949bb..0000000
--- a/.factorypath
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
diff --git a/pom.xml b/pom.xml
index 919e238..5af383f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -59,7 +59,7 @@
org.projectlombok
lombok
- 1.18.26
+ 1.18.32
provided
@@ -207,11 +207,12 @@
21
21
+ true
org.projectlombok
lombok
- 1.18.30
+ 1.18.32
io.soabase.record-builder
@@ -224,6 +225,7 @@
${jmh.version}
+ --enable-preview
diff --git a/splash.png b/splash.png
new file mode 100644
index 0000000..bccfe40
Binary files /dev/null and b/splash.png differ
diff --git a/src/main/java/com/howtodoinjava/algorithms/IsomorphicStrings.java b/src/main/java/com/howtodoinjava/algorithms/IsomorphicStrings.java
new file mode 100644
index 0000000..491ee0f
--- /dev/null
+++ b/src/main/java/com/howtodoinjava/algorithms/IsomorphicStrings.java
@@ -0,0 +1,34 @@
+package com.howtodoinjava.algorithms;
+
+public class IsomorphicStrings {
+
+ public boolean areIsomorphic(String s1, String s2) {
+ if (s1 == null || s2 == null
+ || s1.length() != s2.length()) {
+ return false;
+ }
+
+ int[] arr1 = new int[256];
+ int[] arr2 = new int[256];
+
+ for (int i = 0; i < s1.length(); i++) {
+
+ char c1 = s1.charAt(i);
+ char c2 = s2.charAt(i);
+
+ if (arr1[c1] != arr2[c2]) {
+ return false;
+ }
+
+ arr1[c1] = i + 1;
+ arr2[c2] = i + 1;
+ }
+ return true;
+ }
+
+ public static void main(String[] args) {
+ IsomorphicStrings iso = new IsomorphicStrings();
+ System.out.println(iso.areIsomorphic("abbcdd", "qwwcrr")); // true
+ System.out.println(iso.areIsomorphic("aab", "que")); // false
+ }
+}
diff --git a/src/main/java/com/howtodoinjava/concurrency/SharedSeedExample.java b/src/main/java/com/howtodoinjava/concurrency/SharedSeedExample.java
new file mode 100644
index 0000000..9a28802
--- /dev/null
+++ b/src/main/java/com/howtodoinjava/concurrency/SharedSeedExample.java
@@ -0,0 +1,55 @@
+package com.howtodoinjava.concurrency;
+
+import java.security.SecureRandom;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.atomic.AtomicInteger;
+
+public class SharedSeedExample {
+
+ private static final int THREAD_COUNT = 5;
+ private static final int ITERATIONS_PER_THREAD = 10;
+ private static ExecutorService executorService = Executors.newFixedThreadPool(THREAD_COUNT);
+
+ private static final AtomicInteger sharedCounter = new AtomicInteger(0);
+
+ public static void main(String[] args) {
+ System.out.println("Using a shared Random instance:");
+ java.util.Random sharedRandom = new java.util.Random();
+
+ for (int i = 0; i < THREAD_COUNT; i++) {
+ executorService.submit(() -> {
+ for (int j = 0; j < ITERATIONS_PER_THREAD; j++) {
+ int randomNumber = sharedRandom.nextInt();
+ processRandomNumber(randomNumber);
+ }
+ });
+ }
+
+ System.out.println("\nUsing a shared SecureRandom instance:");
+ SecureRandom sharedSecureRandom = new SecureRandom();
+
+ for (int i = 0; i < THREAD_COUNT; i++) {
+ executorService.submit(() -> {
+ for (int j = 0; j < ITERATIONS_PER_THREAD; j++) {
+ int randomNumber = sharedSecureRandom.nextInt();
+ processRandomNumber(randomNumber);
+ }
+ });
+ }
+ shutdownExecutor(executorService);
+ }
+
+ private static void processRandomNumber(int randomNumber) {
+ // Simulate some processing of the random number
+ sharedCounter.incrementAndGet();
+ }
+
+ private static void shutdownExecutor(ExecutorService executorService) {
+ executorService.shutdown();
+ while (!executorService.isTerminated()) {
+ // Wait for all threads to finish
+ }
+ System.out.println(STR."The counter value: \{sharedCounter.get()}");
+ }
+}
diff --git a/src/main/java/com/howtodoinjava/concurrency/virtualThreads/ExecutorExample.java b/src/main/java/com/howtodoinjava/concurrency/virtualThreads/ExecutorExample.java
new file mode 100644
index 0000000..d52bb86
--- /dev/null
+++ b/src/main/java/com/howtodoinjava/concurrency/virtualThreads/ExecutorExample.java
@@ -0,0 +1,30 @@
+package com.howtodoinjava.concurrency.virtualThreads;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+
+public class ExecutorExample {
+
+ void main(String[] args) throws InterruptedException {
+
+ List numList = Arrays.asList(1, 2, 3, 4, 5);
+
+ ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor();
+
+ numList.forEach(num ->
+ executor.execute(() -> {
+ System.out.println(STR."Square of \{num} is :: \{square(num)}");
+ })
+ );
+
+ executor.awaitTermination(2, TimeUnit.SECONDS);
+ executor.shutdown();
+ }
+
+ private Integer square(Integer num) {
+ return num * num;
+ }
+}
diff --git a/src/main/java/com/howtodoinjava/core/basic/AllPrimeFactors.java b/src/main/java/com/howtodoinjava/core/basic/AllPrimeFactors.java
new file mode 100644
index 0000000..5b1399f
--- /dev/null
+++ b/src/main/java/com/howtodoinjava/core/basic/AllPrimeFactors.java
@@ -0,0 +1,30 @@
+package com.howtodoinjava.core.basic;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class AllPrimeFactors {
+
+ public static void main(String[] args) {
+ System.out.println(primeFactors(90));
+ System.out.println(primeFactors(190));
+ System.out.println(primeFactors(350));
+ }
+
+ public static List primeFactors(int v) {
+ List factorsList = new ArrayList<>();
+ int s = 2;
+
+ while (v > 1) {
+ // each perfect division give us a prime factor
+ if (v % s == 0) {
+ factorsList.add(s);
+ v = v / s;
+ } else {
+ s++;
+ }
+ }
+
+ return factorsList;
+ }
+}
diff --git a/src/main/java/com/howtodoinjava/core/basic/CharacterEncodingExample.java b/src/main/java/com/howtodoinjava/core/basic/CharacterEncodingExample.java
new file mode 100644
index 0000000..dc6e676
--- /dev/null
+++ b/src/main/java/com/howtodoinjava/core/basic/CharacterEncodingExample.java
@@ -0,0 +1,25 @@
+package com.howtodoinjava.core.basic;
+
+import java.nio.charset.Charset;
+
+public class CharacterEncodingExample {
+
+ public static void main(String[] args) {
+ String fileCoding = System.getProperty("file.encoding");
+ System.out.println(STR."Default Character Encoding: \{fileCoding}");
+
+ String filePathEncoding = System.getProperty("sun.jnu.encoding");
+ System.out.println(STR."Default File Path Encoding: \{filePathEncoding}");
+
+ String defaultCharset = Charset.defaultCharset().displayName();
+ System.out.println(STR."Default Charset Name: \{defaultCharset}");
+
+ /*System.setProperty("file.encoding", "UTF-16");
+ System.setProperty("sun.jnu.encoding", "UTF-16");*/
+
+ defaultCharset = System.out.charset().displayName();
+ System.out.println(STR."Default Character Encoding: \{defaultCharset}");
+
+ System.out.println("The façade pattern is a software-design pattern.");
+ }
+}
diff --git a/src/main/java/com/howtodoinjava/core/basic/ObjectIdentityString.java b/src/main/java/com/howtodoinjava/core/basic/ObjectIdentityString.java
new file mode 100644
index 0000000..593de92
--- /dev/null
+++ b/src/main/java/com/howtodoinjava/core/basic/ObjectIdentityString.java
@@ -0,0 +1,33 @@
+package com.howtodoinjava.core.basic;
+
+import java.util.Objects;
+import lombok.AllArgsConstructor;
+
+public class ObjectIdentityString {
+
+ public static void main(String[] args) {
+ Record record = new Record(1L, "record name");
+
+ System.out.println(record);
+
+ System.out.println(record != null ? Objects.toIdentityString(record) : "null");
+
+ System.out.println(getIdentityString(record));
+ }
+
+ static String getIdentityString(Object object) {
+ return object.getClass().getName() + "@"
+ + Integer.toHexString(System.identityHashCode(object));
+ }
+}
+
+@AllArgsConstructor
+class Record {
+ long id;
+ String name;
+
+ @Override
+ public String toString() {
+ return STR."Record{id=\{id}, name='\{name}\{'\''}\{'}'}";
+ }
+}
diff --git a/src/main/java/com/howtodoinjava/core/basic/StricfpExample.java b/src/main/java/com/howtodoinjava/core/basic/StricfpExample.java
new file mode 100644
index 0000000..6d7ac88
--- /dev/null
+++ b/src/main/java/com/howtodoinjava/core/basic/StricfpExample.java
@@ -0,0 +1,22 @@
+package com.howtodoinjava.core.basic;
+
+public class StricfpExample {
+
+ public static void main(String[] args) {
+ runMethod();
+ }
+
+ strictfp public static void runMethod() {
+ double x = 5.899999;
+ double y = 13.888345;
+ double z = 14.463534545;
+
+ double m1 = (x * y) * z; // 1185.1596894396725
+ double m2 = (x * (y * z)); // 1185.1596894396728
+
+ System.out.println(m1);
+ System.out.println(m2);
+
+ System.out.println(m1 == m2); //false
+ }
+}
diff --git a/src/main/java/com/howtodoinjava/core/basic/math/MathAbsoluteExamples.java b/src/main/java/com/howtodoinjava/core/basic/math/MathAbsoluteExamples.java
new file mode 100644
index 0000000..893e2fe
--- /dev/null
+++ b/src/main/java/com/howtodoinjava/core/basic/math/MathAbsoluteExamples.java
@@ -0,0 +1,28 @@
+package com.howtodoinjava.core.basic.math;
+
+public class MathAbsoluteExamples {
+
+ public static void main(String[] args) {
+
+ double doubleValue = -10.56;
+ float floatValue = -7.8f;
+ int intValue = -15;
+ long longValue = -123456789L;
+
+ System.out.println(STR."Absolute value of double: \{Math.abs(doubleValue)}");
+ System.out.println(STR."Absolute value of float: \{Math.abs(floatValue)}");
+ System.out.println(STR."Absolute value of int: \{Math.abs(intValue)}");
+ System.out.println(STR."Absolute value of long: \{Math.abs(longValue)}");
+
+ //Overflow / Underflow Issue
+
+ int intMinValue = Integer.MIN_VALUE;
+ long longMinValue = Long.MIN_VALUE;
+
+ System.out.println(STR."Absolute value of int: \{Math.abs(intMinValue)}");
+ System.out.println(STR."Absolute value of long: \{Math.abs(longMinValue)}");
+
+ System.out.println(STR."Absolute value of int: \{Math.absExact(intMinValue)}");
+ System.out.println(STR."Absolute value of long: \{Math.absExact(longMinValue)}");
+ }
+}
diff --git a/src/main/java/com/howtodoinjava/core/basic/math/MathDivideExact.java b/src/main/java/com/howtodoinjava/core/basic/math/MathDivideExact.java
new file mode 100644
index 0000000..7e46c7d
--- /dev/null
+++ b/src/main/java/com/howtodoinjava/core/basic/math/MathDivideExact.java
@@ -0,0 +1,33 @@
+package com.howtodoinjava.core.basic.math;
+
+import java.util.function.BinaryOperator;
+
+public class MathDivideExact {
+
+ public static void main(String[] args) {
+
+ int result = 100 / -1;
+ System.out.println(result);
+
+ System.out.println(Integer.MAX_VALUE);
+ int x = Integer.MIN_VALUE;
+ System.out.println(x);
+ int quotient1 = x/-1; // -2,147,483,648
+ System.out.println(quotient1);
+
+ long y = Integer.MIN_VALUE;
+ long quotient2 = y/-1; // 2,147,483,648
+ System.out.println(quotient2);
+
+ int quotientExactFine = Math.divideExact(4, -1);
+ System.out.println(quotientExactFine);
+
+ int quotientExactEx = Math.divideExact(x, -1);
+ System.out.println(quotientExactEx);
+
+ BinaryOperator operator = Math::divideExact;
+ int quotientExactBo = operator.apply(x, -1);
+ System.out.println(quotientExactBo);
+ }
+
+}
diff --git a/src/main/java/com/howtodoinjava/core/basic/math/MathFloorDivCeilDiv.java b/src/main/java/com/howtodoinjava/core/basic/math/MathFloorDivCeilDiv.java
new file mode 100644
index 0000000..54fa75e
--- /dev/null
+++ b/src/main/java/com/howtodoinjava/core/basic/math/MathFloorDivCeilDiv.java
@@ -0,0 +1,9 @@
+package com.howtodoinjava.core.basic.math;
+
+public class MathFloorDivCeilDiv {
+
+ public static void main(String[] args) {
+
+ }
+
+}
diff --git a/src/main/java/com/howtodoinjava/core/collections/map/ImmutableMap.java b/src/main/java/com/howtodoinjava/core/collections/map/ImmutableMap.java
index 69fcba4..1d0cd5d 100644
--- a/src/main/java/com/howtodoinjava/core/collections/map/ImmutableMap.java
+++ b/src/main/java/com/howtodoinjava/core/collections/map/ImmutableMap.java
@@ -3,13 +3,65 @@
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
+import java.util.Map.Entry;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static java.util.Map.entry;
+import static java.util.stream.Collectors.*;
public class ImmutableMap {
+
public static void main(String[] args) {
+ //1
Map immutableMap = Map.of("key1", "value1");
-
//throws java.lang.UnsupportedOperationException
- immutableMap.put("key2", "value2");
+ //immutableMap.put("key2", "value2");
+
+ //2
+ Map map = new HashMap<>();
+ map.put("key 1", "value 1");
+ map.put("key 2", "value 2");
+ map.put("key 3", "value 3");
+
+ Map imap = Map.copyOf(map);
+ //modify the original map
+ map.put("key 4", "value 4");
+
+ System.out.println(map); // {key 4=value 4, key 3=value 3, key 2=value 2, key 1=value 1}
+ System.out.println(imap); // {key 3=value 3, key 1=value 1, key 2=value 2}
+
+ imap = Collections.unmodifiableMap(map);
+ //immutableMap.put("key2", "value2");
+
+ System.out.println(imap);
+
+ imap = Stream.of(
+ entry("key 1", "value 1"),
+ entry("key 2", "value 2"),
+ entry("key 3", "value 3"))
+ .collect(toUnmodifiableMap(e->e.getKey(), e->e.getValue()));
+
+ imap.put("key 4", "value 4");
+
+ System.out.println(imap);
+
+ imap = Map.ofEntries(
+ entry("key 1", null),
+ entry("key 2", "value 2"),
+ entry("key 3", "value 3"),
+ entry("key 4", "value 4"),
+ entry("key 5", "value 5"),
+ entry("key 6", "value 6"),
+ entry("key 7", "value 7"),
+ entry("key 8", "value 8"),
+ entry("key 9", "value 9"),
+ entry("key 10", "value 10"),
+ entry("key 11", "value 11"),
+ entry("key 12", "value 12")
+ );
+
+ System.out.println(imap);
}
}
diff --git a/src/main/java/com/howtodoinjava/core/collections/map/InitializeHashMap.java b/src/main/java/com/howtodoinjava/core/collections/map/InitializeHashMap.java
new file mode 100644
index 0000000..2f49400
--- /dev/null
+++ b/src/main/java/com/howtodoinjava/core/collections/map/InitializeHashMap.java
@@ -0,0 +1,46 @@
+package com.howtodoinjava.core.collections.map;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+public class InitializeHashMap {
+
+ public static void main(String[] args) {
+
+ // Empty maps
+ HashMap map1 = new HashMap<>();
+ HashMap map2 = new HashMap<>(10);
+ HashMap map3 = HashMap.newHashMap(10);
+
+ // Pre-populated maps
+ HashMap map4 = new HashMap<>(
+ Map.ofEntries(
+ Map.entry("key1", "value1"),
+ Map.entry("key2", "value3"))
+ );
+
+ Map map5 = new HashMap<>() {{
+ put("key1", "value1");
+ put("key2", "value2");
+ }};
+
+ HashMap map6 = new HashMap<>(
+ Map.of("key1", "value1", "key2", "value3")
+ );
+
+ // Immutable maps
+ Map singleEntryMap = Collections.singletonMap("key", "value");
+ Map emptyMap = Collections.emptyMap();
+
+ //Collecting Stream to Map
+ //More examples: https://howtodoinjava.com/java8/collect-stream-to-map/
+ Stream stream = Stream.of(new String[][] {
+ { "Hello", "World" },
+ { "John", "Doe" },
+ });
+ Map map7 = stream.collect(Collectors.toMap(pair -> pair[0], pair -> pair[1]));
+ }
+}
diff --git a/src/main/java/com/howtodoinjava/core/datatypes/Employee.java b/src/main/java/com/howtodoinjava/core/datatypes/Employee.java
new file mode 100644
index 0000000..5568253
--- /dev/null
+++ b/src/main/java/com/howtodoinjava/core/datatypes/Employee.java
@@ -0,0 +1,28 @@
+package com.howtodoinjava.core.datatypes;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+public class Employee {
+
+ public static void main(String[] args) {
+ Stream tokenStream = Stream.of("A", "B", "C", "D");
+ ArrayList tokenList = tokenStream.collect(Collectors.toCollection(ArrayList::new));
+ tokenList.add("e");
+ System.out.println(tokenList);
+
+ List list = Arrays.asList("A", "B", "C");
+ list.add("e");
+ System.out.println(list);
+
+ ArrayList arraylist = new ArrayList<>(Arrays.asList("A", "B", "C"));
+ }
+
+}
+
+
diff --git a/src/main/java/com/howtodoinjava/core/datetime/ConvertBetweenMonthNameAndNumber.java b/src/main/java/com/howtodoinjava/core/datetime/ConvertBetweenMonthNameAndNumber.java
new file mode 100644
index 0000000..16bdd09
--- /dev/null
+++ b/src/main/java/com/howtodoinjava/core/datetime/ConvertBetweenMonthNameAndNumber.java
@@ -0,0 +1,66 @@
+package com.howtodoinjava.core.datetime;
+
+import java.time.Month;
+import java.time.format.TextStyle;
+import java.util.Arrays;
+import java.util.Locale;
+import java.util.Optional;
+
+public class ConvertBetweenMonthNameAndNumber {
+
+ public static void main(String[] args) {
+
+ // MONTH NUMBER -> NAME
+
+ System.out.println(monthNumberToAbbr(1));
+ System.out.println(monthNumberToFullName(1));
+ System.out.println(monthNumberToName(1));
+
+ // MONTH ABBR -> Number
+
+ System.out.println(monthNameToNumber("January"));
+ System.out.println(monthAbbrToNumber("Jan"));
+
+ // MONTH NAME -> NAME
+
+ System.out.println(monthAbbrToFullName("Jan"));
+ }
+
+ public static String monthNumberToAbbr(int monthNumber) {
+ return Month.of(monthNumber).getDisplayName(
+ TextStyle.SHORT, Locale.getDefault()
+ );
+ }
+
+ public static String monthNumberToFullName(int monthNumber) {
+ return Month.of(monthNumber).getDisplayName(
+ TextStyle.FULL, Locale.getDefault()
+ );
+ }
+
+ public static String monthNumberToName(int monthNumber) {
+ return Month.of(monthNumber).name();
+ }
+
+ public static int monthNameToNumber(String monthName) {
+ return Month.valueOf(monthName.toUpperCase()).getValue();
+ }
+
+ public static int monthAbbrToNumber(String abbreviation) {
+ Optional monthOptional = Arrays.stream(Month.values())
+ .filter(month -> month.name().substring(0, 3).equalsIgnoreCase(abbreviation))
+ .findFirst();
+
+ return monthOptional.orElseThrow(IllegalArgumentException::new).getValue();
+ }
+
+ public static String monthAbbrToFullName(String abbreviation) {
+ Optional monthOptional = Arrays.stream(Month.values())
+ .filter(month -> month.name().substring(0, 3).equalsIgnoreCase(abbreviation))
+ .findFirst();
+
+ return monthOptional.orElseThrow(IllegalArgumentException::new)
+ .getDisplayName(TextStyle.FULL, Locale.getDefault());
+ }
+
+}
diff --git a/src/main/java/com/howtodoinjava/core/datetime/DayPeriodFormatter.java b/src/main/java/com/howtodoinjava/core/datetime/DayPeriodFormatter.java
new file mode 100644
index 0000000..5346cd7
--- /dev/null
+++ b/src/main/java/com/howtodoinjava/core/datetime/DayPeriodFormatter.java
@@ -0,0 +1,57 @@
+package com.howtodoinjava.core.datetime;
+
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+
+public class DayPeriodFormatter {
+
+ static LocalTime night = LocalTime.of(21, 0, 0);
+ static LocalTime morning = LocalTime.of(6, 0, 0);
+ static LocalTime afternoon = LocalTime.of(12, 0, 0);
+ static LocalTime evening = LocalTime.of(18, 0, 0);
+ static LocalTime almostMidnight = LocalTime.of(23, 59, 59);
+ static LocalTime midnight = LocalTime.of(0, 0, 0);
+
+ public static void main(String[] args) {
+
+ LocalDateTime localDateTime = LocalDateTime.now();
+
+ System.out.println(DayPeriodFormatter.formatBeforeJava16(localDateTime, ZoneId.systemDefault()));
+ System.out.println(DayPeriodFormatter.formatSinceJava16(localDateTime, ZoneId.systemDefault()));
+ }
+
+ public static String formatBeforeJava16(LocalDateTime localDateTime, ZoneId zoneId) {
+
+ ZonedDateTime zdt = localDateTime.atZone(zoneId);
+ LocalTime lt = zdt.toLocalTime();
+
+ DateTimeFormatter formatter
+ = DateTimeFormatter.ofPattern("yyyy-MMM-dd");
+
+ String dayTime = "";
+
+ if ((lt.isAfter(night) && lt.isBefore(almostMidnight))
+ || lt.isAfter(midnight) && (lt.isBefore(morning))) {
+ dayTime = " at night";
+ } else if (lt.isAfter(morning) && lt.isBefore(afternoon)) {
+ dayTime = " in the morning";
+ } else if (lt.isAfter(afternoon) && lt.isBefore(evening)) {
+ dayTime = " in the afternoon";
+ } else if (lt.isAfter(evening) && lt.isBefore(night)) {
+ dayTime = " in the evening";
+ }
+
+ return zdt.withZoneSameInstant(zoneId).format(formatter) + dayTime;
+ }
+
+ public static String formatSinceJava16(LocalDateTime localDateTime, ZoneId zoneId) {
+
+ ZonedDateTime zdt = localDateTime.atZone(zoneId);
+ DateTimeFormatter formatter
+ = DateTimeFormatter.ofPattern("yyyy-MMM-dd [B]");
+ return zdt.withZoneSameInstant(zoneId).format(formatter);
+ }
+}
diff --git a/src/main/java/com/howtodoinjava/core/datetime/DisplayDayOfWeekName.java b/src/main/java/com/howtodoinjava/core/datetime/DisplayDayOfWeekName.java
new file mode 100644
index 0000000..418a8c5
--- /dev/null
+++ b/src/main/java/com/howtodoinjava/core/datetime/DisplayDayOfWeekName.java
@@ -0,0 +1,41 @@
+package com.howtodoinjava.core.datetime;
+
+import java.text.DateFormatSymbols;
+import java.time.DayOfWeek;
+import java.time.LocalDate;
+import java.time.format.TextStyle;
+import java.util.Calendar;
+import java.util.Locale;
+import java.util.stream.IntStream;
+
+public class DisplayDayOfWeekName {
+
+ public static void main(String[] args) {
+ //1
+ String[] weekdays = DateFormatSymbols.getInstance().getWeekdays();
+ IntStream.range(0, weekdays.length)
+ .filter(t -> !weekdays[t].isBlank())
+ .mapToObj(t -> String.format("Day: %d -> %s",
+ t, weekdays[t]))
+ .forEach(System.out::println);
+
+ Calendar calendar = Calendar.getInstance();
+ int dayOfWeekValue = calendar.get(Calendar.DAY_OF_WEEK);
+ System.out.println(weekdays[dayOfWeekValue]);
+
+ //2
+ DayOfWeek[] days = DayOfWeek.values();
+ IntStream.range(0, days.length)
+ .mapToObj(t -> String.format("Day: %d -> %s",
+ t, days[t]))
+ .forEach(System.out::println);
+
+ //3
+ LocalDate localDate = LocalDate.now();
+ DayOfWeek weekOfTheDay = DayOfWeek.from(localDate);
+ System.out.println(weekOfTheDay.getValue());
+ System.out.println(weekOfTheDay.getDisplayName(TextStyle.FULL, Locale.getDefault()));
+ System.out.println(weekOfTheDay.getDisplayName(TextStyle.FULL, Locale.FRENCH));
+ }
+
+}
diff --git a/src/main/java/com/howtodoinjava/core/datetime/ElapsedTimeSinceMidnight.java b/src/main/java/com/howtodoinjava/core/datetime/ElapsedTimeSinceMidnight.java
new file mode 100644
index 0000000..2285674
--- /dev/null
+++ b/src/main/java/com/howtodoinjava/core/datetime/ElapsedTimeSinceMidnight.java
@@ -0,0 +1,59 @@
+package com.howtodoinjava.core.datetime;
+
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.OffsetTime;
+import java.time.ZoneId;
+import java.time.ZoneOffset;
+import java.time.ZonedDateTime;
+import java.time.temporal.ChronoUnit;
+
+public class ElapsedTimeSinceMidnight {
+
+ public static void main(String[] args) {
+ System.out.println(getElapsedSecondsSinceMidnight());
+ System.out.println(getElapsedMillisSinceMidnight());
+
+ System.out.println(getElapsedSecondsSinceMidnightAtZone(ZoneOffset.ofHours(-5)));
+ System.out.println(getElapsedSecondsSinceMidnightAtZone(ZoneId.of("America/New_York")));
+ System.out.println(getElapsedSecondsSinceMidnightAtZone(ZoneOffset.UTC));
+
+ System.out.println(getElapsedSecondsSinceMidnightUsingLocalDateTime());
+ System.out.println(getElapsedSecondsSinceMidnightUsingZonedDateTime());
+ }
+
+ public static long getElapsedSecondsSinceMidnightAtZone(ZoneId zoneId) {
+
+ LocalTime currentTime = LocalTime.now(zoneId);
+ return ChronoUnit.SECONDS.between(LocalTime.MIDNIGHT, currentTime);
+ }
+
+ public static long getElapsedSecondsSinceMidnight() {
+ LocalTime midnight = LocalTime.MIDNIGHT;
+ LocalTime currentTime = LocalTime.now();
+ return ChronoUnit.SECONDS.between(midnight, currentTime);
+ }
+
+ public static long getElapsedMillisSinceMidnight() {
+ LocalTime midnight = LocalTime.MIDNIGHT;
+ LocalTime currentTime = LocalTime.now();
+ return ChronoUnit.MILLIS.between(midnight, currentTime);
+ }
+
+ public static long getElapsedSecondsSinceMidnightUsingLocalDateTime() {
+
+ LocalDateTime currentTime = LocalDateTime.now();
+ LocalDateTime midnight = LocalDateTime.of(LocalDate.now(), LocalTime.MIDNIGHT);
+
+ return ChronoUnit.SECONDS.between(midnight, currentTime);
+ }
+
+ public static long getElapsedSecondsSinceMidnightUsingZonedDateTime() {
+
+ ZonedDateTime currentTime = ZonedDateTime.now();
+ ZonedDateTime midnight = ZonedDateTime.of(LocalDate.now(), LocalTime.MIDNIGHT, ZoneId.systemDefault());
+
+ return ChronoUnit.SECONDS.between(midnight, currentTime);
+ }
+}
diff --git a/src/main/java/com/howtodoinjava/core/datetime/FirstAndLastDay.java b/src/main/java/com/howtodoinjava/core/datetime/FirstAndLastDay.java
new file mode 100644
index 0000000..09f2e2d
--- /dev/null
+++ b/src/main/java/com/howtodoinjava/core/datetime/FirstAndLastDay.java
@@ -0,0 +1,39 @@
+package com.howtodoinjava.core.datetime;
+
+import java.time.DayOfWeek;
+import java.time.LocalDate;
+import java.time.temporal.TemporalAdjusters;
+
+public class FirstAndLastDay {
+
+ public static void main(String[] args) {
+ LocalDate today = LocalDate.of(2024, 4, 26);
+
+ //Week
+ LocalDate firstDayOfWeek = today.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
+ LocalDate lastDayOfWeek = today.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY));
+
+ System.out.println(firstDayOfWeek); //2024-04-22
+ System.out.println(lastDayOfWeek); //2024-04-22
+
+ //Month
+ LocalDate firstDayOfMonth = today.withDayOfMonth(1);
+ LocalDate lastDayOfMonth = today.withDayOfMonth(today.lengthOfMonth());
+
+ System.out.println(firstDayOfMonth); //2024-04-01
+ System.out.println(lastDayOfMonth); //2024-04-30
+
+ firstDayOfMonth = today.with(TemporalAdjusters.firstDayOfMonth());
+ lastDayOfMonth = today.with(TemporalAdjusters.lastDayOfMonth());
+
+ System.out.println(firstDayOfMonth); //2024-04-01
+ System.out.println(lastDayOfMonth); //2024-04-30
+
+ //Year
+ LocalDate firstDayOfYear = today.with(TemporalAdjusters.firstDayOfYear());
+ LocalDate lastDayOfYear = today.with(TemporalAdjusters.lastDayOfYear());
+
+ System.out.println(firstDayOfYear); //2024-01-01
+ System.out.println(lastDayOfYear); //2024-12-31
+ }
+}
diff --git a/src/main/java/com/howtodoinjava/core/datetime/FirstLastDayOfYear.java b/src/main/java/com/howtodoinjava/core/datetime/FirstLastDayOfYear.java
new file mode 100644
index 0000000..4b9e057
--- /dev/null
+++ b/src/main/java/com/howtodoinjava/core/datetime/FirstLastDayOfYear.java
@@ -0,0 +1,20 @@
+package com.howtodoinjava.core.datetime;
+
+import java.time.LocalDate;
+import java.time.temporal.TemporalAdjusters;
+
+public class FirstLastDayOfYear {
+
+ public static void main(String[] args) {
+ int year = 2024;
+
+ LocalDate firstDay = LocalDate.of(year, 1, 1);
+ System.out.println(firstDay);
+
+ LocalDate lastDay = LocalDate.of(year, 12, 31);
+ System.out.println(lastDay);
+
+ System.out.println(LocalDate.now().with(TemporalAdjusters.firstDayOfYear()));
+ System.out.println(LocalDate.now().with(TemporalAdjusters.lastDayOfYear()));
+ }
+}
diff --git a/src/main/java/com/howtodoinjava/core/datetime/GetQuarterInfo.java b/src/main/java/com/howtodoinjava/core/datetime/GetQuarterInfo.java
new file mode 100644
index 0000000..6e63c5f
--- /dev/null
+++ b/src/main/java/com/howtodoinjava/core/datetime/GetQuarterInfo.java
@@ -0,0 +1,32 @@
+package com.howtodoinjava.core.datetime;
+
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.time.temporal.IsoFields;
+import java.time.temporal.TemporalAdjusters;
+import net.bytebuddy.asm.Advice.Local;
+
+public class GetQuarterInfo {
+
+ public static void main(String[] args) {
+
+ LocalDate localDate = LocalDate.now();
+
+ //What is current quarter
+ int currentQuarter = localDate.get(IsoFields.QUARTER_OF_YEAR);
+ System.out.println(currentQuarter);
+
+ String currentQuarterStr = localDate.format(DateTimeFormatter.ofPattern("QQQQ"));
+ System.out.println(currentQuarterStr);
+
+ //Current quarter start date and end date
+ LocalDate firstDay = localDate.with(IsoFields.DAY_OF_QUARTER, 1L);
+ LocalDate lastDay = firstDay.plusMonths(2).with(TemporalAdjusters.lastDayOfMonth());
+ System.out.println(firstDay);
+ System.out.println(lastDay);
+
+ //Quarter between two dates
+ long quarterCount = IsoFields.QUARTER_YEARS.between(firstDay, lastDay);
+ System.out.println(quarterCount);
+ }
+}
diff --git a/src/main/java/com/howtodoinjava/core/datetime/LocaleExamples.java b/src/main/java/com/howtodoinjava/core/datetime/LocaleExamples.java
index 71a7cf7..d447b43 100644
--- a/src/main/java/com/howtodoinjava/core/datetime/LocaleExamples.java
+++ b/src/main/java/com/howtodoinjava/core/datetime/LocaleExamples.java
@@ -1,12 +1,15 @@
package com.howtodoinjava.core.datetime;
+import java.math.RoundingMode;
import java.text.DateFormat;
import java.text.NumberFormat;
+import java.text.ParseException;
+import java.util.Currency;
import java.util.Date;
import java.util.Locale;
public class LocaleExamples {
- public static void main(final String[] args) {
+ public static void main(final String[] args) throws ParseException {
//1 Get Locale Basic Info
Locale enUsLocale = new Locale("EN", "US");
@@ -32,11 +35,43 @@ public static void main(final String[] args) {
NumberFormat nf = NumberFormat.getInstance(enUsLocale);
System.out.println(nf.format(123456789L));
+ //Specifying Language Range
+ Locale.LanguageRange lr = new Locale.LanguageRange("de-*");
+
//5 Format Currency
- NumberFormat cf = NumberFormat.getCurrencyInstance(locale);
+ /*NumberFormat cf = NumberFormat.getCurrencyInstance(locale);
String currency = cf.format(123.456);
- System.out.println(currency);
+ System.out.println(currency);*/
+
+
+ double amount = 1234.567;
+ NumberFormat localizedCurrencyFormat = NumberFormat.getCurrencyInstance(Locale.US);
+ String formattedCurrency = localizedCurrencyFormat.format(amount);
+
+ System.out.println(formattedCurrency); // Output: $1,234.57
+
+ NumberFormat frCurrencyFormat = NumberFormat.getCurrencyInstance(Locale.FRANCE);
+ String frFormattedCurrency = frCurrencyFormat.format(amount);
+
+ System.out.println(frFormattedCurrency); // Output: $1,234.57
+
+ String currencyString = "$1,234.57";
+
+ try {
+ Number parsedNumber = localizedCurrencyFormat.parse(currencyString);
+ double parsedAmount = parsedNumber.doubleValue();
+ System.out.println(parsedAmount); // Output: 1234.57
+ } catch (ParseException e) {
+ e.printStackTrace();
+ }
- //6 Decimal Format
+ try {
+ NumberFormat roundedCurrencyFormat = NumberFormat.getCurrencyInstance();
+ roundedCurrencyFormat.setRoundingMode(RoundingMode.HALF_UP);
+ String formattedValue = roundedCurrencyFormat.format(123456.789d);
+ System.out.println(formattedValue); // Output: 1234.57
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
}
}
diff --git a/src/main/java/com/howtodoinjava/core/datetime/LocationBasedDateFormatting.java b/src/main/java/com/howtodoinjava/core/datetime/LocationBasedDateFormatting.java
index 8ae4812..1f5a8dd 100644
--- a/src/main/java/com/howtodoinjava/core/datetime/LocationBasedDateFormatting.java
+++ b/src/main/java/com/howtodoinjava/core/datetime/LocationBasedDateFormatting.java
@@ -1,5 +1,8 @@
package com.howtodoinjava.core.datetime;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
@@ -7,17 +10,49 @@
import java.util.Locale;
public class LocationBasedDateFormatting {
+
public static void main(final String[] args) {
- ZonedDateTime today = ZonedDateTime.now();
-
- DateTimeFormatter format = DateTimeFormatter
- .ofLocalizedDateTime(FormatStyle.MEDIUM)
- .withLocale(Locale.forLanguageTag("es"))
- .withZone(ZoneId.of("UTC"));
- //.withLocale(LocaleContextHolder.getLocale());
-
- String formmatedDate = format.format(today);
- System.out.println(formmatedDate);
+ Locale locale = Locale.forLanguageTag("es");
+
+ DateTimeFormatter formatter = DateTimeFormatter
+ .ofLocalizedDateTime(FormatStyle.MEDIUM)
+ .withLocale(locale);
+
+ String formattedDate = formatter.format(ZonedDateTime.now());
+ System.out.println(formattedDate); // 14 ene 2024, 8:21:54
+
+ DateTimeFormatter chFormatter = DateTimeFormatter
+ .ofLocalizedDateTime(FormatStyle.MEDIUM)
+ .withLocale(Locale.forLanguageTag("zh"));
+
+ formattedDate = chFormatter.format(ZonedDateTime.now());
+ System.out.println(formattedDate); // 2024年1月14日 08:21:54
+
+ Locale.setDefault(Locale.GERMANY);
+
+ String ld = LocalDate.now().format(
+ DateTimeFormatter.ofLocalizedDate(FormatStyle.LONG));
+ System.out.println(ld); // 14. Januar 2024
+
+ String lt = LocalTime.now().format(
+ DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT));
+ System.out.println(lt); // 08:14
+
+ String ldt = LocalDateTime.now().format(
+ DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM));
+ System.out.println(ldt); // 14.01.2024, 08:14:25
+
+ // ofLocalizedPattern() examples
+
+ Locale.setDefault(Locale.ENGLISH);
+
+ String ld1 = LocalDate.now().format(
+ DateTimeFormatter.ofLocalizedPattern("yMM"));
+ System.out.println(ld1); // 01.2024
+
+ String ld2 = LocalDate.now().format(
+ DateTimeFormatter.ofLocalizedPattern("yMMM"));
+ System.out.println(ld2); // 01.2024
}
}
diff --git a/src/main/java/com/howtodoinjava/core/datetime/SplitDateRangeIntoEqualIntervals.java b/src/main/java/com/howtodoinjava/core/datetime/SplitDateRangeIntoEqualIntervals.java
new file mode 100644
index 0000000..cd28d05
--- /dev/null
+++ b/src/main/java/com/howtodoinjava/core/datetime/SplitDateRangeIntoEqualIntervals.java
@@ -0,0 +1,110 @@
+package com.howtodoinjava.core.datetime;
+
+import static java.time.temporal.ChronoField.ALIGNED_WEEK_OF_YEAR;
+import static java.time.temporal.ChronoField.YEAR;
+
+import java.time.DateTimeException;
+import java.time.Duration;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.Year;
+import java.time.YearMonth;
+import java.time.chrono.Chronology;
+import java.time.chrono.IsoChronology;
+import java.time.temporal.ChronoUnit;
+import java.time.temporal.TemporalAccessor;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
+public class SplitDateRangeIntoEqualIntervals {
+
+ public static void main(String[] args) {
+
+ int equalParts = 15;
+ LocalDateTime start = LocalDateTime.of(2021, 10, 1, 0, 0, 0);
+ LocalDateTime end = LocalDateTime.of(2022, 03, 31, 0, 0, 0);
+
+ System.out.println(split_LocalDateTime_Range_In_N_Equal_Intervals(start, end, equalParts));
+ System.out.println(split_LocalDate_Range_Into_Months(start.toLocalDate(), end.toLocalDate()));
+ System.out.println(split_LocalDate_Range_Into_Weeks(start.toLocalDate(), end.toLocalDate()));
+ }
+
+ public static List split_LocalDateTime_Range_In_N_Equal_Intervals(
+ LocalDateTime start, LocalDateTime end, int n) {
+
+ Duration range = Duration.between(start, end);
+ Duration interval = range.dividedBy(n - 1);
+ List listOfDates = new ArrayList<>();
+ LocalDateTime timeline = start;
+ for (int i = 0; i < n - 1; i++) {
+ listOfDates.add(timeline);
+ timeline = timeline.plus(interval);
+ }
+ listOfDates.add(end);
+ return listOfDates;
+ }
+
+ public static List split_LocalDate_Range_Into_Days(
+ LocalDate startDate, LocalDate endDate) {
+
+ long numOfDaysBetween = ChronoUnit.DAYS.between(startDate, endDate);
+ return IntStream.iterate(0, i -> i + 1)
+ .limit(numOfDaysBetween)
+ .mapToObj(i -> startDate.plusDays(i))
+ .collect(Collectors.toList());
+ }
+
+ public static List split_LocalDate_Range_Into_Weeks(
+ LocalDate startDate, LocalDate endDate) {
+
+ long numOfDaysBetween = ChronoUnit.WEEKS.between(startDate, endDate);
+ return IntStream.iterate(0, i -> i + 1)
+ .limit(numOfDaysBetween)
+ .mapToObj(i -> YearWeek.from(startDate.plusWeeks(i)))
+ .collect(Collectors.toList());
+ }
+
+ public static List split_LocalDate_Range_Into_Months(
+ LocalDate startDate, LocalDate endDate) {
+
+ long numOfDaysBetween = ChronoUnit.MONTHS.between(startDate, endDate);
+ return IntStream.iterate(0, i -> i + 1)
+ .limit(numOfDaysBetween)
+ .mapToObj(i -> YearMonth.from(startDate.plusMonths(i)))
+ .collect(Collectors.toList());
+ }
+
+ public static List split_LocalDate_Range_Into_Years(
+ LocalDate startDate, LocalDate endDate) {
+
+ long numOfDaysBetween = ChronoUnit.YEARS.between(startDate, endDate);
+ return IntStream.iterate(0, i -> i + 1)
+ .limit(numOfDaysBetween)
+ .mapToObj(i -> Year.from(startDate.plusYears(i)))
+ .collect(Collectors.toList());
+ }
+}
+
+record YearWeek(int year, int week) {
+
+ public static YearWeek from(TemporalAccessor temporal) {
+ Objects.requireNonNull(temporal, "temporal");
+ try {
+ if (IsoChronology.INSTANCE.equals(Chronology.from(temporal)) == false) {
+ temporal = LocalDate.from(temporal);
+ }
+ return new YearWeek(temporal.get(YEAR), temporal.get(ALIGNED_WEEK_OF_YEAR));
+ } catch (DateTimeException ex) {
+ throw new DateTimeException(
+ STR."Unable to obtain YearWeek from TemporalAccessor: \{temporal} of type \{temporal.getClass().getName()}", ex);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return STR."\{year}-\{week}";
+ }
+}
diff --git a/src/main/java/com/howtodoinjava/core/datetime/StopWatchExamples.java b/src/main/java/com/howtodoinjava/core/datetime/StopWatchExamples.java
new file mode 100644
index 0000000..6b981cf
--- /dev/null
+++ b/src/main/java/com/howtodoinjava/core/datetime/StopWatchExamples.java
@@ -0,0 +1,86 @@
+package com.howtodoinjava.core.datetime;
+
+import java.time.Duration;
+import java.time.Instant;
+import java.util.concurrent.TimeUnit;
+import org.apache.commons.lang3.time.StopWatch;
+
+public class StopWatchExamples {
+
+ public static void main(String[] args) throws InterruptedException {
+
+ // 1- Custom Stopwatch
+
+ Stopwatch stopwatch = new Stopwatch();
+ stopwatch.start();
+ Thread.sleep(2000L);
+ stopwatch.stop();
+ System.out.println(STR."Elapsed Time : \{stopwatch.getElapsedTime()}");
+ System.out.println(STR."Elapsed Time : \{stopwatch.getElapsedTime(TimeUnit.NANOSECONDS)}");
+
+ // 2 - Apache Commons
+
+ StopWatch stopWatch = new StopWatch();
+ stopWatch.start();
+ Thread.sleep(2000L);
+ stopWatch.stop();
+ System.out.println(STR."Elapsed Time : \{stopWatch.getTime()}");
+ System.out.println(STR."Elapsed Time in Nano: \{stopWatch.getTime(TimeUnit.NANOSECONDS)}");
+ }
+
+ // elapsed time in milliseconds
+ public long elapsedTimeToMillis(long nanotime) {
+
+ return TimeUnit.MILLISECONDS.convert(
+ nanotime, TimeUnit.NANOSECONDS);
+ }
+
+ // elapsed time in seconds
+ public long elapsedTimeToSeconds(long nanotime) {
+
+ return TimeUnit.SECONDS.convert(
+ nanotime, TimeUnit.NANOSECONDS);
+ }
+}
+
+final class Stopwatch {
+
+ private Instant startTime;
+ private Instant endTime;
+ private boolean running;
+
+ public void start() {
+ if (!running) {
+ startTime = Instant.now();
+ running = true;
+ } else {
+ System.out.println("Stopwatch is already running. Use stop() before starting again.");
+ }
+ }
+
+ public void stop() {
+ if (running) {
+ endTime = Instant.now();
+ running = false;
+ } else {
+ System.out.println("Stopwatch is not running. Use start() before stopping.");
+ }
+ }
+
+ public Duration getElapsedDuration() {
+ if (running) {
+ return Duration.between(startTime, Instant.now());
+ } else {
+ return Duration.between(startTime, endTime);
+ }
+ }
+
+ public long getElapsedTime() {
+ Duration duration = getElapsedDuration();
+ return duration.toMillis();
+ }
+
+ public long getElapsedTime(TimeUnit timeUnit) {
+ return timeUnit.convert(getElapsedTime(), TimeUnit.MILLISECONDS);
+ }
+}
diff --git a/src/main/java/com/howtodoinjava/core/datetime/WeeksBetweenDates.java b/src/main/java/com/howtodoinjava/core/datetime/WeeksBetweenDates.java
new file mode 100644
index 0000000..8599fe2
--- /dev/null
+++ b/src/main/java/com/howtodoinjava/core/datetime/WeeksBetweenDates.java
@@ -0,0 +1,19 @@
+package com.howtodoinjava.core.datetime;
+
+import java.time.LocalDate;
+import java.time.temporal.ChronoUnit;
+
+public class WeeksBetweenDates {
+
+ public static void main(String[] args) {
+ LocalDate startLd = LocalDate.of(2023, 8, 5);
+ LocalDate endLd = LocalDate.of(2023, 9, 5);
+ long numWeeks = ChronoUnit.WEEKS.between(startLd, endLd);
+ System.out.println(numWeeks);
+
+ long daysDifference = ChronoUnit.DAYS.between(startLd, endLd); // 31
+ int extraDays = Long.valueOf(daysDifference % 7).intValue(); //3
+ System.out.println(extraDays);
+ }
+
+}
diff --git a/src/main/java/com/howtodoinjava/core/jmh/IntToStringBenchmark.java b/src/main/java/com/howtodoinjava/core/jmh/IntToStringBenchmark.java
new file mode 100644
index 0000000..d614ab1
--- /dev/null
+++ b/src/main/java/com/howtodoinjava/core/jmh/IntToStringBenchmark.java
@@ -0,0 +1,75 @@
+package com.howtodoinjava.core.jmh;
+
+import java.util.concurrent.ThreadLocalRandom;
+import java.util.concurrent.TimeUnit;
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.OutputTimeUnit;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.infra.Blackhole;
+import org.openjdk.jmh.runner.Runner;
+import org.openjdk.jmh.runner.options.Options;
+import org.openjdk.jmh.runner.options.OptionsBuilder;
+
+@State(Scope.Thread)
+public class IntToStringBenchmark {
+
+ private ThreadLocalRandom threadLocalRandom = ThreadLocalRandom.current();
+
+ @Benchmark
+ @BenchmarkMode(Mode.AverageTime)
+ @OutputTimeUnit(TimeUnit.MICROSECONDS)
+ public void methodIntegerToString(Blackhole blackhole) {
+ int i = threadLocalRandom.nextInt(1_00_000, 9_99_999);
+ String s = Integer.toString(i);
+ blackhole.consume(s);
+ }
+
+ @Benchmark
+ @BenchmarkMode(Mode.AverageTime)
+ @OutputTimeUnit(TimeUnit.MICROSECONDS)
+ public void dmethodIntegerToStringV2(Blackhole blackhole) {
+ Integer i = threadLocalRandom.nextInt(1_00_000, 9_99_999);
+ String s = Integer.toString(i);
+ blackhole.consume(s);
+ }
+
+ @Benchmark
+ @BenchmarkMode(Mode.AverageTime)
+ @OutputTimeUnit(TimeUnit.MICROSECONDS)
+ public void cmethodStringValueOf(Blackhole blackhole) {
+ int i = threadLocalRandom.nextInt(1_00_000, 9_99_999);
+ String s = String.valueOf(i);
+ blackhole.consume(s);
+ }
+
+ @Benchmark
+ @BenchmarkMode(Mode.AverageTime)
+ @OutputTimeUnit(TimeUnit.MICROSECONDS)
+ public void bmethodStringFormat(Blackhole blackhole) {
+ int i = threadLocalRandom.nextInt(1_00_000, 9_99_999);
+ String s = String.format("%d", i);
+ blackhole.consume(s);
+ }
+
+ @Benchmark
+ @BenchmarkMode(Mode.AverageTime)
+ @OutputTimeUnit(TimeUnit.MICROSECONDS)
+ public void amethodStringTemplate(Blackhole blackhole) {
+ int i = threadLocalRandom.nextInt(1_00_000, 9_99_999);
+ String s = STR."\{i}";
+ blackhole.consume(s);
+ }
+
+ public static void main(String[] args) throws Exception {
+
+ Options opt = new OptionsBuilder()
+ .include(IntToStringBenchmark.class.getSimpleName())
+ .forks(1)
+ .build();
+
+ new Runner(opt).run();
+ }
+}
diff --git a/src/main/java/com/howtodoinjava/core/optional/OptionalExamples.java b/src/main/java/com/howtodoinjava/core/optional/OptionalExamples.java
new file mode 100644
index 0000000..4949214
--- /dev/null
+++ b/src/main/java/com/howtodoinjava/core/optional/OptionalExamples.java
@@ -0,0 +1,20 @@
+package com.howtodoinjava.core.optional;
+
+import java.util.Optional;
+
+public class OptionalExamples {
+
+ public static void main(String[] args) {
+ Optional optionalValue = Optional.of("Hello");
+ String result = optionalValue.orElse( generateDefaultValue() ); // Using orElse()
+ System.out.println(STR."Result using orElse(): \{result}");
+
+ result = optionalValue.orElseGet(() -> generateDefaultValue() ); // Using orElseGet()
+ System.out.println(STR."Result using orElseGet(): \{result}");
+ }
+
+ public static String generateDefaultValue() {
+ System.out.println("Generating Default Value");
+ return "Default Value";
+ }
+}
diff --git a/src/main/java/com/howtodoinjava/core/security/Base64Example.java b/src/main/java/com/howtodoinjava/core/security/Base64Example.java
new file mode 100644
index 0000000..ffc27f5
--- /dev/null
+++ b/src/main/java/com/howtodoinjava/core/security/Base64Example.java
@@ -0,0 +1,16 @@
+package com.howtodoinjava.core.security;
+
+import java.util.Base64;
+
+public class Base64Example {
+
+ public static void main(String[] args) {
+ String originalInput = "hello world";
+ String encodedString = Base64.getEncoder().withoutPadding().encodeToString(originalInput.getBytes());
+ System.out.println(encodedString);
+
+ byte[] decodedBytes = Base64.getDecoder().decode(encodedString);
+ String decodedString = new String(decodedBytes);
+ System.out.println(decodedString);
+ }
+}
diff --git a/src/main/java/com/howtodoinjava/core/security/Base64FileEncodeExample.java b/src/main/java/com/howtodoinjava/core/security/Base64FileEncodeExample.java
new file mode 100644
index 0000000..3dd4396
--- /dev/null
+++ b/src/main/java/com/howtodoinjava/core/security/Base64FileEncodeExample.java
@@ -0,0 +1,29 @@
+package com.howtodoinjava.core.security;
+
+import jakarta.xml.bind.DatatypeConverter;
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.util.Base64;
+
+public class Base64FileEncodeExample {
+
+ public static void main(String[] args) throws IOException {
+ //TextFile
+ File file = new File("c:/temp/output.txt");
+ String encoded = Base64.getEncoder()
+ .encodeToString(Files.readAllBytes(file.toPath()));
+ System.out.println(encoded);
+
+ byte[] decoded = Base64.getDecoder().decode(encoded);
+ System.out.println(new String(decoded));
+
+ //ImageFile
+ File inImage = new File("c:/temp/avni.jpg");
+ File outImage = new File("c:/temp/avni_new.jpg");
+ byte[] encodedImageBytes = Base64.getEncoder().encode(Files.readAllBytes(inImage.toPath()));
+ byte[] decodedImageBytes = Base64.getDecoder().decode(encodedImageBytes);
+ Files.write(outImage.toPath(), decodedImageBytes);
+ }
+
+}
diff --git a/src/main/java/com/howtodoinjava/core/security/concurrent/AES256EncryptionTask.java b/src/main/java/com/howtodoinjava/core/security/concurrent/AES256EncryptionTask.java
new file mode 100644
index 0000000..067e655
--- /dev/null
+++ b/src/main/java/com/howtodoinjava/core/security/concurrent/AES256EncryptionTask.java
@@ -0,0 +1,64 @@
+package com.howtodoinjava.core.security.concurrent;
+
+import java.security.SecureRandom;
+import java.security.spec.KeySpec;
+import java.util.Base64;
+import java.util.concurrent.Callable;
+import javax.crypto.Cipher;
+import javax.crypto.SecretKey;
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.PBEKeySpec;
+import javax.crypto.spec.SecretKeySpec;
+
+public class AES256EncryptionTask implements Callable {
+
+ private static final int KEY_LENGTH = 256;
+ private static final int ITERATION_COUNT = 65536;
+
+ private String strToEncrypt;
+ private String secretKey;
+ private String salt;
+
+ public AES256EncryptionTask(String strToEncrypt, String secretKey, String salt) {
+ this.strToEncrypt = strToEncrypt;
+ this.secretKey = secretKey;
+ this.salt = salt;
+ }
+
+ @Override
+ public String call() throws Exception {
+ return encrypt(strToEncrypt, secretKey, salt);
+ }
+
+ public String encrypt(String strToEncrypt, String secretKey, String salt) {
+
+ try {
+
+ SecureRandom secureRandom = new SecureRandom();
+ byte[] iv = new byte[16];
+ secureRandom.nextBytes(iv);
+ IvParameterSpec ivspec = new IvParameterSpec(iv);
+
+ SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
+ KeySpec spec = new PBEKeySpec(secretKey.toCharArray(), salt.getBytes(), ITERATION_COUNT,
+ KEY_LENGTH);
+ SecretKey tmp = factory.generateSecret(spec);
+ SecretKeySpec secretKeySpec = new SecretKeySpec(tmp.getEncoded(), "AES");
+
+ Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
+ cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivspec);
+
+ byte[] cipherText = cipher.doFinal(strToEncrypt.getBytes("UTF-8"));
+ byte[] encryptedData = new byte[iv.length + cipherText.length];
+ System.arraycopy(iv, 0, encryptedData, 0, iv.length);
+ System.arraycopy(cipherText, 0, encryptedData, iv.length, cipherText.length);
+
+ return Base64.getEncoder().encodeToString(encryptedData);
+ } catch (Exception e) {
+ // Handle the exception properly
+ e.printStackTrace();
+ return null;
+ }
+ }
+}
diff --git a/src/main/java/com/howtodoinjava/core/security/concurrent/Demo.java b/src/main/java/com/howtodoinjava/core/security/concurrent/Demo.java
new file mode 100644
index 0000000..dcb014e
--- /dev/null
+++ b/src/main/java/com/howtodoinjava/core/security/concurrent/Demo.java
@@ -0,0 +1,48 @@
+package com.howtodoinjava.core.security.concurrent;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.stream.Stream;
+
+public class Demo {
+
+ public static void main(String[] args) {
+
+ // Define your secret key and salt (keep these secure and don't hardcode in production)
+ String secretKey = "MySecretKey";
+ String salt = "MySalt";
+
+ Random rand = new Random();
+ List dataLines = Stream
+ .generate(() -> "Token Value : " + rand.nextInt(100))
+ .limit(100)
+ .toList();
+
+ int numberOfThreads = 4; // Adjust based on your system capabilities
+ ExecutorService executor = Executors.newFixedThreadPool(numberOfThreads);
+
+ List> futures = new ArrayList<>();
+ for (String dataLine : dataLines) {
+ // Create new AES256 instance for each line or data chunk
+ AES256EncryptionTask task = new AES256EncryptionTask(dataLine, secretKey, salt);
+ futures.add(executor.submit(task));
+ }
+
+ // Wait for all tasks to complete and collect results
+ for (Future future : futures) {
+ try {
+ String encryptedData = future.get();
+ System.out.println(encryptedData);
+ // Process the encrypted data, e.g., write to file
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ executor.shutdown();
+ }
+}
diff --git a/src/main/java/com/howtodoinjava/core/serialization/SerializeObjectToString.java b/src/main/java/com/howtodoinjava/core/serialization/SerializeObjectToString.java
new file mode 100644
index 0000000..3e26005
--- /dev/null
+++ b/src/main/java/com/howtodoinjava/core/serialization/SerializeObjectToString.java
@@ -0,0 +1,88 @@
+package com.howtodoinjava.core.serialization;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.dataformat.xml.XmlMapper;
+import com.google.gson.Gson;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.util.Base64;
+
+public class SerializeObjectToString {
+
+ public static void main(String[] args) throws IOException, ClassNotFoundException {
+ //1 Using Core Java
+
+ Person person = new Person(1, "Lokesh");
+ String encodedString;
+ Person deserializedPerson;
+
+ /*String encodedString = SerializationUtils.objectToString(person);
+ System.out.println(encodedString);
+
+ Person deserializedPerson = (Person) SerializationUtils.stringToObject(encodedString);
+ System.out.println(deserializedPerson);*/
+
+ //2 Using Jackson
+ ObjectMapper mapper = new ObjectMapper();
+ String json = mapper.writeValueAsString(person);
+ System.out.println(json);
+
+ deserializedPerson = mapper.readValue(json, Person.class);
+ System.out.println(deserializedPerson);
+
+ //3 Gson
+ Gson gson = new Gson();
+ json = gson.toJson(person);
+ System.out.println(json);
+
+ deserializedPerson = gson.fromJson(json, Person.class);
+ System.out.println(deserializedPerson);
+
+ //4 Base64 encoded json
+ String base64EncodedString = Base64.getEncoder().encodeToString(json.getBytes());
+ System.out.println(base64EncodedString);
+
+ String decodedJson = new String(Base64.getDecoder().decode(base64EncodedString));
+ deserializedPerson = mapper.readValue(decodedJson, Person.class);
+ System.out.println(deserializedPerson);
+
+ //xml
+
+ XmlMapper xmlMapper = new XmlMapper();
+ String xml = xmlMapper.writeValueAsString(person);
+ System.out.println(xml);
+
+ deserializedPerson = xmlMapper.readValue(xml, Person.class);
+ System.out.println(deserializedPerson);
+ }
+
+ record Person(long id, String name) {
+ }
+}
+
+class SerializationUtils {
+
+ public static String objectToString(Serializable obj) throws IOException {
+
+ try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ObjectOutputStream ois = new ObjectOutputStream(baos)) {
+
+ ois.writeObject(obj);
+ return Base64.getEncoder().encodeToString(baos.toByteArray());
+ }
+ }
+
+ public static Object stringToObject(String obj)
+ throws IOException, ClassNotFoundException {
+
+ byte[] data = Base64.getDecoder().decode(obj);
+ try (ObjectInputStream ois = new ObjectInputStream(
+ new ByteArrayInputStream(data))) {
+ return ois.readObject();
+ }
+ }
+}
diff --git a/src/main/java/com/howtodoinjava/core/streams/FilterAMap.java b/src/main/java/com/howtodoinjava/core/streams/FilterAMap.java
index e52075a..ef88b79 100644
--- a/src/main/java/com/howtodoinjava/core/streams/FilterAMap.java
+++ b/src/main/java/com/howtodoinjava/core/streams/FilterAMap.java
@@ -1,16 +1,21 @@
package com.howtodoinjava.core.streams;
import java.util.ArrayList;
-import java.util.HashMap;
+import java.util.Comparator;
+import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
+import java.util.function.Function;
+import java.util.function.Predicate;
import java.util.stream.Collectors;
-import lombok.AllArgsConstructor;
import lombok.Data;
public class FilterAMap {
+ @SuppressWarnings("unused")
public static void main(String[] args) {
+
Map usersMap = Map.of(
1, new User(1, "Alex"),
2, new User(2, "Allen"),
@@ -21,8 +26,8 @@ public static void main(String[] args) {
7, new User(7, "Don"),
8, new User(8, "Dave"));
- //1
- List idList = List.of(1,3,5,7);
+ // Collect Keys filtered by List of Keys
+ List idList = List.of(1, 3, 5, 7);
Map filteredMap1 = usersMap.entrySet()
.stream()
@@ -31,39 +36,133 @@ public static void main(String[] args) {
System.out.println(filteredMap1);
+ // Collect entries filtered by List of Keys
+
Map filteredMap2 = usersMap.entrySet()
.stream()
- .filter(entry -> idList.contains(entry.getValue().getId()))
+ .filter(entry -> idList.contains(entry.getValue().id()))
.collect(Collectors.toUnmodifiableMap(Map.Entry::getKey, Map.Entry::getValue));
System.out.println(filteredMap2);
- //2
+ // Collect Values filtered by List of Keys
List usersList1 = usersMap.values()
.stream()
- .filter(user -> idList.contains(user.getId()))
- .collect(Collectors.toUnmodifiableList());
+ .filter(user -> idList.contains(user.id()))
+ .toList();
System.out.println(usersList1);
//3
List usersList2 = new ArrayList<>();
- usersMap.entrySet().forEach( entry -> {
- if(idList.contains(entry.getValue().getId())) {
- usersList2.add(entry.getValue());
+ usersMap.forEach((_, value) -> {
+ if (idList.contains(value.id())) {
+ usersList2.add(value);
}
});
System.out.println(usersList2);
+
+ System.out.println("====================");
+
+ // Using Generic filters
+ Predicate predicate = key -> key > 4;
+ Comparator comparator = Comparator.comparing(Function.identity());
+
+ Map filteredMap = Filters.byKey(usersMap, predicate);
+ System.out.println(filteredMap);
+
+ Map filteredAndSortedMap = Filters.sortedByKey(usersMap, predicate, comparator);
+ System.out.println(filteredAndSortedMap);
+
+ Predicate valuePredicate = user -> user.name().startsWith("D");
+ Comparator valueComparator = Comparator.comparing(User::name);
+
+ Map filteredMapByValue = Filters.byValue(usersMap, valuePredicate);
+ System.out.println(filteredMapByValue);
+
+ Map filteredAndSortedMapByValue = Filters.sortedByValue(usersMap, valuePredicate,
+ valueComparator);
+ System.out.println(filteredAndSortedMapByValue);
+
+ Map filteredMapByKeyAndValue = Filters.byValue(
+ Filters.byKey(usersMap, predicate), valuePredicate);
+ System.out.println(filteredMapByKeyAndValue);
+
+ Map filteredMapByKeyAndValue_V2 = usersMap.entrySet().stream()
+ .filter((entry) -> entry.getKey() > 4 && entry.getValue().name().startsWith("D"))
+ .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
+ System.out.println(filteredMapByKeyAndValue);
}
+ static final class Filters {
+
+ private Filters() {
+ throw new AssertionError("Cannot be instantiated");
+ }
+
+ public static Map byKey(Map map, Predicate predicate) {
+
+ Objects.requireNonNull(map);
+ Objects.requireNonNull(predicate);
+
+ return map.entrySet()
+ .stream()
+ .filter(item -> predicate.test(item.getKey()))
+ .collect(Collectors.toMap(
+ Map.Entry::getKey, Map.Entry::getValue));
+ }
+
+ public static Map sortedByKey(
+ Map map, Predicate predicate, Comparator c) {
+
+ Objects.requireNonNull(map);
+ Objects.requireNonNull(predicate);
+ Objects.requireNonNull(c);
+
+ return map.entrySet()
+ .stream()
+ .filter(item -> predicate.test(item.getKey()))
+ .sorted(Map.Entry.comparingByKey(c))
+ .collect(Collectors.toMap(
+ Map.Entry::getKey, Map.Entry::getValue,
+ (_, c2) -> c2, LinkedHashMap::new));
+ }
+
+
+ public static Map byValue(
+ Map map, Predicate predicate) {
+
+ Objects.requireNonNull(map);
+ Objects.requireNonNull(predicate);
+
+ return map.entrySet()
+ .stream()
+ .filter(item -> predicate.test(item.getValue()))
+ .collect(Collectors.toMap(
+ Map.Entry::getKey, Map.Entry::getValue));
+ }
+
+ public static Map sortedByValue(Map map,
+ Predicate predicate, Comparator c) {
+
+ Objects.requireNonNull(map);
+ Objects.requireNonNull(predicate);
+ Objects.requireNonNull(c);
+
+ return map.entrySet()
+ .stream()
+ .filter(item -> predicate.test(item.getValue()))
+ .sorted(Map.Entry.comparingByValue(c))
+ .collect(Collectors.toMap(
+ Map.Entry::getKey, Map.Entry::getValue,
+ (_, c2) -> c2, LinkedHashMap::new));
+ }
+ }
}
-@Data
-@AllArgsConstructor
-class User {
- Integer id;
- String name;
+record User(Integer id, String name) {
+
}
diff --git a/src/main/java/com/howtodoinjava/core/streams/FilteringNestedCollections.java b/src/main/java/com/howtodoinjava/core/streams/FilteringNestedCollections.java
new file mode 100644
index 0000000..743343c
--- /dev/null
+++ b/src/main/java/com/howtodoinjava/core/streams/FilteringNestedCollections.java
@@ -0,0 +1,86 @@
+package com.howtodoinjava.core.streams;
+
+import java.util.List;
+import java.util.stream.Collectors;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+
+public class FilteringNestedCollections {
+
+ public static void main(String[] args) {
+
+ List accStmts = List.of(
+ new AccountStatement(1, "A001", List.of(
+ new Transaction(1, 100, "A001"),
+ new Transaction(2, 60, "A001"),
+ new Transaction(3, 550, "A001"))),
+ new AccountStatement(2, "A002", List.of(
+ new Transaction(4, 200, "A002"),
+ new Transaction(5, 160, "A002"),
+ new Transaction(6, 100, "A002"))),
+ new AccountStatement(3, "A003", List.of(
+ new Transaction(7, 10, "A003"),
+ new Transaction(8, 20, "A003"),
+ new Transaction(9, 3040, "A003"))));
+
+ List transactionsMoreThan500 = accStmts.stream()
+ .flatMap(stmt -> stmt.getTransactions().stream())
+ .filter(transaction -> transaction.getAmount() > 500)
+ .collect(Collectors.toList());
+
+ System.out.println(transactionsMoreThan500);
+
+ List transactionsMoreThan500_V2 = accStmts.stream()
+ .mapMulti((stmt, consumer) -> {
+ for (Transaction t : stmt.getTransactions()) {
+ if (t.getAmount() > 500) {
+ consumer.accept(t);
+ }
+ }
+ })
+ .collect(Collectors.toList());
+
+ System.out.println(transactionsMoreThan500_V2);
+
+ List stmtHavingTransactionsMoreThan500 = accStmts.stream()
+ .mapMulti((stmt, consumer) -> {
+ for (Transaction t : stmt.getTransactions()) {
+ if (t.getAmount() > 500) {
+ consumer.accept(stmt);
+ break;
+ }
+ }
+ })
+ .collect(Collectors.toList());
+
+ System.out.println(stmtHavingTransactionsMoreThan500);
+
+ List stmtHavingTransactionsMoreThan500_V2 = accStmts.stream()
+ .filter(
+ stmt -> stmt.getTransactions()
+ .stream()
+ .anyMatch(transaction -> transaction.getAmount() > 500)
+ )
+ .collect(Collectors.toList());
+
+ System.out.println(stmtHavingTransactionsMoreThan500_V2);
+ }
+}
+
+@Data
+@AllArgsConstructor
+class AccountStatement {
+
+ private long id;
+ private String accountNumber;
+ private List transactions;
+}
+
+@Data
+@AllArgsConstructor
+class Transaction {
+
+ private long id;
+ private double amount;
+ private String accountNumber;
+}
diff --git a/src/main/java/com/howtodoinjava/core/streams/MapMultiExample.java b/src/main/java/com/howtodoinjava/core/streams/MapMultiExample.java
new file mode 100644
index 0000000..c44b077
--- /dev/null
+++ b/src/main/java/com/howtodoinjava/core/streams/MapMultiExample.java
@@ -0,0 +1,90 @@
+package com.howtodoinjava.core.streams;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class MapMultiExample {
+
+ public static void main(String[] args) {
+
+ List numbers = List.of(1, 2, 3);
+
+ List multiples = numbers.stream().mapMulti((num, downstream) -> {
+ downstream.accept(num);
+ downstream.accept(num * num); // Add the square of the number
+ downstream.accept(num * num * num); // Add the cube of the number
+ }).toList();
+
+ System.out.println(multiples); // Output: [2, 3, 4, 6, 6, 9, 8, 12, 10, 15]
+
+ // second example
+
+ // Sample list of transactions
+ List transactions = List.of(
+ new Transaction("T1", 100, TransactionType.DEPOSIT),
+ new Transaction("T2", 50, TransactionType.WITHDRAWAL),
+ new Transaction("T3", 200, TransactionType.WITHDRAWAL));
+
+ // Process transactions and generate transaction events
+ List transactionEvents = transactions.stream()
+ .mapMulti((transaction, downstream) -> {
+ if (transaction.getType() == TransactionType.DEPOSIT) {
+ downstream.accept(new TransactionEvent("Deposit", transaction.getAmount()));
+ } else if (transaction.getType() == TransactionType.WITHDRAWAL) {
+ downstream.accept(new TransactionEvent("Withdrawal", transaction.getAmount()));
+ // If withdrawal amount is greater than 100, generate an additional fraud alert event
+ if (transaction.getAmount() > 100) {
+ downstream.accept(new TransactionEvent("Fraud Alert", transaction.getAmount()));
+ }
+ }
+ }).toList();
+
+ // Print the generated transaction events
+ transactionEvents.forEach(System.out::println);
+ }
+
+ static class Transaction {
+
+ private String id;
+ private double amount;
+ private TransactionType type;
+
+ public Transaction(String id, double amount, TransactionType type) {
+ this.id = id;
+ this.amount = amount;
+ this.type = type;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public double getAmount() {
+ return amount;
+ }
+
+ public TransactionType getType() {
+ return type;
+ }
+ }
+
+ static class TransactionEvent {
+
+ private String type;
+ private double amount;
+
+ public TransactionEvent(String type, double amount) {
+ this.type = type;
+ this.amount = amount;
+ }
+
+ @Override
+ public String toString() {
+ return "TransactionEvent{" + "type='" + type + '\'' + ", amount=" + amount + '}';
+ }
+ }
+
+ enum TransactionType {
+ DEPOSIT, WITHDRAWAL
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/howtodoinjava/core/streams/MethodReferenceVsLambdaExamples.java b/src/main/java/com/howtodoinjava/core/streams/MethodReferenceVsLambdaExamples.java
new file mode 100644
index 0000000..2f2d1c4
--- /dev/null
+++ b/src/main/java/com/howtodoinjava/core/streams/MethodReferenceVsLambdaExamples.java
@@ -0,0 +1,51 @@
+package com.howtodoinjava.core.streams;
+
+import java.util.function.Function;
+import lombok.Data;
+
+public class MethodReferenceVsLambdaExamples {
+
+ public static void main(String[] args) {
+
+ System.out.println("Creating method reference");
+ Function methodRef = Person::getFullName;
+
+ System.out.println("Creating lambda expression");
+ Function lambdaRef = (person) -> person.getFullName();
+
+ Person person = new Person("Lokesh", "Gupta");
+
+ System.out.println("a");
+ System.out.println(methodRef.apply(person));
+ System.out.println(methodRef.apply(person));
+ System.out.println(methodRef.apply(person));
+
+ System.out.println("b");
+ System.out.println(lambdaRef.apply(person));
+ System.out.println(lambdaRef.apply(person));
+ System.out.println(lambdaRef.apply(person));
+
+
+ }
+
+ @Data
+ static class Person {
+ private String firstName;
+ private String lastName;
+
+ public Person() {
+ System.out.println("Default Constructor called.");
+ }
+
+ public Person(String firstName, String lastName) {
+ System.out.println("Custom Constructor called.");
+ this.firstName = firstName;
+ this.lastName = lastName;
+ }
+
+ public String getFullName() {
+ return STR."\{firstName} \{lastName}";
+ }
+ }
+}
+
diff --git a/src/main/java/com/howtodoinjava/core/streams/StreamContainsAnyContainsAll.java b/src/main/java/com/howtodoinjava/core/streams/StreamContainsAnyContainsAll.java
new file mode 100644
index 0000000..4b85a16
--- /dev/null
+++ b/src/main/java/com/howtodoinjava/core/streams/StreamContainsAnyContainsAll.java
@@ -0,0 +1,94 @@
+package com.howtodoinjava.core.streams;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.Objects;
+
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.junit.jupiter.api.Assertions;
+
+public class StreamContainsAnyContainsAll {
+
+ public static void main(String[] args) {
+ List cars = Arrays.asList(
+ new Car("Dacia", "diesel", 100),
+ new Car("Lexus", "gasoline", 300),
+ new Car("Ford", "electric", 200)
+ );
+
+ Car car1 = new Car("Dacia", "diesel", 100); //Present in original list
+ Car car2 = new Car("Ford", "electric", 80);
+ Car car3 = new Car("Chevrolet", "electric", 150);
+
+ Assertions.assertTrue(StreamUtils.contains(cars.stream(), car1));
+ Assertions.assertFalse(StreamUtils.contains(cars.stream(), car2));
+
+ Assertions.assertTrue(StreamUtils.containsAny(cars.stream(), car1, car2));
+ Assertions.assertFalse(StreamUtils.containsAny(cars.stream(), car2, car3));
+ Assertions.assertTrue(StreamUtils.containsAny(cars.stream(), List.of(car1, car2, car3)));
+ Assertions.assertTrue(StreamUtils.containsAny(cars.stream(), Stream.of(car1, car2, car3)));
+
+
+ Assertions.assertTrue(StreamUtils.containsAll(cars.stream(), car1));
+ Assertions.assertFalse(StreamUtils.containsAll(cars.stream(), car1, car3));
+ Assertions.assertTrue(StreamUtils.containsAll(cars.stream(), List.of(car1)));
+ Assertions.assertFalse(StreamUtils.containsAll(cars.stream(), Stream.of(car2)));
+ }
+}
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+class Car {
+
+ String model;
+ String fuel;
+ Integer capacity;
+}
+
+final class StreamUtils {
+
+ private StreamUtils() {
+ // Private constructor to prevent instantiation
+ }
+
+ public static boolean contains(Stream stream, T element) {
+ Objects.requireNonNull(stream);
+ Objects.requireNonNull(element);
+ return stream.anyMatch(Predicate.isEqual(element));
+ }
+
+ public static boolean containsAny(Stream stream, Collection extends T> elements) {
+ return containsAny(stream, elements.stream());
+ }
+
+ public static boolean containsAny(Stream stream, T... elements) {
+ return containsAny(stream, Stream.of(elements));
+ }
+
+ public static boolean containsAny(Stream stream, Stream extends T> elements) {
+ Objects.requireNonNull(stream);
+ Objects.requireNonNull(elements);
+ return elements.anyMatch(stream.collect(Collectors.toSet())::contains);
+ }
+
+ public static boolean containsAll(Stream stream, Collection extends T> elements) {
+ return containsAll(stream, elements.stream());
+ }
+
+ public static boolean containsAll(Stream stream, T... elements) {
+ return containsAll(stream, Stream.of(elements));
+ }
+
+ public static boolean containsAll(Stream stream, Stream extends T> elements) {
+ Objects.requireNonNull(stream);
+ Objects.requireNonNull(elements);
+ return elements.allMatch(stream.collect(Collectors.toSet())::contains);
+ }
+}
diff --git a/src/main/java/com/howtodoinjava/core/streams/TeeingCollectorExample.java b/src/main/java/com/howtodoinjava/core/streams/TeeingCollectorExample.java
new file mode 100644
index 0000000..74d62c9
--- /dev/null
+++ b/src/main/java/com/howtodoinjava/core/streams/TeeingCollectorExample.java
@@ -0,0 +1,8 @@
+package com.howtodoinjava.core.streams;
+
+public class TeeingCollectorExample {
+
+ public static void main(String[] args) {
+
+ }
+}
diff --git a/src/main/java/com/howtodoinjava/core/string/MultilineStringExample.java b/src/main/java/com/howtodoinjava/core/string/MultilineStringExample.java
new file mode 100644
index 0000000..f74ed3a
--- /dev/null
+++ b/src/main/java/com/howtodoinjava/core/string/MultilineStringExample.java
@@ -0,0 +1,84 @@
+package com.howtodoinjava.core.string;
+
+import java.util.StringJoiner;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+@SuppressWarnings("StringTemplateMigration")
+public class MultilineStringExample {
+
+ public static void main(String[] args) {
+
+ //Text Blocks
+ String content = """
+ Line 1
+ 'Line 2'
+ "Line 3"
+ Line 4
+ """;
+
+ System.out.println(content);
+
+ String json = """
+ {
+ "name": "John Doe",
+ "age": 30,
+ "city": "New York"
+ }
+ """;
+ System.out.println(json);
+
+ // String Concatenation
+
+ String NEW_LINE = System.getProperty("line.separator");
+
+ content = "Line 1" +
+ NEW_LINE +
+ "'Line 2'" +
+ NEW_LINE +
+ "\"Line 3\"" +
+ NEW_LINE +
+ "Line 4 ";
+
+ System.out.println(content);
+
+ StringBuffer sb = new StringBuffer();
+
+ content = sb.append("Line 1")
+ .append(NEW_LINE)
+ .append("'Line 2'")
+ .append(NEW_LINE)
+ .append("\"Line 3\"")
+ .append(NEW_LINE)
+ .append("Line 4 ").toString();
+
+ System.out.println(content);
+
+ //String Join
+ content = String.join(NEW_LINE,
+ "Line 1",
+ "'Line 2'",
+ "\"Line 3\"",
+ "Line 4 ");
+
+ System.out.println(content);
+
+ //StringJoiner
+
+ StringJoiner stringJoiner = new StringJoiner(NEW_LINE);
+
+ content = stringJoiner.add("Line 1")
+ .add("'Line 2'")
+ .add("\"Line 3\"")
+ .add("Line 4 ").toString();
+
+ System.out.println(content);
+
+ //Stream API
+
+ content = Stream.of("Line 1", "'Line 2'", "\"Line 3\"", "Line 4 ")
+ .collect(Collectors.joining(NEW_LINE));
+
+ System.out.println(content);
+ }
+}
diff --git a/src/main/java/com/howtodoinjava/core/string/StringConcatenationBenchmark.java b/src/main/java/com/howtodoinjava/core/string/StringConcatenationBenchmark.java
new file mode 100644
index 0000000..7a9b9ad
--- /dev/null
+++ b/src/main/java/com/howtodoinjava/core/string/StringConcatenationBenchmark.java
@@ -0,0 +1,82 @@
+package com.howtodoinjava.core.string;
+
+import java.time.LocalTime;
+import java.util.concurrent.TimeUnit;
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.OutputTimeUnit;
+import org.openjdk.jmh.annotations.Param;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.runner.Runner;
+import org.openjdk.jmh.runner.options.Options;
+import org.openjdk.jmh.runner.options.OptionsBuilder;
+
+@State(Scope.Thread)
+public class StringConcatenationBenchmark {
+
+ @Param({"10", "100", "1000"})
+ private int count;
+
+ private String baseString;
+
+ @Setup
+ public void setup() {
+ baseString = "SampleString";
+ }
+
+ @Benchmark
+ @BenchmarkMode(Mode.AverageTime)
+ @OutputTimeUnit(TimeUnit.MICROSECONDS)
+ public String testStringConcatenation() {
+ String result = "";
+ for (int i = 0; i < count; i++) {
+ result += baseString;
+ }
+ return result;
+ }
+
+ @Benchmark
+ @BenchmarkMode(Mode.AverageTime)
+ @OutputTimeUnit(TimeUnit.MICROSECONDS)
+ public String testStringBuilder() {
+ StringBuilder builder = new StringBuilder();
+ for (int i = 0; i < count; i++) {
+ builder.append(baseString);
+ }
+ return builder.toString();
+ }
+
+ @Benchmark
+ @BenchmarkMode(Mode.AverageTime)
+ @OutputTimeUnit(TimeUnit.MICROSECONDS)
+ public String testStringBuffer() {
+ StringBuffer buffer = new StringBuffer();
+ for (int i = 0; i < count; i++) {
+ buffer.append(baseString);
+ }
+ return buffer.toString();
+ }
+
+ public static void main(String[] args) throws Exception {
+
+ var name = "Alex";
+ var time = LocalTime.now();
+
+ String greeting = "Hello " + name + ", how are you?\nThe current time is " + time + " now!";
+ System.out.println(greeting);
+
+ String greetingTemplate = STR."Hello \{name}, how are you?\nThe current time is \{time} now!";
+ System.out.println(greetingTemplate);
+
+ Options opt = new OptionsBuilder()
+ .include(StringConcatenationBenchmark.class.getSimpleName())
+ .forks(1)
+ .build();
+
+ new Runner(opt).run();
+ }
+}
+
diff --git a/src/main/java/com/howtodoinjava/core/string/StringIndentExample.java b/src/main/java/com/howtodoinjava/core/string/StringIndentExample.java
new file mode 100644
index 0000000..c2c849a
--- /dev/null
+++ b/src/main/java/com/howtodoinjava/core/string/StringIndentExample.java
@@ -0,0 +1,24 @@
+package com.howtodoinjava.core.string;
+
+public class StringIndentExample {
+
+ public static void main(String[] args) {
+ String line1 = "ABC".indent(8);
+ System.out.println(line1.replace(" ", "-"));
+
+ String line2 = "ABC".indent(8).indent(-5);
+ System.out.println(line2.replace(" ", "-"));
+
+ String textBlock = """
+ Line 1
+ Line 2""";
+
+ String indentedBlock = """
+ Line 1
+ Line 2""".indent(8);
+
+ System.out.println(textBlock.replace(" ", "-"));
+ System.out.println(indentedBlock.replace(" ", "-"));
+ }
+
+}
diff --git a/src/main/java/com/howtodoinjava/core/string/TextBlockFormatting.java b/src/main/java/com/howtodoinjava/core/string/TextBlockFormatting.java
new file mode 100644
index 0000000..4cea32d
--- /dev/null
+++ b/src/main/java/com/howtodoinjava/core/string/TextBlockFormatting.java
@@ -0,0 +1,68 @@
+package com.howtodoinjava.core.string;
+
+import java.text.MessageFormat;
+
+public class TextBlockFormatting {
+
+ public static void main(String[] args) {
+
+ //Expected Output
+ /*{
+ "id": 1001,
+ "name": "John Doe",
+ "age": 34
+ }*/
+
+ int id = 1001;
+ int age = 34;
+ String name = "John Doe";
+
+ Object[] formatArguments = {
+ 1001, // id
+ "John Doe", // name
+ 34 // age
+ };
+
+
+ /*String greeting = """
+ Hello, """ + name + """
+ Welcome to Java text blocks!
+ """;
+
+ System.out.println(greeting.toString()); //Prints "Hello,John DoeWelcome to Java text blocks!"*/
+
+
+
+ String textBlock = """
+ {
+ "id": %d,
+ "name": "%s",
+ "age": %d
+ }
+ """;
+
+ String formattedTextBlock1 = String.format(textBlock, formatArguments);
+ System.out.println(formattedTextBlock1);
+
+ String formattedTextBlock2 = String.format(textBlock, id, name, age);
+ System.out.println(formattedTextBlock2);
+
+
+ String json = """
+ '{'
+ "id": {0, number, #},
+ "name": "{1}",
+ "salary": "{2, number, integer}"
+ '}'
+ """;
+
+ Object[] arguments = {
+ 1001, // id
+ "John Doe", // name
+ 34000 // salary
+ };
+
+ String formattedTextBlock3 = MessageFormat.format(json, arguments);
+ System.out.println(formattedTextBlock3);
+ }
+}
diff --git a/src/main/java/com/howtodoinjava/jaxb/Main.java b/src/main/java/com/howtodoinjava/jaxb/Main.java
index 6d9ea6e..5dc920e 100644
--- a/src/main/java/com/howtodoinjava/jaxb/Main.java
+++ b/src/main/java/com/howtodoinjava/jaxb/Main.java
@@ -1,10 +1,15 @@
package com.howtodoinjava.jaxb;
+import com.howtodoinjava.xml.model.Department;
+import com.howtodoinjava.xml.model.Employee;
+import java.io.File;
+import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
@@ -24,6 +29,16 @@ public static void main(final String[] args) throws JAXBException {
JAXBContext context6 = getJAXBContext(Book.class);
JAXBContext context7 = getJAXBContext(Book.class);
JAXBContext context8 = getJAXBContext(Book.class);
+
+ JAXBContext jaxbContext = JAXBContext.newInstance( Employee.class );
+ Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
+
+ Employee employee = new Employee(1, "Lokesh", "Gupta", "India", new Department(101, "IT"));
+
+ //Overloaded methods to marshal to different outputs
+ jaxbMarshaller.marshal(employee, System.out);
+ jaxbMarshaller.marshal(employee, new File("output.xml"));
+ jaxbMarshaller.marshal(employee, new StringWriter());
}
@SuppressWarnings("rawtypes")
diff --git a/src/main/java/com/howtodoinjava/jaxb/MarshalListExample.java b/src/main/java/com/howtodoinjava/jaxb/MarshalListExample.java
new file mode 100644
index 0000000..ad6963e
--- /dev/null
+++ b/src/main/java/com/howtodoinjava/jaxb/MarshalListExample.java
@@ -0,0 +1,67 @@
+package com.howtodoinjava.jaxb;
+
+import com.howtodoinjava.xml.model.Employee;
+import jakarta.xml.bind.Unmarshaller;
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import jakarta.xml.bind.JAXBContext;
+import jakarta.xml.bind.JAXBException;
+import jakarta.xml.bind.Marshaller;
+import jakarta.xml.bind.annotation.XmlAccessType;
+import jakarta.xml.bind.annotation.XmlAccessorType;
+import jakarta.xml.bind.annotation.XmlElement;
+import jakarta.xml.bind.annotation.XmlRootElement;
+
+public class MarshalListExample {
+
+ public static void main(String[] args) throws JAXBException {
+ Employees employees = new Employees();
+
+ //Add the employees in list
+ Employee emp1 = new Employee(1, "Lokesh", "Gupta", null, null);
+ Employee emp2 = new Employee(1, "John", "McLean", null, null);
+ employees.getEmployees().add(emp1);
+ employees.getEmployees().add(emp2);
+
+ //Write to XML
+ JAXBContext jaxbContext = JAXBContext.newInstance(Employees.class);
+ Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
+
+ jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
+
+ //Marshal the employees list in console
+ jaxbMarshaller.marshal(employees, System.out);
+
+ //Marshal the employees list in file
+ jaxbMarshaller.marshal(employees, new File("out.xml"));
+
+ //unmarshal example
+ Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
+
+ //We had written this file in marshalling example
+ Employees emps = (Employees) jaxbUnmarshaller.unmarshal(new File("out.xml"));
+
+ for (Employee emp : emps.getEmployees()) {
+
+ System.out.println(emp.getId());
+ System.out.println(emp.getFirstName());
+ }
+ }
+}
+
+@XmlRootElement(name = "employees")
+@XmlAccessorType(XmlAccessType.FIELD)
+class Employees {
+
+ @XmlElement(name = "employee")
+ private List employees = new ArrayList<>();
+
+ public List getEmployees() {
+ return employees;
+ }
+
+ public void setEmployees(List employees) {
+ this.employees = employees;
+ }
+}
diff --git a/src/main/java/com/howtodoinjava/jaxb/NoDefaultConstructor.java b/src/main/java/com/howtodoinjava/jaxb/NoDefaultConstructor.java
new file mode 100644
index 0000000..1da0b1e
--- /dev/null
+++ b/src/main/java/com/howtodoinjava/jaxb/NoDefaultConstructor.java
@@ -0,0 +1,95 @@
+package com.howtodoinjava.jaxb;
+
+import jakarta.xml.bind.JAXBContext;
+import jakarta.xml.bind.JAXBException;
+import jakarta.xml.bind.Marshaller;
+import jakarta.xml.bind.Unmarshaller;
+import jakarta.xml.bind.annotation.XmlAccessType;
+import jakarta.xml.bind.annotation.XmlAccessorType;
+import jakarta.xml.bind.annotation.XmlRootElement;
+import jakarta.xml.bind.annotation.XmlTransient;
+import jakarta.xml.bind.annotation.adapters.XmlAdapter;
+import jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
+import java.io.StringReader;
+import java.io.StringWriter;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+public class NoDefaultConstructor {
+
+ public static void main(String[] args) throws JAXBException {
+ Address address = new Address("Line 1", "Line 2", "New Delhi", "India", new PinCode("110075"));
+ JAXBContext jaxbContext = JAXBContext.newInstance(Address.class);
+ Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
+ StringWriter stringWriter = new StringWriter();
+ jaxbMarshaller.marshal(address, stringWriter);
+ String XML = stringWriter.toString();
+ System.out.println(XML);
+
+ String xmlAddress = """
+
+
+ Line 1
+ Line 2
+ New Delhi
+ India
+
+ 110075
+
+
+ """;
+
+ Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
+ Address newAddress = (Address) jaxbUnmarshaller.unmarshal(new StringReader(xmlAddress));
+ System.out.println(newAddress);
+ }
+}
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@XmlRootElement(name = "Address")
+@XmlAccessorType(XmlAccessType.FIELD)
+class Address {
+ String line1;
+ String line2;
+ String city;
+ String country;
+ //@XmlTransient
+ @XmlJavaTypeAdapter(PinCodeAdapter.class)
+ PinCode pinCode;
+}
+@Data
+class PinCode {
+ String code;
+
+ public PinCode(String code){
+ this.code = code;
+ }
+}
+
+@Data
+class XmlPinCode {
+
+ String code;
+ public XmlPinCode(){
+ }
+
+ public XmlPinCode(String code){
+ this.code = code;
+ }
+}
+
+class PinCodeAdapter extends XmlAdapter {
+
+ @Override
+ public PinCode unmarshal(XmlPinCode v) throws Exception {
+ return new PinCode(v.getCode());
+ }
+
+ @Override
+ public XmlPinCode marshal(PinCode v) throws Exception {
+ return new XmlPinCode(v.getCode());
+ }
+}
diff --git a/src/main/java/com/howtodoinjava/jaxb/ReadWriteXML.java b/src/main/java/com/howtodoinjava/jaxb/ReadWriteXML.java
new file mode 100644
index 0000000..189a964
--- /dev/null
+++ b/src/main/java/com/howtodoinjava/jaxb/ReadWriteXML.java
@@ -0,0 +1,37 @@
+package com.howtodoinjava.jaxb;
+
+import com.howtodoinjava.xml.model.Employee;
+import jakarta.xml.bind.JAXBContext;
+import jakarta.xml.bind.JAXBException;
+import jakarta.xml.bind.Unmarshaller;
+import java.io.StringReader;
+
+public class ReadWriteXML {
+
+ public static void main(String[] args) {
+
+ // Convert XML String to Java Object
+
+ String xmlString = "" +
+ " " +
+ " 101" +
+ " IT" +
+ " " +
+ " India" +
+ " Lokesh" +
+ " 1" +
+ " Gupta" +
+ "";
+
+ JAXBContext jaxbContext;
+ try {
+ jaxbContext = JAXBContext.newInstance(Employee.class);
+ Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
+ Employee employee = (Employee) jaxbUnmarshaller.unmarshal(new StringReader(xmlString));
+ System.out.println(employee);
+ } catch (JAXBException e) {
+ e.printStackTrace();
+ }
+
+ }
+}
diff --git a/src/main/java/com/howtodoinjava/jaxb/XmlTypeAdapterOverInterface.java b/src/main/java/com/howtodoinjava/jaxb/XmlTypeAdapterOverInterface.java
new file mode 100644
index 0000000..d004555
--- /dev/null
+++ b/src/main/java/com/howtodoinjava/jaxb/XmlTypeAdapterOverInterface.java
@@ -0,0 +1,61 @@
+package com.howtodoinjava.jaxb;
+
+import jakarta.xml.bind.JAXBContext;
+import jakarta.xml.bind.JAXBException;
+import jakarta.xml.bind.Marshaller;
+import jakarta.xml.bind.Unmarshaller;
+import jakarta.xml.bind.annotation.XmlAccessType;
+import jakarta.xml.bind.annotation.XmlAccessorType;
+import jakarta.xml.bind.annotation.XmlRootElement;
+import jakarta.xml.bind.annotation.adapters.XmlAdapter;
+import jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.time.LocalDateTime;
+import java.time.temporal.Temporal;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+public class XmlTypeAdapterOverInterface {
+
+ public static void main(String[] args) throws JAXBException {
+ JAXBContext jaxbContext = JAXBContext.newInstance(BatchJob.class);
+ Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
+ StringWriter stringWriter = new StringWriter();
+ jaxbMarshaller.marshal(new BatchJob(LocalDateTime.now()), stringWriter);
+ String XML = stringWriter.toString();
+ System.out.println(XML);
+
+ Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
+ BatchJob newBatchJob = (BatchJob) jaxbUnmarshaller.unmarshal(new StringReader(XML));
+ System.out.println(newBatchJob);
+ }
+}
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@XmlRootElement(name = "BatchJob")
+@XmlAccessorType(XmlAccessType.FIELD)
+class BatchJob {
+
+ @XmlJavaTypeAdapter(TemporalAdapter.class)
+ Temporal startTime;
+}
+
+class TemporalAdapter extends XmlAdapter {
+
+ @Override
+ public Temporal unmarshal(String v) throws Exception {
+ return LocalDateTime.parse(v);
+ }
+
+ @Override
+ public String marshal(Temporal v) throws Exception {
+ return v.toString();
+ }
+}
+
+
+
diff --git a/src/main/java/com/howtodoinjava/reflection/CallingInterfaceMethodWithoutImplementing.java b/src/main/java/com/howtodoinjava/reflection/CallingInterfaceMethodWithoutImplementing.java
new file mode 100644
index 0000000..b1e5f80
--- /dev/null
+++ b/src/main/java/com/howtodoinjava/reflection/CallingInterfaceMethodWithoutImplementing.java
@@ -0,0 +1,96 @@
+package com.howtodoinjava.reflection;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodHandles.Lookup;
+import java.lang.invoke.MethodType;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Proxy;
+
+public class CallingInterfaceMethodWithoutImplementing {
+
+ public static void main(String[] args) {
+
+ //Since Java 16
+
+ Movable movableProxy = (Movable) Proxy.newProxyInstance(
+ Movable.class.getClassLoader(),
+ new Class>[]{Movable.class}, (o, m, p) -> {
+ if (m.isDefault()) {
+ return InvocationHandler.invokeDefault(o, m, p);
+ }
+ return null;
+ });
+
+ // invoke interface methods
+ movableProxy.move();
+ String returnedValue = movableProxy.moveWithParamAndReturn("lion");
+ System.out.println(returnedValue);
+
+ //Java 15 and Before
+
+ Movable movableProxy2 = (Movable) Proxy.newProxyInstance(
+ Movable.class.getClassLoader(),
+ new Class>[]{Movable.class}, (o, m, p) -> {
+ if (m.isDefault()) {
+ // Adjust the method type as per the default method's signature
+ MethodType methodType;
+ if (m.getName().equals("move")) {
+ methodType = MethodType.methodType(void.class);
+ } else if (m.getName().equals("moveWithParamAndReturn")) {
+ methodType = MethodType.methodType(String.class, String.class);
+ } else {
+ throw new UnsupportedOperationException("Unknown default method: " + m.getName());
+ }
+ return MethodHandles.lookup()
+ .findSpecial(Movable.class, m.getName(),
+ methodType,
+ Movable.class)
+ .bindTo(o)
+ .invokeWithArguments(p);
+ }
+ return null;
+ });
+
+ movableProxy2.move();
+ returnedValue = movableProxy2.moveWithParamAndReturn("lion");
+ System.out.println(returnedValue);
+
+ //JDK 8
+
+ Movable movableProxy3 = (Movable) Proxy.newProxyInstance(
+ Movable.class.getClassLoader(),
+ new Class>[]{Movable.class}, (o, m, p) -> {
+ if (m.isDefault()) {
+ Constructor cntr = Lookup.class
+ .getDeclaredConstructor(Class.class);
+ cntr.setAccessible(true);
+ return cntr.newInstance(Movable.class)
+ .in(Movable.class)
+ .unreflectSpecial(m, Movable.class)
+ .bindTo(o)
+ .invokeWithArguments(p);
+ }
+ return null;
+ });
+
+ movableProxy3.move();
+ returnedValue = movableProxy3.moveWithParamAndReturn("lion");
+ System.out.println(returnedValue);
+ }
+
+}
+
+interface Movable {
+
+ default void move() {
+ System.out.println("Inside Movable.move()");
+ }
+
+ default String moveWithParamAndReturn(String param) {
+ System.out.println("Inside Movable.moveWithParamAndReturn()");
+ return STR."\{param}-returned";
+ }
+
+ void moveToImplement();
+}
diff --git a/src/main/java/com/howtodoinjava/regex/StartsWithEndsWith.java b/src/main/java/com/howtodoinjava/regex/StartsWithEndsWith.java
new file mode 100644
index 0000000..9738499
--- /dev/null
+++ b/src/main/java/com/howtodoinjava/regex/StartsWithEndsWith.java
@@ -0,0 +1,33 @@
+package com.howtodoinjava.regex;
+
+import java.util.List;
+import java.util.regex.*;
+
+public class StartsWithEndsWith {
+
+ public static void main(String[] args) {
+
+ List lines = List.of(
+ "The cat is cute",
+ "The category is empty",
+ "The noncategory is also empty");
+
+ Pattern pattern = Pattern.compile("\\bcat\\b", Pattern.CASE_INSENSITIVE);
+
+ for(String line: lines) {
+ Matcher matcher = pattern.matcher(line);
+ while (matcher.find()) {
+ //System.out.println(STR."Match found: \{matcher.group()}");
+ }
+ }
+
+ pattern = Pattern.compile("\\b\\w*cat\\w*\\b");
+
+ for(String line: lines) {
+ Matcher matcher = pattern.matcher(line);
+ while (matcher.find()) {
+ System.out.println(STR."Match found: \{matcher.group()}");
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/howtodoinjava/xml/model/Employee.java b/src/main/java/com/howtodoinjava/xml/model/Employee.java
index 6c2c99f..bb722ec 100644
--- a/src/main/java/com/howtodoinjava/xml/model/Employee.java
+++ b/src/main/java/com/howtodoinjava/xml/model/Employee.java
@@ -2,18 +2,16 @@
import jakarta.xml.bind.annotation.XmlAccessType;
import jakarta.xml.bind.annotation.XmlAccessorType;
-import jakarta.xml.bind.annotation.XmlAttribute;
-import jakarta.xml.bind.annotation.XmlElement;
import jakarta.xml.bind.annotation.XmlRootElement;
import java.io.Serializable;
-@XmlRootElement(name="employee")
+@XmlRootElement(name = "employee")
@XmlAccessorType(XmlAccessType.FIELD)
public class Employee implements Serializable {
private static final long serialVersionUID = 1L;
- @XmlAttribute
+ //@XmlAttribute
private Integer id;
private String firstName;
private String lastName;
@@ -24,7 +22,7 @@ public Employee() {
super();
}
- public Employee(int id, String fName, String lName, Department department) {
+ public Employee(int id, String fName, String lName, String location, Department department) {
super();
this.id = id;
this.firstName = fName;
@@ -75,7 +73,6 @@ public void setLocation(String location) {
@Override
public String toString() {
- return "Employee [id=" + id + ", firstName=" + firstName + ", lastName=" + lastName + ", department="
- + department + "]";
+ return STR."Employee{id=\{id}, firstName='\{firstName}\{'\''}, lastName='\{lastName}\{'\''}, location='\{location}\{'\''}, department=\{department}\{'}'}";
}
}
\ No newline at end of file