Merge remote-tracking branch 'upstream/master' into feature/BAEL-7062-GetIndex

This commit is contained in:
Niket Agrawal
2023-12-14 19:56:27 +05:30
2179 changed files with 27446 additions and 6797 deletions
@@ -5,7 +5,6 @@ This module contains articles about Java 11 core features
### Relevant articles
- [Guide To Java 8 Optional](https://www.baeldung.com/java-optional)
- [Guide to Java Reflection](http://www.baeldung.com/java-reflection)
- [Guide to Java 8s Collectors](https://www.baeldung.com/java-8-collectors)
- [New Features in Java 11](https://www.baeldung.com/java-11-new-features)
- [Getting the Java Version at Runtime](https://www.baeldung.com/get-java-version-runtime)
- [Invoking a SOAP Web Service in Java](https://www.baeldung.com/java-soap-web-service)
@@ -1,237 +0,0 @@
package com.baeldung.collectors;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import org.junit.Test;
import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collector;
import static com.google.common.collect.Sets.newHashSet;
import static java.util.stream.Collectors.*;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
public class Java8CollectorsUnitTest {
private final List<String> givenList = Arrays.asList("a", "bb", "ccc", "dd");
private final List<String> listWithDuplicates = Arrays.asList("a", "bb", "c", "d", "bb");
@Test
public void whenCollectingToList_shouldCollectToList() throws Exception {
final List<String> result = givenList.stream().collect(toList());
assertThat(result).containsAll(givenList);
}
@Test
public void whenCollectingToUnmodifiableList_shouldCollectToUnmodifiableList() {
final List<String> result = givenList.stream().collect(toUnmodifiableList());
assertThatThrownBy(() -> result.add("foo"))
.isInstanceOf(UnsupportedOperationException.class);
}
@Test
public void whenCollectingToSet_shouldCollectToSet() throws Exception {
final Set<String> result = givenList.stream().collect(toSet());
assertThat(result).containsAll(givenList);
}
@Test
public void whenCollectingToUnmodifiableSet_shouldCollectToUnmodifiableSet() {
final Set<String> result = givenList.stream().collect(toUnmodifiableSet());
assertThatThrownBy(() -> result.add("foo"))
.isInstanceOf(UnsupportedOperationException.class);
}
@Test
public void givenContainsDuplicateElements_whenCollectingToSet_shouldAddDuplicateElementsOnlyOnce() throws Exception {
final Set<String> result = listWithDuplicates.stream().collect(toSet());
assertThat(result).hasSize(4);
}
@Test
public void whenCollectingToCollection_shouldCollectToCollection() throws Exception {
final List<String> result = givenList.stream().collect(toCollection(LinkedList::new));
assertThat(result).containsAll(givenList).isInstanceOf(LinkedList.class);
}
@Test
public void whenCollectingToImmutableCollection_shouldThrowException() throws Exception {
assertThatThrownBy(() -> {
givenList.stream().collect(toCollection(ImmutableList::of));
}).isInstanceOf(UnsupportedOperationException.class);
}
@Test
public void whenCollectingToMap_shouldCollectToMap() throws Exception {
final Map<String, Integer> result = givenList.stream().collect(toMap(Function.identity(), String::length));
assertThat(result).containsEntry("a", 1).containsEntry("bb", 2).containsEntry("ccc", 3).containsEntry("dd", 2);
}
@Test
public void whenCollectingToUnmodifiableMap_shouldCollectToUnmodifiableMap() {
final Map<String, Integer> result = givenList.stream()
.collect(toUnmodifiableMap(Function.identity(), String::length));
assertThatThrownBy(() -> result.put("foo", 3))
.isInstanceOf(UnsupportedOperationException.class);
}
@Test
public void whenCollectingToMapwWithDuplicates_shouldCollectToMapMergingTheIdenticalItems() throws Exception {
final Map<String, Integer> result = listWithDuplicates.stream().collect(
toMap(
Function.identity(),
String::length,
(item, identicalItem) -> item
)
);
assertThat(result).containsEntry("a", 1).containsEntry("bb", 2).containsEntry("c", 1).containsEntry("d", 1);
}
@Test
public void givenContainsDuplicateElements_whenCollectingToMap_shouldThrowException() throws Exception {
assertThatThrownBy(() -> {
listWithDuplicates.stream().collect(toMap(Function.identity(), String::length));
}).isInstanceOf(IllegalStateException.class);
}
@Test
public void whenCollectingAndThen_shouldCollect() throws Exception {
final List<String> result = givenList.stream().collect(collectingAndThen(toList(), ImmutableList::copyOf));
assertThat(result).containsAll(givenList).isInstanceOf(ImmutableList.class);
}
@Test
public void whenJoining_shouldJoin() throws Exception {
final String result = givenList.stream().collect(joining());
assertThat(result).isEqualTo("abbcccdd");
}
@Test
public void whenJoiningWithSeparator_shouldJoinWithSeparator() throws Exception {
final String result = givenList.stream().collect(joining(" "));
assertThat(result).isEqualTo("a bb ccc dd");
}
@Test
public void whenJoiningWithSeparatorAndPrefixAndPostfix_shouldJoinWithSeparatorPrePost() throws Exception {
final String result = givenList.stream().collect(joining(" ", "PRE-", "-POST"));
assertThat(result).isEqualTo("PRE-a bb ccc dd-POST");
}
@Test
public void whenPartitioningBy_shouldPartition() throws Exception {
final Map<Boolean, List<String>> result = givenList.stream().collect(partitioningBy(s -> s.length() > 2));
assertThat(result).containsKeys(true, false).satisfies(booleanListMap -> {
assertThat(booleanListMap.get(true)).contains("ccc");
assertThat(booleanListMap.get(false)).contains("a", "bb", "dd");
});
}
@Test
public void whenCounting_shouldCount() throws Exception {
final Long result = givenList.stream().collect(counting());
assertThat(result).isEqualTo(4);
}
@Test
public void whenSummarizing_shouldSummarize() throws Exception {
final DoubleSummaryStatistics result = givenList.stream().collect(summarizingDouble(String::length));
assertThat(result.getAverage()).isEqualTo(2);
assertThat(result.getCount()).isEqualTo(4);
assertThat(result.getMax()).isEqualTo(3);
assertThat(result.getMin()).isEqualTo(1);
assertThat(result.getSum()).isEqualTo(8);
}
@Test
public void whenAveraging_shouldAverage() throws Exception {
final Double result = givenList.stream().collect(averagingDouble(String::length));
assertThat(result).isEqualTo(2);
}
@Test
public void whenSumming_shouldSum() throws Exception {
final Double result = givenList.stream().filter(i -> true).collect(summingDouble(String::length));
assertThat(result).isEqualTo(8);
}
@Test
public void whenMaxingBy_shouldMaxBy() throws Exception {
final Optional<String> result = givenList.stream().collect(maxBy(Comparator.naturalOrder()));
assertThat(result).isPresent().hasValue("dd");
}
@Test
public void whenGroupingBy_shouldGroupBy() throws Exception {
final Map<Integer, Set<String>> result = givenList.stream().collect(groupingBy(String::length, toSet()));
assertThat(result).containsEntry(1, newHashSet("a")).containsEntry(2, newHashSet("bb", "dd")).containsEntry(3, newHashSet("ccc"));
}
@Test
public void whenCreatingCustomCollector_shouldCollect() throws Exception {
final ImmutableSet<String> result = givenList.stream().collect(toImmutableSet());
assertThat(result).isInstanceOf(ImmutableSet.class).contains("a", "bb", "ccc", "dd");
}
private static <T> ImmutableSetCollector<T> toImmutableSet() {
return new ImmutableSetCollector<>();
}
private static class ImmutableSetCollector<T> implements Collector<T, ImmutableSet.Builder<T>, ImmutableSet<T>> {
@Override
public Supplier<ImmutableSet.Builder<T>> supplier() {
return ImmutableSet::builder;
}
@Override
public BiConsumer<ImmutableSet.Builder<T>, T> accumulator() {
return ImmutableSet.Builder::add;
}
@Override
public BinaryOperator<ImmutableSet.Builder<T>> combiner() {
return (left, right) -> left.addAll(right.build());
}
@Override
public Function<ImmutableSet.Builder<T>, ImmutableSet<T>> finisher() {
return ImmutableSet.Builder::build;
}
@Override
public Set<Characteristics> characteristics() {
return Sets.immutableEnumSet(Characteristics.UNORDERED);
}
}
}
+1 -1
View File
@@ -45,7 +45,7 @@
<properties>
<maven.compiler.source.version>11</maven.compiler.source.version>
<maven.compiler.target.version>11</maven.compiler.target.version>
<jackson.version>2.14.1</jackson.version>
<jackson.version>2.16.0</jackson.version>
<gson.version>2.10</gson.version>
</properties>
+3 -29
View File
@@ -8,9 +8,9 @@
<packaging>jar</packaging>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-modules</artifactId>
<version>1.0.0-SNAPSHOT</version>
<groupId>com.baeldung.core-java-modules</groupId>
<artifactId>core-java-modules</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<dependencies>
@@ -21,30 +21,4 @@
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
<configuration>
<source>${maven.compiler.source.version}</source>
<target>${maven.compiler.target.version}</target>
<compilerArgs>--enable-preview</compilerArgs>
</configuration>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>--enable-preview</argLine>
</configuration>
</plugin>
</plugins>
</build>
<properties>
<maven.compiler.source.version>12</maven.compiler.source.version>
<maven.compiler.target.version>12</maven.compiler.target.version>
</properties>
</project>
@@ -19,19 +19,6 @@ public class SwitchUnitTest {
Assert.assertEquals(value, 2);
}
@Test
public void switchLocalVariable(){
var month = Month.AUG;
int i = switch (month){
case JAN,JUN, JUL -> 3;
case FEB,SEP, OCT, NOV, DEC -> 1;
case MAR,MAY, APR, AUG -> {
int j = month.toString().length() * 4;
break j;
}
};
Assert.assertEquals(12, i);
}
enum Month {JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC}
}
+3 -33
View File
@@ -8,39 +8,9 @@
<packaging>jar</packaging>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-modules</artifactId>
<version>1.0.0-SNAPSHOT</version>
<groupId>com.baeldung.core-java-modules</groupId>
<artifactId>core-java-modules</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
<configuration>
<source>${maven.compiler.source.version}</source>
<target>${maven.compiler.target.version}</target>
<release>13</release>
<compilerArgs>--enable-preview</compilerArgs>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${surefire.plugin.version}</version>
<configuration>
<argLine>--enable-preview</argLine>
</configuration>
</plugin>
</plugins>
</build>
<properties>
<maven.compiler.source.version>13</maven.compiler.source.version>
<maven.compiler.target.version>13</maven.compiler.target.version>
<surefire.plugin.version>3.0.0-M3</surefire.plugin.version>
</properties>
</project>
@@ -7,7 +7,6 @@ import org.junit.Test;
public class SwitchExpressionsWithYieldUnitTest {
@Test
@SuppressWarnings("preview")
public void whenSwitchingOnOperationSquareMe_thenWillReturnSquare() {
var me = 4;
var operation = "squareMe";
@@ -8,7 +8,6 @@ public class TextBlocksUnitTest {
private static final String JSON_STRING = "{\r\n" + "\"name\" : \"Baeldung\",\r\n" + "\"website\" : \"https://www.%s.com/\"\r\n" + "}";
@SuppressWarnings("preview")
private static final String TEXT_BLOCK_JSON = """
{
"name" : "Baeldung",
@@ -25,7 +24,6 @@ public class TextBlocksUnitTest {
}
@SuppressWarnings("removal")
@Test
public void whenTextBlocks_thenFormattedWorksAsFormat() {
assertThat(TEXT_BLOCK_JSON.formatted("baeldung")
@@ -13,7 +13,6 @@ import org.junit.Test;
public class SwitchExpressionsUnitTest {
@Test
@SuppressWarnings ("preview")
public void whenSwitchingOverMonthJune_thenWillReturn3() {
var month = JUNE;
@@ -29,7 +28,6 @@ public class SwitchExpressionsUnitTest {
}
@Test
@SuppressWarnings ("preview")
public void whenSwitchingOverMonthAugust_thenWillReturn24() {
var month = AUGUST;
@@ -47,7 +45,6 @@ public class SwitchExpressionsUnitTest {
}
@Test
@SuppressWarnings ("preview")
public void whenSwitchingOverMonthJanuary_thenWillReturn3() {
Function<Month, Integer> func = (month) -> {
@@ -61,7 +58,6 @@ public class SwitchExpressionsUnitTest {
}
@Test
@SuppressWarnings ("preview")
public void whenSwitchingOverMonthAugust_thenWillReturn2() {
var month = AUGUST;
+3 -33
View File
@@ -8,10 +8,9 @@
<packaging>jar</packaging>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-modules</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
<groupId>com.baeldung.core-java-modules</groupId>
<artifactId>core-java-modules</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<dependencies>
@@ -27,33 +26,4 @@
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
<configuration>
<release>${maven.compiler.release}</release>
<compilerArgs>--enable-preview</compilerArgs>
<source>14</source>
<target>14</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${surefire.plugin.version}</version>
<configuration>
<argLine>--enable-preview</argLine>
</configuration>
</plugin>
</plugins>
</build>
<properties>
<maven.compiler.release>15</maven.compiler.release>
<surefire.plugin.version>3.0.0-M3</surefire.plugin.version>
</properties>
</project>
-1
View File
@@ -4,5 +4,4 @@
- [Guide to mapMulti in Stream API](https://www.baeldung.com/java-mapmulti)
- [Collecting Stream Elements into a List in Java](https://www.baeldung.com/java-stream-to-list-collecting)
- [New Features in Java 16](https://www.baeldung.com/java-16-new-features)
- [Guide to Java 8 groupingBy Collector](https://www.baeldung.com/java-groupingby-collector)
- [Value-Based Classes in Java](https://www.baeldung.com/java-value-based-classes)
+2
View File
@@ -8,3 +8,5 @@
- [Sealed Classes and Interfaces in Java](https://www.baeldung.com/java-sealed-classes-interfaces)
- [Migrate From Java 8 to Java 17](https://www.baeldung.com/java-migrate-8-to-17)
- [Format Multiple or Conditions in an If Statement in Java](https://www.baeldung.com/java-multiple-or-conditions-if-statement)
- [Get All Record Fields and Its Values via Reflection](https://www.baeldung.com/java-reflection-record-fields-values)
- [Context-Specific Deserialization Filters in Java 17](https://www.baeldung.com/java-context-specific-deserialization-filters)
@@ -0,0 +1,47 @@
package com.baeldung.deserializationfilters;
import java.io.ObjectInputFilter;
import java.util.function.BinaryOperator;
import com.baeldung.deserializationfilters.service.DeserializationService;
import com.baeldung.deserializationfilters.service.LimitedArrayService;
import com.baeldung.deserializationfilters.service.LowDepthService;
import com.baeldung.deserializationfilters.service.SmallObjectService;
import com.baeldung.deserializationfilters.utils.FilterUtils;
public class ContextSpecificDeserializationFilterFactory implements BinaryOperator<ObjectInputFilter> {
@Override
public ObjectInputFilter apply(ObjectInputFilter current, ObjectInputFilter next) {
if (current == null) {
Class<?> caller = findInStack(DeserializationService.class);
if (caller == null) {
current = FilterUtils.fallbackFilter();
} else if (caller.equals(SmallObjectService.class)) {
current = FilterUtils.safeSizeFilter(190);
} else if (caller.equals(LowDepthService.class)) {
current = FilterUtils.safeDepthFilter(2);
} else if (caller.equals(LimitedArrayService.class)) {
current = FilterUtils.safeArrayFilter(3);
}
}
return ObjectInputFilter.merge(current, next);
}
private static Class<?> findInStack(Class<?> superType) {
for (StackTraceElement element : Thread.currentThread()
.getStackTrace()) {
try {
Class<?> subType = Class.forName(element.getClassName());
if (superType.isAssignableFrom(subType)) {
return subType;
}
} catch (ClassNotFoundException e) {
return null;
}
}
return null;
}
}
@@ -0,0 +1,7 @@
package com.baeldung.deserializationfilters.pojo;
import java.io.Serializable;
public interface ContextSpecific extends Serializable {
}
@@ -0,0 +1,19 @@
package com.baeldung.deserializationfilters.pojo;
public class NestedSample implements ContextSpecific {
private static final long serialVersionUID = 1L;
private Sample optional;
public NestedSample(Sample optional) {
this.optional = optional;
}
public Sample getOptional() {
return optional;
}
public void setOptional(Sample optional) {
this.optional = optional;
}
}
@@ -0,0 +1,61 @@
package com.baeldung.deserializationfilters.pojo;
public class Sample implements ContextSpecific, Comparable<Sample> {
private static final long serialVersionUID = 1L;
private int[] array;
private String name;
private NestedSample nested;
public Sample(String name) {
this.name = name;
}
public Sample(int[] array) {
this.array = array;
}
public Sample(NestedSample nested) {
this.nested = nested;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int[] getArray() {
return array;
}
public void setArray(int[] array) {
this.array = array;
}
public NestedSample getNested() {
return nested;
}
public void setNested(NestedSample nested) {
this.nested = nested;
}
@Override
public String toString() {
return name;
}
@Override
public int compareTo(Sample o) {
if (name == null)
return -1;
if (o == null || o.getName() == null)
return 1;
return getName().compareTo(o.getName());
}
}
@@ -0,0 +1,25 @@
package com.baeldung.deserializationfilters.pojo;
public class SampleExploit extends Sample {
private static final long serialVersionUID = 1L;
public SampleExploit() {
super("exploit");
}
public static void maliciousCode() {
System.out.println("exploit executed");
}
@Override
public String toString() {
maliciousCode();
return "exploit";
}
@Override
public int compareTo(Sample o) {
maliciousCode();
return super.compareTo(o);
}
}
@@ -0,0 +1,11 @@
package com.baeldung.deserializationfilters.service;
import java.io.InputStream;
import java.util.Set;
import com.baeldung.deserializationfilters.pojo.ContextSpecific;
public interface DeserializationService {
Set<ContextSpecific> process(InputStream... inputStreams);
}
@@ -0,0 +1,15 @@
package com.baeldung.deserializationfilters.service;
import java.io.InputStream;
import java.util.Set;
import com.baeldung.deserializationfilters.pojo.ContextSpecific;
import com.baeldung.deserializationfilters.utils.DeserializationUtils;
public class LimitedArrayService implements DeserializationService {
@Override
public Set<ContextSpecific> process(InputStream... inputStreams) {
return DeserializationUtils.deserializeIntoSet(inputStreams);
}
}
@@ -0,0 +1,20 @@
package com.baeldung.deserializationfilters.service;
import java.io.InputStream;
import java.io.ObjectInputFilter;
import java.util.Set;
import com.baeldung.deserializationfilters.pojo.ContextSpecific;
import com.baeldung.deserializationfilters.utils.DeserializationUtils;
public class LowDepthService implements DeserializationService {
public Set<ContextSpecific> process(ObjectInputFilter filter, InputStream... inputStreams) {
return DeserializationUtils.deserializeIntoSet(filter, inputStreams);
}
@Override
public Set<ContextSpecific> process(InputStream... inputStreams) {
return process(null, inputStreams);
}
}
@@ -0,0 +1,15 @@
package com.baeldung.deserializationfilters.service;
import java.io.InputStream;
import java.util.Set;
import com.baeldung.deserializationfilters.pojo.ContextSpecific;
import com.baeldung.deserializationfilters.utils.DeserializationUtils;
public class SmallObjectService implements DeserializationService {
@Override
public Set<ContextSpecific> process(InputStream... inputStreams) {
return DeserializationUtils.deserializeIntoSet(inputStreams);
}
}
@@ -0,0 +1,50 @@
package com.baeldung.deserializationfilters.utils;
import java.io.InputStream;
import java.io.InvalidClassException;
import java.io.ObjectInputFilter;
import java.io.ObjectInputStream;
import java.util.Set;
import java.util.TreeSet;
import com.baeldung.deserializationfilters.pojo.ContextSpecific;
public class DeserializationUtils {
private DeserializationUtils() {
}
public static Object deserialize(InputStream inStream) {
return deserialize(inStream, null);
}
public static Object deserialize(InputStream inStream, ObjectInputFilter filter) {
try (ObjectInputStream in = new ObjectInputStream(inStream)) {
if (filter != null) {
in.setObjectInputFilter(filter);
}
return in.readObject();
} catch (InvalidClassException e) {
return null;
} catch (Throwable e) {
e.printStackTrace();
return null;
}
}
public static Set<ContextSpecific> deserializeIntoSet(InputStream... inputStreams) {
return deserializeIntoSet(null, inputStreams);
}
public static Set<ContextSpecific> deserializeIntoSet(ObjectInputFilter filter, InputStream... inputStreams) {
Set<ContextSpecific> set = new TreeSet<>();
for (InputStream inputStream : inputStreams) {
Object object = deserialize(inputStream, filter);
if (object != null) {
set.add((ContextSpecific) object);
}
}
return set;
}
}
@@ -0,0 +1,32 @@
package com.baeldung.deserializationfilters.utils;
import java.io.ObjectInputFilter;
public class FilterUtils {
private static final String DEFAULT_PACKAGE_PATTERN = "java.base/*;!*";
private static final String POJO_PACKAGE = "com.baeldung.deserializationfilters.pojo";
private FilterUtils() {
}
private static ObjectInputFilter baseFilter(String parameter, int max) {
return ObjectInputFilter.Config.createFilter(String.format("%s=%d;%s.**;%s", parameter, max, POJO_PACKAGE, DEFAULT_PACKAGE_PATTERN));
}
public static ObjectInputFilter fallbackFilter() {
return ObjectInputFilter.Config.createFilter(String.format("%s", DEFAULT_PACKAGE_PATTERN));
}
public static ObjectInputFilter safeSizeFilter(int max) {
return baseFilter("maxbytes", max);
}
public static ObjectInputFilter safeArrayFilter(int max) {
return baseFilter("maxarray", max);
}
public static ObjectInputFilter safeDepthFilter(int max) {
return baseFilter("maxdepth", max);
}
}
@@ -0,0 +1,17 @@
package com.baeldung.deserializationfilters.utils;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
public class SerializationUtils {
private SerializationUtils() {
}
public static void serialize(Object object, OutputStream outStream) throws IOException {
try (ObjectOutputStream objStream = new ObjectOutputStream(outStream)) {
objStream.writeObject(object);
}
}
}
@@ -0,0 +1,119 @@
package com.baeldung.deserializationfilters;
import static org.junit.Assert.assertNull;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputFilter;
import java.util.Set;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import com.baeldung.deserializationfilters.pojo.ContextSpecific;
import com.baeldung.deserializationfilters.pojo.NestedSample;
import com.baeldung.deserializationfilters.pojo.Sample;
import com.baeldung.deserializationfilters.pojo.SampleExploit;
import com.baeldung.deserializationfilters.service.LimitedArrayService;
import com.baeldung.deserializationfilters.service.LowDepthService;
import com.baeldung.deserializationfilters.service.SmallObjectService;
import com.baeldung.deserializationfilters.utils.DeserializationUtils;
import com.baeldung.deserializationfilters.utils.FilterUtils;
import com.baeldung.deserializationfilters.utils.SerializationUtils;
public class ContextSpecificDeserializationFilterIntegrationTest {
private static ByteArrayOutputStream serialSampleA = new ByteArrayOutputStream();
private static ByteArrayOutputStream serialBigSampleA = new ByteArrayOutputStream();
private static ByteArrayOutputStream serialSampleB = new ByteArrayOutputStream();
private static ByteArrayOutputStream serialBigSampleB = new ByteArrayOutputStream();
private static ByteArrayOutputStream serialSampleC = new ByteArrayOutputStream();
private static ByteArrayOutputStream serialBigSampleC = new ByteArrayOutputStream();
private static ByteArrayInputStream bytes(ByteArrayOutputStream stream) {
return new ByteArrayInputStream(stream.toByteArray());
}
@BeforeAll
static void setup() throws IOException {
ObjectInputFilter.Config.setSerialFilterFactory(new ContextSpecificDeserializationFilterFactory());
SerializationUtils.serialize(new Sample("simple"), serialSampleA);
SerializationUtils.serialize(new SampleExploit(), serialBigSampleA);
SerializationUtils.serialize(new Sample(new int[] { 1, 2, 3 }), serialSampleB);
SerializationUtils.serialize(new Sample(new int[] { 1, 2, 3, 4, 5, 6 }), serialBigSampleB);
SerializationUtils.serialize(new Sample(new NestedSample(null)), serialSampleC);
SerializationUtils.serialize(new Sample(new NestedSample(new Sample("deep"))), serialBigSampleC);
}
@Test
void whenSmallObjectContext_thenCorrectFilterApplied() {
Set<ContextSpecific> result = new SmallObjectService().process( //
bytes(serialSampleA), //
bytes(serialBigSampleA));
assertEquals(1, result.size());
assertEquals("simple", ((Sample) result.iterator()
.next()).getName());
}
@Test
void whenLimitedArrayContext_thenCorrectFilterApplied() {
Set<ContextSpecific> result = new LimitedArrayService().process( //
bytes(serialSampleB), //
bytes(serialBigSampleB));
assertEquals(1, result.size());
}
@Test
void whenLowDepthContext_thenCorrectFilterApplied() {
Set<ContextSpecific> result = new LowDepthService().process( //
bytes(serialSampleC), //
bytes(serialBigSampleC));
assertEquals(1, result.size());
}
@Test
void givenExtraFilter_whenCombinedContext_thenMergedFiltersApplied() {
Set<ContextSpecific> result = new LowDepthService().process( //
FilterUtils.safeSizeFilter(190), //
bytes(serialSampleA), //
bytes(serialBigSampleA), //
bytes(serialSampleC), //
bytes(serialBigSampleC));
assertEquals(1, result.size());
assertEquals("simple", ((Sample) result.iterator()
.next()).getName());
}
@Test
void givenFallbackContext_whenUsingBaseClasses_thenRestrictiveFilterApplied() throws IOException {
String a = new String("a");
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
SerializationUtils.serialize(a, outStream);
String deserializedA = (String) DeserializationUtils.deserialize(bytes(outStream));
assertEquals(a, deserializedA);
}
@Test
void givenFallbackContext_whenUsingAppClasses_thenRejected() throws IOException {
Sample a = new Sample("a");
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
SerializationUtils.serialize(a, outStream);
Sample deserializedA = (Sample) DeserializationUtils.deserialize(bytes(outStream));
assertNull(deserializedA);
}
}
@@ -0,0 +1,89 @@
package com.baeldung.recordproperties;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.lang.reflect.Field;
import java.lang.reflect.RecordComponent;
import java.util.ArrayList;
import org.junit.jupiter.api.Test;
record Player(String name, int age, Long score) {
}
public class ReadRecordPropertiesByReflectionUnitTest {
private static final Player ERIC = new Player("Eric", 28, 4242L);
@Test
void whenUsingRecordComponent_thenGetExpectedResult() {
var fields = new ArrayList<Field>();
RecordComponent[] components = Player.class.getRecordComponents();
for (var comp : components) {
try {
Field field = ERIC.getClass()
.getDeclaredField(comp.getName());
field.setAccessible(true);
fields.add(field);
} catch (NoSuchFieldException e) {
// for simplicity, error handling is skipped
}
}
assertEquals(3, fields.size());
var nameField = fields.get(0);
var ageField = fields.get(1);
var scoreField = fields.get(2);
try {
assertEquals("name", nameField.getName());
assertEquals(String.class, nameField.getType());
assertEquals("Eric", nameField.get(ERIC));
assertEquals("age", ageField.getName());
assertEquals(int.class, ageField.getType());
assertEquals(28, ageField.get(ERIC));
assertEquals("score", scoreField.getName());
assertEquals(Long.class, scoreField.getType());
assertEquals(4242L, scoreField.get(ERIC));
} catch (IllegalAccessException exception) {
// for simplicity, error handling is skipped
}
}
@Test
void whenUsingClassGetDeclaredField_thenGetExpectedResult() {
// record has no public fields
assertEquals(0, Player.class.getFields().length);
var fields = new ArrayList<Field>();
for (var field : Player.class.getDeclaredFields()) {
field.setAccessible(true);
fields.add(field);
}
assertEquals(3, fields.size());
var nameField = fields.get(0);
var ageField = fields.get(1);
var scoreField = fields.get(2);
try {
assertEquals("name", nameField.getName());
assertEquals(String.class, nameField.getType());
assertEquals("Eric", nameField.get(ERIC));
assertEquals("age", ageField.getName());
assertEquals(int.class, ageField.getType());
assertEquals(28, ageField.get(ERIC));
assertEquals("score", scoreField.getName());
assertEquals(Long.class, scoreField.getType());
assertEquals(4242L, scoreField.get(ERIC));
} catch (IllegalAccessException ex) {
// for simplicity, error handling is skipped
}
}
}
@@ -18,19 +18,19 @@ public class VehicleUnitTest {
}
@Test
public void givenCar_whenUsingReflectionAPI_thenSuperClassIsSealed() {
public void givenCar_whenUsingReflectionAPI_thenSuperClassIsSealed() throws ClassNotFoundException {
Assertions.assertThat(car.getClass().isSealed()).isEqualTo(false);
Assertions.assertThat(car.getClass().getSuperclass().isSealed()).isEqualTo(true);
Assertions.assertThat(car.getClass().getSuperclass().getPermittedSubclasses())
.contains(ClassDesc.of(car.getClass().getCanonicalName()));
.contains(Class.forName(car.getClass().getCanonicalName()));
}
@Test
public void givenTruck_whenUsingReflectionAPI_thenSuperClassIsSealed() {
public void givenTruck_whenUsingReflectionAPI_thenSuperClassIsSealed() throws ClassNotFoundException {
Assertions.assertThat(truck.getClass().isSealed()).isEqualTo(false);
Assertions.assertThat(truck.getClass().getSuperclass().isSealed()).isEqualTo(true);
Assertions.assertThat(truck.getClass().getSuperclass().getPermittedSubclasses())
.contains(ClassDesc.of(truck.getClass().getCanonicalName()));
.contains(Class.forName(truck.getClass().getCanonicalName()));
}
@Test
@@ -18,19 +18,19 @@ public class VehicleUnitTest {
}
@Test
public void givenCar_whenUsingReflectionAPI_thenInterfaceIsSealed() {
public void givenCar_whenUsingReflectionAPI_thenInterfaceIsSealed() throws ClassNotFoundException {
Assertions.assertThat(car.getClass().isSealed()).isEqualTo(false);
Assertions.assertThat(car.getClass().getInterfaces()[0].isSealed()).isEqualTo(true);
Assertions.assertThat(car.getClass().getInterfaces()[0].permittedSubclasses())
.contains(ClassDesc.of(car.getClass().getCanonicalName()));
Assertions.assertThat(car.getClass().getInterfaces()[0].getPermittedSubclasses())
.contains(Class.forName(car.getClass().getCanonicalName()));
}
@Test
public void givenTruck_whenUsingReflectionAPI_thenInterfaceIsSealed() {
public void givenTruck_whenUsingReflectionAPI_thenInterfaceIsSealed() throws ClassNotFoundException {
Assertions.assertThat(truck.getClass().isSealed()).isEqualTo(false);
Assertions.assertThat(truck.getClass().getInterfaces()[0].isSealed()).isEqualTo(true);
Assertions.assertThat(truck.getClass().getInterfaces()[0].permittedSubclasses())
.contains(ClassDesc.of(truck.getClass().getCanonicalName()));
Assertions.assertThat(truck.getClass().getInterfaces()[0].getPermittedSubclasses())
.contains(Class.forName(truck.getClass().getCanonicalName()));
}
@Test
+2
View File
@@ -0,0 +1,2 @@
## Relevant Articles
- [Deprecate Finalization in Java 18](https://www.baeldung.com/java-18-deprecate-finalization)
+27 -27
View File
@@ -3,19 +3,34 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>core-java-20</artifactId>
<parent>
<groupId>com.baeldung.core-java-modules</groupId>
<artifactId>core-java-modules</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>core-java-20</artifactId>
<properties>
<maven.compiler.source>20</maven.compiler.source>
<maven.compiler.target>20</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>6.0.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>3.24.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>5.2.0</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
@@ -41,25 +56,10 @@
</plugins>
</build>
<dependencies>
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>6.0.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>3.24.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>5.2.0</version>
<scope>test</scope>
</dependency>
</dependencies>
<properties>
<maven.compiler.source>20</maven.compiler.source>
<maven.compiler.target>20</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>
@@ -0,0 +1,5 @@
package com.baeldung.deserialization;
public record Contact(String email, String phone) {
// Constructor, getters, and other methods are automatically generated
}
@@ -0,0 +1,5 @@
package com.baeldung.deserialization;
public record Person(String name, int age, String address, Contact contact) {
// Constructor, getters, and other methods are automatically generated
}
@@ -0,0 +1,39 @@
package com.baeldung.deserialization;
import com.google.gson.Gson;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
public class DeserializationUnitTest {
@Test
public void givenJsonString_whenDeserialized_thenPersonRecordCreated() {
String json = "{\"name\":\"John Doe\",\"age\":30,\"address\":\"123 Main St\"}";
Person person = new Gson().fromJson(json, Person.class);
assertEquals("John Doe", person.name());
assertEquals(30, person.age());
assertEquals("123 Main St", person.address());
}
@Test
public void givenNestedJsonString_whenDeserialized_thenPersonRecordCreated() {
String json = "{\"name\":\"John Doe\",\"age\":30,\"address\":\"123 Main St\",\"contact\":{\"email\":\"john.doe@example.com\",\"phone\":\"555-1234\"}}";
Person person = new Gson().fromJson(json, Person.class);
assertNotNull(person);
assertEquals("John Doe", person.name());
assertEquals(30, person.age());
assertEquals("123 Main St", person.address());
Contact contact = person.contact();
assertNotNull(contact);
assertEquals("john.doe@example.com", contact.email());
assertEquals("555-1234", contact.phone());
}
}
+8 -8
View File
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>core-java-21</artifactId>
<name>core-java-21</name>
@@ -12,12 +12,6 @@
<version>0.0.1-SNAPSHOT</version>
</parent>
<properties>
<maven.compiler.source.version>21</maven.compiler.source.version>
<maven.compiler.target.version>21</maven.compiler.target.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<plugins>
<plugin>
@@ -44,4 +38,10 @@
</plugins>
</build>
<properties>
<maven.compiler.source.version>21</maven.compiler.source.version>
<maven.compiler.target.version>21</maven.compiler.target.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>
@@ -6,4 +6,7 @@
- [How Many Days Are There in a Particular Month of a Given Year?](https://www.baeldung.com/days-particular-month-given-year)
- [Difference Between Instant and LocalDateTime](https://www.baeldung.com/java-instant-vs-localdatetime)
- [Add Minutes to a Time String in Java](https://www.baeldung.com/java-string-time-add-mins)
- [Round the Date in Java](https://www.baeldung.com/java-round-the-date)
- [Representing Furthest Possible Date in Java](https://www.baeldung.com/java-date-represent-max)
- [Retrieving Unix Time in Java](https://www.baeldung.com/java-retrieve-unix-time)
- [[<-- Prev]](/core-java-modules/core-java-datetime-java8-1)
@@ -55,7 +55,7 @@
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<joda-time.version>2.10</joda-time.version>
<joda-time.version>2.12.5</joda-time.version>
</properties>
</project>
@@ -0,0 +1,18 @@
package com.baeldung.maxdate;
import java.util.Date;
public class DateComparison {
public int compareTodayWithMaxDate() {
Date today = new Date();
Date maxDate = new Date(Long.MAX_VALUE);
int comparisonResult = today.compareTo(maxDate);
return comparisonResult;
}
public static void main(String[] args) {
DateComparison comparator = new DateComparison();
System.out.println(comparator.compareTodayWithMaxDate());
}
}
@@ -0,0 +1,18 @@
package com.baeldung.maxdate;
import java.util.Date;
import java.text.SimpleDateFormat;
public class MaxDateDisplay {
public String getMaxDateValue() {
Date maxDate = new Date(Long.MAX_VALUE);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
return "The maximum date value in Java is: " + sdf.format(maxDate);
}
public static void main(String[] args) {
MaxDateDisplay display = new MaxDateDisplay();
System.out.println(display.getMaxDateValue());
}
}
@@ -7,7 +7,7 @@ import java.util.List;
public class SimpleParseDate {
public Date parseDate(String dateString, List<String> formatStrings) {
public static Date parseDate(String dateString, List<String> formatStrings) {
for (String formatString : formatStrings) {
try {
return new SimpleDateFormat(formatString).parse(dateString);
@@ -0,0 +1,113 @@
package com.baeldung.rounddate;
import java.time.DayOfWeek;
import java.time.temporal.ChronoField;
import java.time.temporal.TemporalAdjusters;
import java.util.Calendar;
import java.util.Date;
import java.time.LocalDateTime;
import java.time.ZonedDateTime;
public class RoundDate {
public static Date getDate(int year, int month, int day, int hour, int minute) {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.YEAR, year);
calendar.set(Calendar.MONTH, month);
calendar.set(Calendar.DAY_OF_MONTH, day);
calendar.set(Calendar.HOUR_OF_DAY, hour);
calendar.set(Calendar.MINUTE, minute);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
return calendar.getTime();
}
public static Date roundToDay(Date date) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
return calendar.getTime();
}
public static Date roundToNearestUnit(Date date, int unit) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
switch (unit) {
case Calendar.HOUR:
int minute = calendar.get(Calendar.MINUTE);
if (minute >= 0 && minute < 15) {
calendar.set(Calendar.MINUTE, 0);
} else if (minute >= 15 && minute < 45) {
calendar.set(Calendar.MINUTE, 30);
} else {
calendar.set(Calendar.MINUTE, 0);
calendar.add(Calendar.HOUR_OF_DAY, 1);
}
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
break;
case Calendar.DAY_OF_MONTH:
int hour = calendar.get(Calendar.HOUR_OF_DAY);
if (hour >= 12) {
calendar.add(Calendar.DAY_OF_MONTH, 1);
}
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
break;
case Calendar.MONTH:
int day = calendar.get(Calendar.DAY_OF_MONTH);
if (day >= 15) {
calendar.add(Calendar.MONTH, 1);
}
calendar.set(Calendar.DAY_OF_MONTH, 1);
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
break;
}
return calendar.getTime();
}
public static LocalDateTime roundToStartOfMonthUsingLocalDateTime(LocalDateTime dateTime) {
return dateTime.withDayOfMonth(1).withHour(0).withMinute(0).withSecond(0).withNano(0);
}
public static LocalDateTime roundToEndOfWeekUsingLocalDateTime(LocalDateTime dateTime) {
return dateTime.with(TemporalAdjusters.next(DayOfWeek.SATURDAY))
.withHour(23)
.withMinute(59)
.withSecond(59)
.withNano(999);
}
public static ZonedDateTime roundToStartOfMonthUsingZonedDateTime(ZonedDateTime dateTime) {
return dateTime.withDayOfMonth(1)
.withHour(0)
.withMinute(0)
.withSecond(0)
.with(ChronoField.MILLI_OF_SECOND, 0)
.with(ChronoField.MICRO_OF_SECOND, 0)
.with(ChronoField.NANO_OF_SECOND, 0);
}
public static ZonedDateTime roundToEndOfWeekUsingZonedDateTime(ZonedDateTime dateTime) {
return dateTime.with(TemporalAdjusters.next(DayOfWeek.SATURDAY))
.withHour(23)
.withMinute(59)
.withSecond(59)
.with(ChronoField.MILLI_OF_SECOND, 999)
.with(ChronoField.MICRO_OF_SECOND, 999)
.with(ChronoField.NANO_OF_SECOND, 999);
}
}
@@ -0,0 +1,16 @@
package com.baeldung.maxdate;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.junit.jupiter.api.Test;
class DateComparisonUnitTest {
@Test
void whenCompareTodayWithMaxDate_thenCorrectResult() {
DateComparison comparator = new DateComparison();
int result = comparator.compareTodayWithMaxDate();
assertTrue(result < 0);
}
}
@@ -0,0 +1,18 @@
package com.baeldung.maxdate;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;
class MaxDateDisplayUnitTest {
@Test
void whenGetMaxDate_thenCorrectResult() {
MaxDateDisplay display = new MaxDateDisplay();
String result = display.getMaxDateValue();
assertEquals(
"The maximum date value in Java is: 292278994-08-17 07:12:55.807",
result
);
}
}
@@ -1,43 +1,41 @@
package com.baeldung.parsingDates;
import com.baeldung.parsingDates.SimpleDateTimeFormat;
import com.baeldung.parsingDates.SimpleDateTimeFormater;
import com.baeldung.parsingDates.SimpleDateUtils;
import com.baeldung.parsingDates.SimpleParseDate;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import java.time.format.DateTimeParseException;
import java.util.Arrays;
import org.junit.*;
import static org.junit.Assert.*;
import org.joda.time.LocalDate;
import org.junit.jupiter.api.Test;
public class SimpleParseDateUnitTest {
class SimpleParseDateUnitTest {
@Test
public void whenInvalidInput_thenGettingUnexpectedResult() {
SimpleParseDate simpleParseDate = new SimpleParseDate();
void whenInvalidInput_thenGettingUnexpectedResult() {
String date = "2022-40-40";
assertEquals("Sat May 10 00:00:00 UTC 2025", simpleParseDate.parseDate(date, Arrays.asList("MM/dd/yyyy", "dd.MM.yyyy", "yyyy-MM-dd")).toString());
assertEquals("Sat May 10 00:00:00 UTC 2025", SimpleParseDate.parseDate(date, Arrays.asList("MM/dd/yyyy", "dd.MM.yyyy", "yyyy-MM-dd"))
.toString());
}
@Test
public void whenInvalidDate_thenAssertThrows() {
SimpleDateTimeFormater simpleDateTimeFormater = new SimpleDateTimeFormater();
assertEquals(java.time.LocalDate.parse("2022-12-04"), simpleDateTimeFormater.parseDate("2022-12-04"));
assertThrows(DateTimeParseException.class, () -> simpleDateTimeFormater.parseDate("2022-13-04"));
void whenInvalidDate_thenAssertThrows() {
assertEquals(java.time.LocalDate.parse("2022-12-04"), SimpleDateTimeFormater.parseDate("2022-12-04"));
assertThrows(DateTimeParseException.class, () -> SimpleDateTimeFormater.parseDate("2022-13-04"));
}
@Test
public void whenDateIsCorrect_thenParseCorrect() {
SimpleDateUtils simpleDateUtils = new SimpleDateUtils();
assertNull(simpleDateUtils.parseDate("53/10/2014"));
assertEquals("Wed Sep 10 00:00:00 UTC 2014", simpleDateUtils.parseDate("10/09/2014").toString());
void whenDateIsCorrect_thenParseCorrect() {
assertNull(SimpleDateUtils.parseDate("53/10/2014"));
assertEquals("Wed Sep 10 00:00:00 UTC 2014", SimpleDateUtils.parseDate("10/09/2014")
.toString());
}
@Test
public void whenDateIsCorrect_thenResultCorrect() {
SimpleDateTimeFormat simpleDateTimeFormat = new SimpleDateTimeFormat();
assertNull(simpleDateTimeFormat.parseDate("53/10/2014"));
assertEquals(LocalDate.parse("2014-10-10"), simpleDateTimeFormat.parseDate("2014-10-10"));
void whenDateIsCorrect_thenResultCorrect() {
assertNull(SimpleDateTimeFormat.parseDate("53/10/2014"));
assertEquals(LocalDate.parse("2014-10-10"), SimpleDateTimeFormat.parseDate("2014-10-10"));
}
}
@@ -0,0 +1,63 @@
package com.baeldung.rounddate;
import org.junit.Test;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Calendar;
import java.util.Date;
import static org.junit.Assert.assertEquals;
public class DateRoundingUnitTest {
@Test
public void givenDate_whenRoundToDay_thenBeginningOfDay() {
Date date = RoundDate.getDate(2023, Calendar.JANUARY, 27, 14, 30);
Date result = RoundDate.roundToDay(date);
assertEquals(RoundDate.getDate(2023, Calendar.JANUARY, 27, 0, 0), result);
}
@Test
public void givenDate_whenRoundToNearestUnit_thenNearestUnit() {
Date date = RoundDate.getDate(2023, Calendar.JANUARY, 27, 14, 12);
Date result = RoundDate.roundToNearestUnit(date, Calendar.DAY_OF_MONTH);
Date expected = RoundDate.getDate(2023, Calendar.JANUARY, 28, 0, 0);
assertEquals(expected, result);
}
@Test
public void givenLocalDateTime_whenRoundToStartOfMonth_thenStartOfMonth() {
LocalDateTime dateTime = LocalDateTime.of(2023, 1, 27, 14, 12);
LocalDateTime result = RoundDate.roundToStartOfMonthUsingLocalDateTime(dateTime);
LocalDateTime expected = LocalDateTime.of(2023, 1, 1, 0, 0, 0);
assertEquals(expected, result);
}
@Test
public void givenZonedDateTime_whenRoundToStartOfMonth_thenStartOfMonth() {
ZonedDateTime dateTime = ZonedDateTime.of(2023, 1, 27, 14, 12, 0, 0, ZoneId.systemDefault());
ZonedDateTime result = RoundDate.roundToStartOfMonthUsingZonedDateTime(dateTime);
ZonedDateTime expected = ZonedDateTime.of(2023, 1, 1, 0, 0, 0, 0, ZoneId.systemDefault());
assertEquals(expected, result);
}
@Test
public void givenLocalDateTime_whenRoundToEndOfWeek_thenEndOfWeek() {
LocalDateTime dateTime = LocalDateTime.of(2023, 1, 27, 14, 12);
LocalDateTime result = RoundDate.roundToEndOfWeekUsingLocalDateTime(dateTime);
LocalDateTime expected = LocalDateTime.of(2023, 1, 28, 23, 59, 59, 999);
assertEquals(expected, result);
}
@Test
public void givenZonedDateTime_whenRoundToEndOfWeek_thenEndOfWeek() {
ZonedDateTime dateTime = ZonedDateTime.of(2023, 1, 27, 14, 12, 0, 0, ZoneId.systemDefault());
ZonedDateTime result = RoundDate.roundToEndOfWeekUsingZonedDateTime(dateTime);
ZonedDateTime expected = ZonedDateTime.of(2023, 1, 28, 23, 59, 59, 999, ZoneId.systemDefault());
assertEquals(expected, result);
}
}
@@ -0,0 +1,42 @@
package com.baeldung.unixtime;
import static org.junit.Assert.assertEquals;
import java.time.Instant;
import java.time.LocalDate;
import java.time.Month;
import java.time.ZoneId;
import java.util.Date;
import org.joda.time.DateTime;
import org.junit.jupiter.api.Test;
public class UnixTimeUnitTest {
@Test
public void givenTimeUsingDateApi_whenConvertedToUnixTime_thenMatch() {
Date date = new Date(2023 - 1900, 1, 15, 0, 0, 0);
long expected = 1676419200;
long actual = date.getTime() / 1000L;
assertEquals(expected, actual);
}
@Test
public void givenTimeUsingJodaTime_whenConvertedToUnixTime_thenMatch() {
DateTime dateTime = new DateTime(2023, 2, 15, 00, 00, 00, 0);
long expected = 1676419200;
long actual = dateTime.getMillis() / 1000L;
assertEquals(expected, actual);
}
@Test
public void givenTimeUsingLocalDate_whenConvertedToUnixTime_thenMatch() {
LocalDate date = LocalDate.of(2023, Month.FEBRUARY, 15);
Instant instant = date.atStartOfDay().atZone(ZoneId.of("UTC")).toInstant();
long expected = 1676419200;
long actual = instant.getEpochSecond();
assertEquals(expected, actual);
}
}
@@ -56,7 +56,7 @@
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<joda-time.version>2.10</joda-time.version>
<joda-time.version>2.12.5</joda-time.version>
</properties>
</project>
+1 -1
View File
@@ -11,5 +11,5 @@ This module contains articles about Java 8 core features
- [Finding Min/Max in an Array with Java](https://www.baeldung.com/java-array-min-max)
- [Internationalization and Localization in Java 8](https://www.baeldung.com/java-8-localization)
- [Generalized Target-Type Inference in Java](https://www.baeldung.com/java-generalized-target-type-inference)
- [Monads in Java](https://www.baeldung.com/java-monads)
- [Monads in Java Optional](https://www.baeldung.com/java-monads)
- [[More -->]](/core-java-modules/core-java-8-2)
@@ -0,0 +1,48 @@
package com.baeldung.spliterator;
import java.util.List;
import java.util.Spliterator;
import java.util.function.Consumer;
public class CustomSpliterator implements Spliterator<Integer> {
private final List<Integer> elements;
private int currentIndex;
public CustomSpliterator(List<Integer> elements) {
this.elements = elements;
this.currentIndex = 0;
}
@Override
public boolean tryAdvance(Consumer<? super Integer> action) {
if (currentIndex < elements.size()) {
action.accept(elements.get(currentIndex));
currentIndex++;
return true;
}
return false;
}
@Override
public Spliterator<Integer> trySplit() {
int currentSize = elements.size() - currentIndex;
if (currentSize < 2) {
return null;
}
int splitIndex = currentIndex + currentSize / 2;
CustomSpliterator newSpliterator = new CustomSpliterator(elements.subList(currentIndex, splitIndex));
currentIndex = splitIndex;
return newSpliterator;
}
@Override
public long estimateSize() {
return elements.size() - currentIndex;
}
@Override
public int characteristics() {
return ORDERED | SIZED | SUBSIZED | NONNULL;
}
}
@@ -1,12 +0,0 @@
package com.baeldung.spliterator;
import java.util.stream.Stream;
public class Executor {
public static int countAutors(Stream<Author> stream) {
RelatedAuthorCounter wordCounter = stream.reduce(new RelatedAuthorCounter(0, true),
RelatedAuthorCounter::accumulate, RelatedAuthorCounter::combine);
return wordCounter.getCounter();
}
}
@@ -1,27 +0,0 @@
package com.baeldung.spliterator;
public class RelatedAuthorCounter {
private final int counter;
private final boolean isRelated;
public RelatedAuthorCounter(int counter, boolean isRelated) {
this.counter = counter;
this.isRelated = isRelated;
}
public RelatedAuthorCounter accumulate(Author author) {
if (author.getRelatedArticleId() == 0) {
return isRelated ? this : new RelatedAuthorCounter(counter, true);
} else {
return isRelated ? new RelatedAuthorCounter(counter + 1, false) : this;
}
}
public RelatedAuthorCounter combine(RelatedAuthorCounter RelatedAuthorCounter) {
return new RelatedAuthorCounter(counter + RelatedAuthorCounter.counter, RelatedAuthorCounter.isRelated);
}
public int getCounter() {
return counter;
}
}
@@ -1,49 +0,0 @@
package com.baeldung.spliterator;
import java.util.List;
import java.util.Spliterator;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
public class RelatedAuthorSpliterator implements Spliterator<Author> {
private final List<Author> list;
AtomicInteger current = new AtomicInteger();
public RelatedAuthorSpliterator(List<Author> list) {
this.list = list;
}
@Override
public boolean tryAdvance(Consumer<? super Author> action) {
action.accept(list.get(current.getAndIncrement()));
return current.get() < list.size();
}
@Override
public Spliterator<Author> trySplit() {
int currentSize = list.size() - current.get();
if (currentSize < 10) {
return null;
}
for (int splitPos = currentSize / 2 + current.intValue(); splitPos < list.size(); splitPos++) {
if (list.get(splitPos).getRelatedArticleId() == 0) {
Spliterator<Author> spliterator = new RelatedAuthorSpliterator(list.subList(current.get(), splitPos));
current.set(splitPos);
return spliterator;
}
}
return null;
}
@Override
public long estimateSize() {
return list.size() - current.get();
}
@Override
public int characteristics() {
return CONCURRENT;
}
}
@@ -1,62 +0,0 @@
package com.baeldung.streamreduce.application;
import com.baeldung.streamreduce.entities.User;
import com.baeldung.streamreduce.utilities.NumberUtils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Application {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
int result1 = numbers.stream().reduce(0, (a, b) -> a + b);
System.out.println(result1);
int result2 = numbers.stream().reduce(0, Integer::sum);
System.out.println(result2);
List<String> letters = Arrays.asList("a", "b", "c", "d", "e");
String result3 = letters.stream().reduce("", (a, b) -> a + b);
System.out.println(result3);
String result4 = letters.stream().reduce("", String::concat);
System.out.println(result4);
String result5 = letters.stream().reduce("", (a, b) -> a.toUpperCase() + b.toUpperCase());
System.out.println(result5);
List<User> users = Arrays.asList(new User("John", 30), new User("Julie", 35));
int result6 = users.stream().reduce(0, (partialAgeResult, user) -> partialAgeResult + user.getAge(), Integer::sum);
System.out.println(result6);
String result7 = letters.parallelStream().reduce("", String::concat);
System.out.println(result7);
int result8 = users.parallelStream().reduce(0, (partialAgeResult, user) -> partialAgeResult + user.getAge(), Integer::sum);
System.out.println(result8);
List<User> userList = new ArrayList<>();
for (int i = 0; i <= 1000000; i++) {
userList.add(new User("John" + i, i));
}
long t1 = System.currentTimeMillis();
int result9 = userList.stream().reduce(0, (partialAgeResult, user) -> partialAgeResult + user.getAge(), Integer::sum);
long t2 = System.currentTimeMillis();
System.out.println(result9);
System.out.println("Sequential stream time: " + (t2 - t1) + "ms");
long t3 = System.currentTimeMillis();
int result10 = userList.parallelStream().reduce(0, (partialAgeResult, user) -> partialAgeResult + user.getAge(), Integer::sum);
long t4 = System.currentTimeMillis();
System.out.println(result10);
System.out.println("Parallel stream time: " + (t4 - t3) + "ms");
int result11 = NumberUtils.divideListElements(numbers, 1);
System.out.println(result11);
int result12 = NumberUtils.divideListElementsWithExtractedTryCatchBlock(numbers, 0);
System.out.println(result12);
}
}
@@ -1,28 +0,0 @@
package com.baeldung.streamreduce.entities;
public class Review {
int points;
String review;
public Review(int points, String review) {
this.points = points;
this.review = review;
}
public int getPoints() {
return points;
}
public void setPoints(int points) {
this.points = points;
}
public String getReview() {
return review;
}
public void setReview(String review) {
this.review = review;
}
}
@@ -1,52 +0,0 @@
package com.baeldung.streamreduce.utilities;
import java.util.List;
import java.util.function.BiFunction;
import java.util.logging.Level;
import java.util.logging.Logger;
public abstract class NumberUtils {
private static final Logger LOGGER = Logger.getLogger(NumberUtils.class.getName());
public static int divideListElements(List<Integer> values, Integer divider) {
return values.stream()
.reduce(0, (a, b) -> {
try {
return a / divider + b / divider;
} catch (ArithmeticException e) {
LOGGER.log(Level.INFO, "Arithmetic Exception: Division by Zero");
}
return 0;
});
}
public static int divideListElementsWithExtractedTryCatchBlock(List<Integer> values, int divider) {
return values.stream().reduce(0, (a, b) -> divide(a, divider) + divide(b, divider));
}
public static int divideListElementsWithApplyFunctionMethod(List<Integer> values, int divider) {
BiFunction<Integer, Integer, Integer> division = (a, b) -> a / b;
return values.stream().reduce(0, (a, b) -> applyFunction(division, a, divider) + applyFunction(division, b, divider));
}
private static int divide(int value, int factor) {
int result = 0;
try {
result = value / factor;
} catch (ArithmeticException e) {
LOGGER.log(Level.INFO, "Arithmetic Exception: Division by Zero");
}
return result;
}
private static int applyFunction(BiFunction<Integer, Integer, Integer> function, int a, int b) {
try {
return function.apply(a, b);
}
catch(Exception e) {
LOGGER.log(Level.INFO, "Exception occurred!");
}
return 0;
}
}
@@ -6,10 +6,10 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Spliterator;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import org.junit.Before;
import org.junit.Test;
@@ -18,22 +18,50 @@ import lombok.extern.slf4j.Slf4j;
@Slf4j
public class ExecutorUnitTest {
Article article;
Stream<Author> stream;
Spliterator<Author> spliterator;
@Before
public void init() {
article = new Article(Arrays.asList(new Author("Ahmad", 0), new Author("Eugen", 0), new Author("Alice", 1), new Author("Alice", 1), new Author("Mike", 0), new Author("Alice", 1), new Author("Mike", 0), new Author("Alice", 1), new Author("Mike", 0),
new Author("Alice", 1), new Author("Mike", 0), new Author("Mike", 0), new Author("Alice", 1), new Author("Mike", 0), new Author("Alice", 1), new Author("Mike", 0), new Author("Alice", 1), new Author("Mike", 0), new Author("Alice", 1),
new Author("Mike", 0), new Author("Michał", 0), new Author("Loredana", 1)), 0);
spliterator = new RelatedAuthorSpliterator(article.getListOfAuthors());
}
@Test
public void givenAstreamOfAuthors_whenProcessedInParallelWithCustomSpliterator_coubtProducessRightOutput() {
Stream<Author> stream2 = StreamSupport.stream(spliterator, true);
assertThat(Executor.countAutors(stream2.parallel())).isEqualTo(9);
public void givenAStreamOfIntegers_whenProcessedSequentialCustomSpliterator_countProducesRightOutput() {
List<Integer> numbers = new ArrayList<>();
numbers.add(1);
numbers.add(2);
numbers.add(3);
numbers.add(4);
numbers.add(5);
CustomSpliterator customSpliterator = new CustomSpliterator(numbers);
AtomicInteger sum = new AtomicInteger();
customSpliterator.forEachRemaining(sum::addAndGet);
assertThat(sum.get()).isEqualTo(15);
}
@Test
public void givenAStreamOfIntegers_whenProcessedInParallelWithCustomSpliterator_countProducesRightOutput() {
List<Integer> numbers = new ArrayList<>();
numbers.add(1);
numbers.add(2);
numbers.add(3);
numbers.add(4);
numbers.add(5);
CustomSpliterator customSpliterator = new CustomSpliterator(numbers);
// Create a ForkJoinPool for parallel processing
ForkJoinPool forkJoinPool = ForkJoinPool.commonPool();
AtomicInteger sum = new AtomicInteger(0);
// Process elements in parallel using parallelStream
forkJoinPool.submit(() -> customSpliterator.forEachRemaining(sum::addAndGet)).join();
assertThat(sum.get()).isEqualTo(15);
}
@Test
@@ -43,9 +71,7 @@ public class ExecutorUnitTest {
.collect(Collectors.toList());
Spliterator<Article> spliterator = articles.spliterator();
while (spliterator.tryAdvance(article -> article.setName(article.getName()
.concat("- published by Baeldung"))))
;
while(spliterator.tryAdvance(article -> article.setName(article.getName().concat("- published by Baeldung"))));
articles.forEach(article -> assertThat(article.getName()).isEqualTo("Java- published by Baeldung"));
}
@@ -10,3 +10,5 @@ This module contains articles about arrays conversion in Java
- [Convert Java Array to Iterable](https://www.baeldung.com/java-array-convert-to-iterable)
- [Converting an int[] to HashSet in Java](https://www.baeldung.com/java-converting-int-array-to-hashset)
- [Convert an ArrayList of String to a String Array in Java](https://www.baeldung.com/java-convert-string-arraylist-array)
- [Convert Char Array to Int Array in Java](https://www.baeldung.com/java-convert-char-int-array)
- [How to Convert Byte Array to Char Array](https://www.baeldung.com/java-convert-byte-array-char)
@@ -0,0 +1,47 @@
package com.baeldung.array.conversions;
import org.junit.Test;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.StandardCharsets;
import static org.junit.Assert.assertArrayEquals;
public class ByteToCharArrayUnitTest {
public static byte[] byteArray = {65, 66, 67, 68};
public static char[] expected = {'A', 'B', 'C', 'D'};
@Test
public void givenByteArray_WhenUsingStandardCharsets_thenConvertToCharArray() {
char[] charArray = new String(byteArray, StandardCharsets.UTF_8).toCharArray();
assertArrayEquals(expected, charArray);
}
@Test
public void givenByteArray_WhenUsingSUsingStreams_thenConvertToCharArray() throws IOException {
ByteArrayInputStream inputStream = new ByteArrayInputStream(byteArray);
InputStreamReader reader = new InputStreamReader(inputStream);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
int data;
while ((data = reader.read()) != -1) {
char ch = (char) data;
outputStream.write(ch);
}
char[] charArray = outputStream.toString().toCharArray();
assertArrayEquals(expected, charArray);
}
@Test
public void givenByteArray_WhenUsingCharBuffer_thenConvertToCharArray() {
ByteBuffer byteBuffer = ByteBuffer.wrap(byteArray);
CharBuffer charBuffer = StandardCharsets.UTF_8.decode(byteBuffer);
char[] charArray = new char[charBuffer.remaining()];
charBuffer.get(charArray);
assertArrayEquals(expected, charArray);
}
}
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>core-java-arrays-operations-advanced-2</artifactId>
<name>core-java-arrays-operations-advanced-2</name>
@@ -58,4 +58,8 @@
</plugins>
</build>
<properties>
<maven.compiler.release>11</maven.compiler.release>
</properties>
</project>
@@ -0,0 +1,29 @@
package com.baeldung.arraycompare;
import static org.assertj.core.api.Assertions.assertThat;
import java.util.Arrays;
import org.junit.jupiter.api.Test;
class ArraysCompareUnitTest {
@Test
void givenSameContents_whenCompare_thenCorrect() {
String[] array1 = new String[] { "A", "B", "C" };
String[] array2 = new String[] { "A", "B", "C" };
assertThat(Arrays.compare(array1, array2)).isEqualTo(0);
}
@Test
void givenDifferentContents_whenCompare_thenDifferent() {
String[] array1 = new String[] { "A", "B", "C" };
String[] array2 = new String[] { "A", "C", "B", "D" };
assertThat(Arrays.compare(array1, array2)).isLessThan(0);
assertThat(Arrays.compare(array2, array1)).isGreaterThan(0);
assertThat(Arrays.compare(array1, null)).isGreaterThan(0);
}
}
@@ -0,0 +1,6 @@
## Core Java Arrays - Basic Operations
This module contains articles about Java array fundamentals. They assume no previous background knowledge on working with arrays.
### Relevant Articles:
- [Arrays mismatch() Method in Java](https://www.baeldung.com/java-arrays-mismatch)
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>core-java-arrays-operations-basic-2</artifactId>
<name>core-java-arrays-operations-basic-2</name>
<packaging>jar</packaging>
<parent>
<artifactId>core-java-modules</artifactId>
<groupId>com.baeldung.core-java-modules</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
</project>
@@ -0,0 +1,269 @@
package com.baeldung.array.mismatch;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import java.util.Arrays;
import java.util.Comparator;
import org.junit.jupiter.api.Test;
class ArrayMismatchUnitTest {
@Test
void givenTwoArraysWithACommonPrefix_whenMismatch_thenIndexOfFirstMismatch() {
int[] firstArray = {1, 2, 3, 4, 5};
int[] secondArray = {1, 2, 3, 5, 8};
assertEquals(3, Arrays.mismatch(firstArray, secondArray));
}
@Test
void givenTwoIdenticalArrays_whenMismatch_thenMinusOne() {
int[] firstArray = {1, 2, 3, 4, 5};
int[] secondArray = {1, 2, 3, 4, 5};
assertEquals(-1, Arrays.mismatch(firstArray, secondArray));
}
@Test
void givenFirstArrayIsAPrefixOfTheSecond_whenMismatch_thenFirstArrayLength() {
int[] firstArray = {1, 2, 3, 4, 5};
int[] secondArray = {1, 2, 3, 4, 5, 6, 7, 8, 9};
assertEquals(firstArray.length, Arrays.mismatch(firstArray, secondArray));
}
@Test
void givenNoCommonPrefix_whenMismatch_thenZero() {
int[] firstArray = {1, 2, 3, 4, 5};
int[] secondArray = {9, 8, 7};
assertEquals(0, Arrays.mismatch(firstArray, secondArray));
}
@Test
void givenAtLeastANullArray_whenMismatch_thenThrowsNullPointerException() {
int[] firstArray = null;
int[] secondArray = {1, 2, 3, 4, 5};
assertThrows(NullPointerException.class, () -> Arrays.mismatch(firstArray, secondArray));
assertThrows(NullPointerException.class, () -> Arrays.mismatch(secondArray, firstArray));
assertThrows(NullPointerException.class, () -> Arrays.mismatch(firstArray, firstArray));
}
@Test
void givenExactlyOneAnEmptyArray_whenMismatch_thenZero() {
int[] firstArray = {};
int[] secondArray = {1, 2, 3};
assertEquals(0, Arrays.mismatch(firstArray, secondArray));
assertEquals(0, Arrays.mismatch(secondArray, firstArray));
}
@Test
void givenTwoEmptyArrays_whenMismatch_thenMinusOne() {
assertEquals(-1, Arrays.mismatch(new int[] {}, new int[] {}));
}
@Test
void givenTwoSubArraysWithACommonPrefix_whenMismatch_thenIndexOfFirstMismatch() {
int[] firstArray = {1, 2, 3, 4, 5};
int[] secondArray = {0, 1, 2, 3, 5, 8};
assertEquals(3, Arrays.mismatch(firstArray, 0, 4, secondArray, 1, 6));
}
@Test
void givenTwoIdenticalSubArrays_whenMismatch_thenMinusOne() {
int[] firstArray = {0, 0, 1, 2};
int[] secondArray = {0, 1, 2, 3, 4};
assertEquals(-1, Arrays.mismatch(firstArray, 2, 4, secondArray, 1, 3));
}
@Test
void givenFirstSubArrayIsAPrefixOfTheSecond_whenMismatch_thenFirstArrayLength() {
int[] firstArray = {2, 3, 4, 5, 4, 3, 2};
int[] secondArray = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
assertEquals(4, Arrays.mismatch(firstArray, 0, 4, secondArray, 2, 9));
}
@Test
void givenNoCommonPrefixForSubArrays_whenMismatch_thenZero() {
int[] firstArray = {0, 0, 0, 0, 0};
int[] secondArray = {9, 8, 7, 6, 5};
assertEquals(0, Arrays.mismatch(firstArray, 1, 2, secondArray, 1, 2));
}
@Test
void givenAtLeastANullSubArray_whenMismatch_thenThrowsNullPointerException() {
int[] firstArray = null;
int[] secondArray = {1, 2, 3, 4, 5};
assertThrows(NullPointerException.class, () -> Arrays.mismatch(firstArray, 0, 1, secondArray, 0, 1));
assertThrows(NullPointerException.class, () -> Arrays.mismatch(secondArray, 0, 1, firstArray, 0, 1));
assertThrows(NullPointerException.class, () -> Arrays.mismatch(firstArray, 0, 1, firstArray, 0, 1));
}
@Test
void givenExactlyOneEmptySubArray_whenMismatch_thenZero() {
int[] firstArray = {1};
int[] secondArray = {1, 2, 3};
assertEquals(0, Arrays.mismatch(firstArray, 0, 0, secondArray, 0, 2));
assertEquals(0, Arrays.mismatch(firstArray, 0, 1, secondArray, 2, 2));
}
@Test
void givenTwoEmptySubArrays_whenMismatch_thenMinusOne() {
int[] firstArray = {1};
int[] secondArray = {1, 2, 3};
assertEquals(-1, Arrays.mismatch(firstArray, 0, 0, secondArray, 2, 2));
}
@Test
void givenToIndexGreaterThanFromIndex_whenMismatch_thenThrowsIllegalArgumentException() {
int[] firstArray = {2, 3, 4, 5, 4, 3, 2};
int[] secondArray = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
assertThrows(IllegalArgumentException.class, () -> Arrays.mismatch(firstArray, 4, 2, secondArray, 0, 6));
assertThrows(IllegalArgumentException.class, () -> Arrays.mismatch(firstArray, 2, 3, secondArray, 6, 0));
}
@Test
void givenIllegalIndexes_whenMismatch_thenThrowsArrayIndexOutOfBoundsException() {
int[] firstArray = {2, 3, 4, 5, 4, 3, 2};
int[] secondArray = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
assertThrows(ArrayIndexOutOfBoundsException.class, () -> Arrays.mismatch(firstArray, -1, 2, secondArray, 0, 6));
assertThrows(ArrayIndexOutOfBoundsException.class, () -> Arrays.mismatch(firstArray, 0, 8, secondArray, 0, 6));
assertThrows(ArrayIndexOutOfBoundsException.class, () -> Arrays.mismatch(firstArray, 2, 3, secondArray, -5, 0));
assertThrows(ArrayIndexOutOfBoundsException.class, () -> Arrays.mismatch(firstArray, 2, 3, secondArray, 11, 12));
}
@Test
void givenTwoStringArraysAndAComparator_whenMismatch_thenIndexOfFirstMismatch() {
String[] firstArray = {"one", "two", "three"};
String[] secondArray = {"ONE", "TWO", "FOUR"};
Comparator<String> comparator = String.CASE_INSENSITIVE_ORDER;
assertEquals(2, Arrays.mismatch(firstArray, secondArray, comparator));
}
@Test
void givenTwoIdenticalStringArraysForTheComparator_whenMismatch_thenMinusOne() {
String[] firstArray = {"one", "two", "three"};
String[] secondArray = {"ONE", "TWO", "THREE"};
Comparator<String> comparator = String.CASE_INSENSITIVE_ORDER;
assertEquals(-1, Arrays.mismatch(firstArray, secondArray, comparator));
}
@Test
void givenFirstStringArrayIsAPrefixOfTheSecondForTheComparator_whenMismatch_thenFirstArrayLength() {
String[] firstArray = {"one", "two", "three"};
String[] secondArray = {"ONE", "TWO", "THREE", "FOUR", "FIVE"};
Comparator<String> comparator = String.CASE_INSENSITIVE_ORDER;
assertEquals(firstArray.length, Arrays.mismatch(firstArray, secondArray, comparator));
}
@Test
void givenNoCommonPrefixForTheComparator_whenMismatch_thenZero() {
String[] firstArray = {"one", "two", "three"};
String[] secondArray = {"six", "seven", "eight"};
Comparator<String> comparator = String.CASE_INSENSITIVE_ORDER;
assertEquals(0, Arrays.mismatch(firstArray, secondArray, comparator));
}
@Test
void givenAtLeastANullArrayOrNullComparator_whenMismatch_thenThrowsNullPointerException() {
String[] firstArray = null;
String[] secondArray = {"one"};
Comparator<String> comparator = String.CASE_INSENSITIVE_ORDER;
assertThrows(NullPointerException.class, () -> Arrays.mismatch(firstArray, secondArray, comparator));
assertThrows(NullPointerException.class, () -> Arrays.mismatch(secondArray, firstArray, comparator));
assertThrows(NullPointerException.class, () -> Arrays.mismatch(secondArray, secondArray, null));
}
@Test
void givenExactlyOneAnEmptyArrayAndAComparator_whenMismatch_thenZero() {
String[] firstArray = {};
String[] secondArray = {"one"};
Comparator<String> comparator = String.CASE_INSENSITIVE_ORDER;
assertEquals(0, Arrays.mismatch(firstArray, secondArray, comparator));
assertEquals(0, Arrays.mismatch(secondArray, firstArray, comparator));
}
@Test
void givenTwoEmptyStringArraysForTheComparator_whenMismatch_thenMinusOne() {
assertEquals(-1, Arrays.mismatch(new String[] {}, new String[] {}, String.CASE_INSENSITIVE_ORDER));
}
@Test
void givenTwoStringSubarraysAndAComparator_whenMismatch_thenIndexOfFirstMismatch() {
String[] firstArray = {"one", "two", "three", "four"};
String[] secondArray = {"ZERO", "ONE", "TWO", "FOUR", "EIGHT", "SIXTEEN"};
Comparator<String> comparator = String.CASE_INSENSITIVE_ORDER;
assertEquals(2, Arrays.mismatch(firstArray, 0, 4, secondArray, 1, 3, comparator));
}
@Test
void givenTwoIdenticalStringSubArraysForTheComparator_whenMismatch_thenMinusOne() {
String[] firstArray = {"zero", "zero", "one", "two"};
String[] secondArray = {"zero", "one", "two", "three", "four"};
Comparator<String> comparator = String.CASE_INSENSITIVE_ORDER;
assertEquals(-1, Arrays.mismatch(firstArray, 2, 4, secondArray, 1, 3, comparator));
}
@Test
void givenFirstSubArrayIsAPrefixOfTheSecondForTheComparator_whenMismatch_thenFirstArrayLength() {
String[] firstArray = {"two", "three", "four", "five", "four", "three", "two"};
String[] secondArray = {"ZERO", "ONE", "TWO", "THREE", "FOUR", "FIVE", "EIGHT", "NINE", "TEN"};
Comparator<String> comparator = String.CASE_INSENSITIVE_ORDER;
assertEquals(4, Arrays.mismatch(firstArray, 0, 4, secondArray, 2, 9, comparator));
}
@Test
void givenNoCommonPrefixForSubArraysForTheComparator_whenMismatch_thenZero() {
String[] firstArray = {"zero", "one"};
String[] secondArray = {"TEN", "ELEVEN", "TWELVE"};
Comparator<String> comparator = String.CASE_INSENSITIVE_ORDER;
assertEquals(0, Arrays.mismatch(firstArray, 1, 2, secondArray, 1, 2, comparator));
}
@Test
void givenAtLeastANullSubArrayOrNullComparator_whenMismatch_thenThrowsNullPointerException() {
String[] firstArray = null;
String[] secondArray = {"ONE", "TWO", "THREE", "FOUR", "FIVE"};
Comparator<String> comparator = String.CASE_INSENSITIVE_ORDER;
assertThrows(NullPointerException.class, () -> Arrays.mismatch(firstArray, 0, 1, secondArray, 0, 1, comparator));
assertThrows(NullPointerException.class, () -> Arrays.mismatch(secondArray, 0, 1, firstArray, 0, 1, comparator));
assertThrows(NullPointerException.class, () -> Arrays.mismatch(firstArray, 0, 1, firstArray, 0, 1, comparator));
assertThrows(NullPointerException.class, () -> Arrays.mismatch(secondArray, 0, 1, secondArray, 0, 1, null));
}
@Test
void givenExactlyOneEmptySubArrayAndAComparator_whenMismatch_thenZero() {
String[] firstArray = {"one"};
String[] secondArray = {"ONE", "TWO", "THREE"};
Comparator<String> comparator = String.CASE_INSENSITIVE_ORDER;
assertEquals(0, Arrays.mismatch(firstArray, 0, 0, secondArray, 0, 2, comparator));
assertEquals(0, Arrays.mismatch(firstArray, 0, 1, secondArray, 2, 2, comparator));
}
@Test
void givenTwoEmptySubArraysAndAComparator_whenMismatch_thenMinusOne() {
String[] firstArray = {"one"};
String[] secondArray = {"ONE", "TWO", "THREE"};
Comparator<String> comparator = String.CASE_INSENSITIVE_ORDER;
assertEquals(-1, Arrays.mismatch(firstArray, 0, 0, secondArray, 2, 2, comparator));
}
@Test
void givenToIndexGreaterThanFromIndexAndAComparator_whenMismatch_thenThrowsIllegalArgumentException() {
String[] firstArray = {"two", "three", "four", "five", "four", "three", "two"};
String[] secondArray = {"ZERO", "ONE", "TWO", "THREE", "FOUR", "FIVE", "EIGHT", "NINE", "TEN"};
Comparator<String> comparator = String.CASE_INSENSITIVE_ORDER;
assertThrows(IllegalArgumentException.class, () -> Arrays.mismatch(firstArray, 4, 2, secondArray, 0, 6, comparator));
assertThrows(IllegalArgumentException.class, () -> Arrays.mismatch(firstArray, 2, 3, secondArray, 6, 0, comparator));
}
@Test
void givenIllegalIndexesAndAComparator_whenMismatch_thenThrowsArrayIndexOutOfBoundsException() {
String[] firstArray = {"two", "three", "four", "five", "four", "three", "two"};
String[] secondArray = {"ZERO", "ONE", "TWO", "THREE", "FOUR", "FIVE", "EIGHT", "NINE", "TEN"};
Comparator<String> comparator = String.CASE_INSENSITIVE_ORDER;
assertThrows(ArrayIndexOutOfBoundsException.class, () -> Arrays.mismatch(firstArray, -1, 2, secondArray, 0, 6, comparator));
assertThrows(ArrayIndexOutOfBoundsException.class, () -> Arrays.mismatch(firstArray, 0, 8, secondArray, 0, 6, comparator));
assertThrows(ArrayIndexOutOfBoundsException.class, () -> Arrays.mismatch(firstArray, 2, 3, secondArray, -5, 0, comparator));
assertThrows(ArrayIndexOutOfBoundsException.class, () -> Arrays.mismatch(firstArray, 2, 3, secondArray, 11, 12, comparator));
}
}
@@ -34,7 +34,6 @@
<properties>
<commons-lang.version>2.2</commons-lang.version>
<commons-lang3.version>3.12.0</commons-lang3.version>
</properties>
</project>
@@ -7,4 +7,8 @@
- [Creating Custom Iterator in Java](https://www.baeldung.com/java-creating-custom-iterator)
- [Difference Between Arrays.sort() and Collections.sort()](https://www.baeldung.com/java-arrays-collections-sort-methods)
- [Skipping the First Iteration in Java](https://www.baeldung.com/java-skip-first-iteration)
- [Remove Elements From a Queue Using Loop](https://www.baeldung.com/java-remove-elements-queue)
- [Intro to Vector Class in Java](https://www.baeldung.com/java-vector-guide)
- [HashSet toArray() Method in Java](https://www.baeldung.com/java-hashset-toarray)
- [Time Complexity of Java Collections Sort in Java](https://www.baeldung.com/java-time-complexity-collections-sort)
- More articles: [[<-- prev]](/core-java-modules/core-java-collections-4)
@@ -0,0 +1,60 @@
package com.baeldung.collectionssortcomplexity;
import org.openjdk.jmh.annotations.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@Fork(value = 1, warmups = 1)
@Warmup(iterations = 5, time = 1)
@Measurement(iterations = 5, time = 1)
public class CollectionsSortTimeComplexityJMH {
public static void main(String[] args) throws Exception {
org.openjdk.jmh.Main.main(args);
}
@Benchmark
public void measureCollectionsSortBestCase(BestCaseBenchmarkState state) {
List<Integer> sortedList = new ArrayList<>(state.sortedList);
Collections.sort(sortedList);
}
@Benchmark
public void measureCollectionsSortAverageWorstCase(AverageWorstCaseBenchmarkState state) {
List<Integer> unsortedList = new ArrayList<>(state.unsortedList);
Collections.sort(unsortedList);
}
@State(Scope.Benchmark)
public static class BestCaseBenchmarkState {
List<Integer> sortedList;
@Setup(Level.Trial)
public void setUp() {
sortedList = new ArrayList<>();
for (int i = 1; i <= 1000000; i++) {
sortedList.add(i);
}
}
}
@State(Scope.Benchmark)
public static class AverageWorstCaseBenchmarkState {
List<Integer> unsortedList;
@Setup(Level.Trial)
public void setUp() {
unsortedList = new ArrayList<>();
for (int i = 1000000; i > 0; i--) {
unsortedList.add(i);
}
}
}
}
@@ -0,0 +1,33 @@
package com.baeldung.collectionssortcomplexity;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class CollectionsSortTimeComplexityMain {
// O(n log n) Time Complexity Example
public static void worstAndAverageCasesTimeComplexity() {
Integer[] sortedArray = {20, 21, 22, 23, 24, 25, 26, 17, 28, 29, 30, 31, 18, 19, 32, 33, 34, 27, 35};
List<Integer> list = Arrays.asList(sortedArray);
Collections.shuffle(list);
long startTime = System.nanoTime();
Collections.sort(list);
long endTime = System.nanoTime();
System.out.println("Execution Time for O(n log n): " + (endTime - startTime) + " nanoseconds");
}
// O(n) Time Complexity Example
public static void bestCaseTimeComplexity() {
Integer[] sortedArray = {19, 22, 19, 22, 24, 25, 17, 11, 22, 23, 28, 23, 0, 1, 12, 9, 13, 27, 15};
List<Integer> list = Arrays.asList(sortedArray);
long startTime = System.nanoTime();
Collections.sort(list);
long endTime = System.nanoTime();
System.out.println("Execution Time for O(n): " + (endTime - startTime) + " nanoseconds");
}
public static void main(String[] args) {
worstAndAverageCasesTimeComplexity();
bestCaseTimeComplexity();
}
}
@@ -0,0 +1,60 @@
package com.baeldung.removequeueelements;
import org.junit.Test;
import java.util.LinkedList;
import java.util.Queue;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class RemoveQueueElementsUnitTest {
@Test
public void givenQueueWithEvenAndOddNumbers_whenRemovingEvenNumbers_thenOddNumbersRemain() {
Queue<Integer> queue = new LinkedList<>();
Queue<Integer> oddElementsQueue = new LinkedList<>();
queue.add(1);
queue.add(2);
queue.add(3);
queue.add(4);
queue.add(5);
while (queue.peek() != null) {
int element = queue.remove();
if (element % 2 != 0) {
oddElementsQueue.add(element);
}
}
assertEquals(3, oddElementsQueue.size());
assertTrue(oddElementsQueue.contains(1));
assertTrue(oddElementsQueue.contains(3));
assertTrue(oddElementsQueue.contains(5));
}
@Test
public void givenStringQueue_whenRemovingStringsThatStartWithA_thenStringElementsRemain() {
Queue<String> queue = new LinkedList<>();
Queue<String> stringElementsQueue = new LinkedList<>();
queue.add("Apple");
queue.add("Banana");
queue.add("Orange");
queue.add("Grape");
queue.add("Mango");
while (queue.peek() != null) {
String element = queue.remove();
if (!element.startsWith("A")) {
stringElementsQueue.add(element);
}
}
assertEquals(4, stringElementsQueue.size());
assertTrue(stringElementsQueue.contains("Banana"));
assertTrue(stringElementsQueue.contains("Orange"));
assertTrue(stringElementsQueue.contains("Grape"));
assertTrue(stringElementsQueue.contains("Mango"));
}
}
@@ -0,0 +1,87 @@
package com.baeldung.vectors;
import static org.junit.Assert.assertEquals;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Vector;
import org.junit.Test;
public class VectorOperationsUnitTest {
private static Vector<String> getVector() {
Vector<String> vector = new Vector<String>();
vector.add("Today");
vector.add("is");
vector.add("a");
vector.add("great");
vector.add("day!");
return vector;
}
@Test
public void givenAVector_whenAddElementsUsingAddMethod_thenElementsGetAddedAtEnd() {
Vector<String> vector = getVector();
vector.add("Hello");
assertEquals(6, vector.size());
}
@Test
public void givenAVector_whenUpdateElementAtIndex_thenElementAtIndexGetsUpdated() {
Vector<String> vector = getVector();
assertEquals(5, vector.size());
assertEquals("great", vector.get(3));
vector.set(3, "good");
assertEquals("good", vector.get(3));
}
@Test
public void givenAVector_whenRemoveAnElement_thenElementGetsRemovedFromTheVector() {
Vector<String> vector = getVector();
assertEquals(5, vector.size());
// remove a specific element
vector.remove("a");
assertEquals(4, vector.size());
// remove at specific index
vector.remove(2);
assertEquals("day!", vector.get(2));
assertEquals(3, vector.size());
assertEquals(false, vector.remove("SomethingThatDoesn'tExist"));
}
@Test(expected = ArrayIndexOutOfBoundsException.class)
public void givenAVector_whenIndexIsBeyondRange_thenRemoveMethodThrowsArrayIndexOutOfBoundsException() {
Vector<String> vector = getVector();
assertEquals(5, vector.size());
vector.remove(10);
}
@Test
public void givenAVector_whenGetElementWithinARange_thenGetMethodGetsAnElementFromTheVector() {
Vector<String> vector = getVector();
String fourthElement = vector.get(3);
assertEquals("great", fourthElement);
}
@Test(expected = ArrayIndexOutOfBoundsException.class)
public void givenAVector_whenGetElementBeyondARange_thenGetMethodThrowsArrayIndexOutOfBoundsException() {
Vector<String> vector = getVector();
assertEquals(5, vector.size());
vector.get(10);
}
@Test
public void givenAVector_whenAddElementFromACollection_thenAllElementsGetAdeddToTheVector() {
Vector<String> vector = getVector();
assertEquals(5, vector.size());
ArrayList<String> words = new ArrayList<>(Arrays.asList("Baeldung", "is", "cool!"));
vector.addAll(words);
assertEquals(8, vector.size());
assertEquals("cool!", vector.get(7));
}
}
@@ -0,0 +1,51 @@
package com.baeldung.toarraymethod;
import org.junit.Test;
import java.util.HashSet;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
public class ConvertingHashSetToArrayUnitTest {
@Test
public void givenStringHashSet_whenConvertedToArray_thenArrayContainsStringElements() {
HashSet<String> stringSet = new HashSet<>();
stringSet.add("Apple");
stringSet.add("Banana");
stringSet.add("Cherry");
// Convert the HashSet of Strings to an array of Strings
String[] stringArray = stringSet.toArray(new String[0]);
// Test that the array is of the correct length
assertEquals(3, stringArray.length);
for (String str : stringArray) {
assertTrue(stringSet.contains(str));
}
}
@Test
public void givenIntegerHashSet_whenConvertedToArray_thenArrayContainsIntegerElements() {
HashSet<Integer> integerSet = new HashSet<>();
integerSet.add(5);
integerSet.add(10);
integerSet.add(15);
// Convert the HashSet of Integers to an array of Integers
Integer[] integerArray = integerSet.toArray(new Integer[0]);
// Test that the array is of the correct length
assertEquals(3, integerArray.length);
for (Integer num : integerArray) {
assertTrue(integerSet.contains(num));
}
assertTrue(integerSet.contains(5));
assertTrue(integerSet.contains(10));
assertTrue(integerSet.contains(15));
}
}
@@ -1,17 +1,17 @@
<project
xmlns="http://maven.apache.org/POM/4.0.0"
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>core-java-collections-array-list-2</artifactId>
<name>core-java-collections-array-list-2</name>
<packaging>jar</packaging>
<parent>
<groupId>com.baeldung.core-java-modules</groupId>
<artifactId>core-java-modules</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<build>
<plugins>
<plugin>
@@ -24,7 +24,7 @@
</plugin>
</plugins>
</build>
<properties>
<maven-compiler-plugin.source>17</maven-compiler-plugin.source>
<maven-compiler-plugin.target>17</maven-compiler-plugin.target>
@@ -43,7 +43,6 @@
<properties>
<vavr.version>0.10.3</vavr.version>
<java.version>11</java.version>
<modelmapper.version>3.1.1</modelmapper.version>
<modelmapper.version>3.2.0</modelmapper.version>
</properties>
</project>
@@ -1,8 +1,9 @@
package com.baeldung.modelmapper;
import org.hamcrest.Matchers;
import org.junit.Before;
import org.junit.Test;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.modelmapper.ModelMapper;
import org.modelmapper.TypeMap;
import org.modelmapper.TypeToken;
@@ -10,11 +11,10 @@ import org.modelmapper.TypeToken;
import java.util.ArrayList;
import java.util.List;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasItems;
import static org.hamcrest.Matchers.hasProperty;
import static org.junit.Assert.assertThat;
/**
* This class has test methods of mapping Integer to Character list,
@@ -22,12 +22,12 @@ import static org.junit.Assert.assertThat;
*
* @author Sasa Milenkovic
*/
public class UsersListMappingUnitTest {
class UsersListMappingUnitTest {
private ModelMapper modelMapper;
private List<User> users;
@Before
@BeforeEach
public void init() {
modelMapper = new ModelMapper();
@@ -35,18 +35,16 @@ public class UsersListMappingUnitTest {
TypeMap<UserList, UserListDTO> typeMap = modelMapper.createTypeMap(UserList.class, UserListDTO.class);
typeMap.addMappings(mapper -> mapper.using(new UsersListConverter())
.map(UserList::getUsers, UserListDTO::setUsernames));
.map(UserList::getUsers, UserListDTO::setUsernames));
users = new ArrayList();
users = new ArrayList<>();
users.add(new User("b100", "user1", "user1@baeldung.com", "111-222", "USER"));
users.add(new User("b101", "user2", "user2@baeldung.com", "111-333", "USER"));
users.add(new User("b102", "user3", "user3@baeldung.com", "111-444", "ADMIN"));
}
@Test
public void whenInteger_thenMapToCharacter() {
void whenInteger_thenMapToCharacter() {
List<Integer> integers = new ArrayList<Integer>();
integers.add(1);
@@ -57,36 +55,27 @@ public class UsersListMappingUnitTest {
}.getType());
assertThat(characters, hasItems('1', '2', '3'));
}
@Test
public void givenUsersList_whenUseGenericType_thenMapToUserDTO() {
void givenUsersList_whenUseGenericType_thenMapToUserDTO() {
// Mapping lists using custom (generic) type mapping
List<UserDTO> userDtoList = MapperUtil.mapList(users, UserDTO.class);
assertThat(userDtoList, Matchers.<UserDTO>hasItem(
Matchers.both(hasProperty("userId", equalTo("b100")))
.and(hasProperty("email", equalTo("user1@baeldung.com")))
.and(hasProperty("username", equalTo("user1")))));
assertThat(userDtoList, Matchers.<UserDTO> hasItem(Matchers.both(hasProperty("userId", equalTo("b100")))
.and(hasProperty("email", equalTo("user1@baeldung.com")))
.and(hasProperty("username", equalTo("user1")))));
}
@Test
public void givenUsersList_whenUseConverter_thenMapToUsernames() {
void givenUsersList_whenUseConverter_thenMapToUsernames() {
// Mapping lists using property mapping and converter
UserList userList = new UserList();
userList.setUsers(users);
UserListDTO dtos = new UserListDTO();
modelMapper.map(userList, dtos);
assertThat(dtos.getUsernames(), hasItems("user1", "user2", "user3"));
}
}
@@ -4,3 +4,4 @@ This module contains articles about conversions among Collection types in Java.
### Relevant Articles:
- [Converting HashMap Values to an ArrayList in Java](https://www.baeldung.com/java-hashmap-arraylist)
- [Joining a List<String> in Java With Commas and “and”](https://www.baeldung.com/java-string-concatenation-natural-language)
@@ -71,4 +71,15 @@ public class ListOfListsUnitTest {
assertThat(listOfLists.get(2)).containsExactly("Slack", "Zoom", "Microsoft Teams", "Telegram");
printListOfLists(listOfLists);
}
}
@Test
void givenListOfLists_whenGettingSizeOfSubListsAndSizeOfElements_thenGetExpectedResults() throws URISyntaxException, IOException {
List<List<String>> listOfLists = getListOfListsFromCsv();
// size of inner lists
assertThat(listOfLists).hasSize(3);
// size of all elements in subLists
int totalElements = listOfLists.stream().mapToInt(List::size).sum();
assertThat(totalElements).isEqualTo(12);
}
}
@@ -39,7 +39,7 @@
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.26</version>
<version>${lombok.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
@@ -66,9 +66,8 @@
<properties>
<jmh.version>1.21</jmh.version>
<commons-lang.version>2.2</commons-lang.version>
<commons-lang3.version>3.12.0</commons-lang3.version>
<gson.version>2.10.1</gson.version>
<jackson.version>2.15.2</jackson.version>
<jackson.version>2.16.0</jackson.version>
<org.json.version>20230618</org.json.version>
</properties>
</project>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>core-java-collections-list-6</artifactId>
<name>core-java-collections-list-6</name>
@@ -12,4 +12,5 @@
<artifactId>core-java-modules</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
</project>
@@ -9,3 +9,4 @@
- [Converting String or String Array to Map in Java](https://www.baeldung.com/java-convert-string-to-map)
- [Remove Duplicate Values From HashMap in Java](https://www.baeldung.com/java-hashmap-delete-duplicates)
- [Sorting Java Map in Descending Order](https://www.baeldung.com/java-sort-map-descending)
- [Convert HashMap.toString() to HashMap in Java](https://www.baeldung.com/hashmap-from-tostring)
@@ -13,14 +13,11 @@
<version>0.0.1-SNAPSHOT</version>
</parent>
<properties>
<spring.version>5.2.5.RELEASE</spring.version>
</properties>
<dependencies>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.13.1</version>
<version>2.16.0</version>
</dependency>
<dependency>
<groupId>org.openjdk.jmh</groupId>
@@ -40,7 +37,7 @@
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.1</version>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
@@ -51,4 +48,8 @@
</dependency>
</dependencies>
<properties>
<spring.version>5.2.5.RELEASE</spring.version>
</properties>
</project>
@@ -1 +1,10 @@
## Relevant Articles
## Relevant Articles:
- [Difference Between putIfAbsent() and computeIfAbsent() in Javas Map](https://www.baeldung.com/java-map-putifabsent-computeifabsent)
- [How to Write and Read a File with a Java HashMap](https://www.baeldung.com/how-to-write-and-read-a-file-with-a-java-hashmap/)
- [How to Write Hashmap to CSV File](https://www.baeldung.com/java-write-hashmap-csv)
- [How to Get First or Last Entry From a LinkedHashMap in Java](https://www.baeldung.com/java-linkedhashmap-first-last-key-value-pair)
- [How to Write and Read a File with a Java HashMap](https://www.baeldung.com/java-hashmap-write-read-file)
- [Limiting the Max Size of a HashMap in Java](https://www.baeldung.com/java-hashmap-size-bound)
- [How to Sort LinkedHashMap By Values in Java](https://www.baeldung.com/java-sort-linkedhashmap-using-values)
- [How to Increment a Map Value in Java](https://www.baeldung.com/java-increment-map-value)
- More articles: [[<-- prev]](/core-java-modules/core-java-collections-maps-6)
@@ -13,66 +13,56 @@
<version>0.0.1-SNAPSHOT</version>
</parent>
<properties>
<spring.version>5.2.5.RELEASE</spring.version>
</properties>
<dependencies>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.12.4</version>
</dependency>
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-core</artifactId>
<version>1.36</version>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.9</version>
<version>${gson.version}</version>
</dependency>
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20230227</version>
<groupId>org.apache.commons</groupId>
<artifactId>commons-csv</artifactId>
<version>${csv.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.1</version>
<scope>test</scope>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>32.1.2-jre</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.8.1</version>
<scope>test</scope>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-core</artifactId>
<version>1.37</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.1</version>
<scope>test</scope>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-generator-annprocess</artifactId>
<version>1.37</version>
</dependency>
</dependencies>
</project>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>
--add-opens java.base/java.util=ALL-UNNAMED
</argLine>
</configuration>
</plugin>
</plugins>
</build>
<properties>
<gson.version>2.10.1</gson.version>
<csv.version>1.5</csv.version>
</properties>
</project>
@@ -0,0 +1,25 @@
package com.baeldung.map;
import java.util.HashMap;
public class HashMapWithMaxSizeLimit<K, V> extends HashMap<K, V> {
private int maxSize = -1;
public HashMapWithMaxSizeLimit() {
super();
}
public HashMapWithMaxSizeLimit(int maxSize) {
super();
this.maxSize = maxSize;
}
@Override
public V put(K key, V value) {
if (this.maxSize == -1 || this.containsKey(key) || this.size() < this.maxSize) {
return super.put(key, value);
}
throw new RuntimeException("Max size exceeded!");
}
}
@@ -0,0 +1,70 @@
package com.baeldung.map.incrementmapkey;
import java.util.HashMap;
import java.util.Map;
public class BenchmarkMapMethods {
public static void main(String[] args) {
BenchmarkMapMethods bmm = new BenchmarkMapMethods();
Map<String, Long> map = new HashMap<>();
map.put("Guava", bmm.benchMarkGuavaMap());
map.put("ContainsKey", bmm.benchContainsKeyMap());
map.put("MergeMethod", bmm.benchMarkMergeMethod());
map.put("ComputeMethod", bmm.benchMarComputeMethod());
map.put("GetOrDefault", bmm.benchMarkGetOrDefaultMethod());
}
private long benchMarkGuavaMap() {
long startTime = System.nanoTime();
IncrementMapValueWays im = new IncrementMapValueWays();
im.charFrequencyUsingAtomicMap(getString());
long endTime = System.nanoTime();
return endTime - startTime;
}
private long benchContainsKeyMap() {
long startTime = System.nanoTime();
IncrementMapValueWays im = new IncrementMapValueWays();
im.charFrequencyUsingContainsKey(getString());
long endTime = System.nanoTime();
return endTime - startTime;
}
private long benchMarComputeMethod() {
long startTime = System.nanoTime();
IncrementMapValueWays im = new IncrementMapValueWays();
im.charFrequencyUsingCompute(getString());
long endTime = System.nanoTime();
return endTime - startTime;
}
private long benchMarkMergeMethod() {
long startTime = System.nanoTime();
IncrementMapValueWays im = new IncrementMapValueWays();
im.charFrequencyUsingMerge(getString());
long endTime = System.nanoTime();
return endTime - startTime;
}
private long benchMarkGetOrDefaultMethod() {
long startTime = System.nanoTime();
IncrementMapValueWays im = new IncrementMapValueWays();
im.charFrequencyUsingGetOrDefault(getString());
long endTime = System.nanoTime();
return endTime - startTime;
}
private String getString() {
return
"Once upon a time in a quaint village nestled between rolling hills and whispering forests, there lived a solitary storyteller named Elias. Elias was known for spinning tales that transported listeners to magical realms and awakened forgotten dreams.\n"
+ "\n"
+ "His favorite spot was beneath an ancient oak tree, its sprawling branches offering shade to those who sought refuge from the bustle of daily life. Villagers of all ages would gather around Elias, their faces illuminated by the warmth of his stories.\n"
+ "\n" + "One evening, as dusk painted the sky in hues of orange and purple, a curious young girl named Lily approached Elias. Her eyes sparkled with wonder as she asked for a tale unlike any other.\n" + "\n"
+ "Elias smiled, sensing her thirst for adventure, and began a story about a forgotten kingdom veiled by mist, guarded by mystical creatures and enchanted by ancient spells. With each word, the air grew thick with anticipation, and the listeners were transported into a world where magic danced on the edges of reality.\n"
+ "\n" + "As Elias weaved the story, Lily's imagination took flight. She envisioned herself as a brave warrior, wielding a shimmering sword against dark forces, her heart fueled by courage and kindness.\n" + "\n"
+ "The night wore on, but the spell of the tale held everyone captive. The villagers laughed, gasped, and held their breaths, journeying alongside the characters through trials and triumphs.\n" + "\n"
+ "As the final words lingered in the air, a sense of enchantment settled upon the listeners. They thanked Elias for the gift of his storytelling, each carrying a piece of the magical kingdom within their hearts.\n" + "\n"
+ "Lily, inspired by the story, vowed to cherish the spirit of adventure and kindness in her own life. With a newfound spark in her eyes, she bid Elias goodnight, already dreaming of the countless adventures awaiting her.\n" + "\n"
+ "Under the star-studded sky, Elias remained beneath the ancient oak, his heart aglow with the joy of sharing tales that ignited imagination and inspired dreams. And as the night embraced the village, whispers of the enchanted kingdom lingered in the breeze, promising endless possibilities to those who dared to believe.";
}
}
@@ -0,0 +1,68 @@
package com.baeldung.map.incrementmapkey;
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.Mode;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.State;
@State(Scope.Benchmark)
public class BenchmarkMapMethodsJMH {
@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Fork(value = 1, warmups = 1)
public void benchMarkGuavaMap() {
IncrementMapValueWays im = new IncrementMapValueWays();
im.charFrequencyUsingAtomicMap(getString());
}
@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Fork(value = 1, warmups = 1)
public void benchContainsKeyMap() {
IncrementMapValueWays im = new IncrementMapValueWays();
im.charFrequencyUsingContainsKey(getString());
}
@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Fork(value = 1, warmups = 1)
public void benchMarkComputeMethod() {
IncrementMapValueWays im = new IncrementMapValueWays();
im.charFrequencyUsingCompute(getString());
}
@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Fork(value = 1, warmups = 1)
public void benchMarkMergeMethod() {
IncrementMapValueWays im = new IncrementMapValueWays();
im.charFrequencyUsingMerge(getString());
}
public static void main(String[] args) throws Exception {
org.openjdk.jmh.Main.main(args);
}
private String getString() {
return
"Once upon a time in a quaint village nestled between rolling hills and whispering forests, there lived a solitary storyteller named Elias. Elias was known for spinning tales that transported listeners to magical realms and awakened forgotten dreams.\n"
+ "\n"
+ "His favorite spot was beneath an ancient oak tree, its sprawling branches offering shade to those who sought refuge from the bustle of daily life. Villagers of all ages would gather around Elias, their faces illuminated by the warmth of his stories.\n"
+ "\n" + "One evening, as dusk painted the sky in hues of orange and purple, a curious young girl named Lily approached Elias. Her eyes sparkled with wonder as she asked for a tale unlike any other.\n" + "\n"
+ "Elias smiled, sensing her thirst for adventure, and began a story about a forgotten kingdom veiled by mist, guarded by mystical creatures and enchanted by ancient spells. With each word, the air grew thick with anticipation, and the listeners were transported into a world where magic danced on the edges of reality.\n"
+ "\n" + "As Elias weaved the story, Lily's imagination took flight. She envisioned herself as a brave warrior, wielding a shimmering sword against dark forces, her heart fueled by courage and kindness.\n" + "\n"
+ "The night wore on, but the spell of the tale held everyone captive. The villagers laughed, gasped, and held their breaths, journeying alongside the characters through trials and triumphs.\n" + "\n"
+ "As the final words lingered in the air, a sense of enchantment settled upon the listeners. They thanked Elias for the gift of his storytelling, each carrying a piece of the magical kingdom within their hearts.\n" + "\n"
+ "Lily, inspired by the story, vowed to cherish the spirit of adventure and kindness in her own life. With a newfound spark in her eyes, she bid Elias goodnight, already dreaming of the countless adventures awaiting her.\n" + "\n"
+ "Under the star-studded sky, Elias remained beneath the ancient oak, his heart aglow with the joy of sharing tales that ignited imagination and inspired dreams. And as the night embraced the village, whispers of the enchanted kingdom lingered in the breeze, promising endless possibilities to those who dared to believe.";
}
}
@@ -0,0 +1,80 @@
package com.baeldung.map.incrementmapkey;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import com.google.common.util.concurrent.AtomicLongMap;
public class IncrementMapValueWays {
public Map<Character, Integer> charFrequencyUsingContainsKey(String sentence) {
Map<Character, Integer> charMap = new HashMap<>();
for (int c = 0; c < sentence.length(); c++) {
int count = 0;
if (charMap.containsKey(sentence.charAt(c))) {
count = charMap.get(sentence.charAt(c));
}
charMap.put(sentence.charAt(c), count + 1);
}
return charMap;
}
public Map<Character, Integer> charFrequencyUsingGetOrDefault(String sentence) {
Map<Character, Integer> charMap = new HashMap<>();
for (int c = 0; c < sentence.length(); c++) {
charMap.put(sentence.charAt(c), charMap.getOrDefault(sentence.charAt(c), 0) + 1);
}
return charMap;
}
public Map<Character, Integer> charFrequencyUsingMerge(String sentence) {
Map<Character, Integer> charMap = new HashMap<>();
for (int c = 0; c < sentence.length(); c++) {
charMap.merge(sentence.charAt(c), 1, Integer::sum);
}
return charMap;
}
public Map<Character, Integer> charFrequencyUsingCompute(String sentence) {
Map<Character, Integer> charMap = new HashMap<>();
for (int c = 0; c < sentence.length(); c++) {
charMap.compute(sentence.charAt(c), (key, value) -> (value == null) ? 1 : value + 1);
}
return charMap;
}
public Map<Character, Long> charFrequencyUsingAtomicMap(String sentence) {
AtomicLongMap<Character> map = AtomicLongMap.create();
for (int c = 0; c < sentence.length(); c++) {
map.getAndIncrement(sentence.charAt(c));
}
return map.asMap();
}
public Map<Character, Integer> charFrequencyWithConcurrentMap(String sentence, Map<Character, Integer> charMap) {
for (int c = 0; c < sentence.length(); c++) {
charMap.compute(sentence.charAt(c), (key, value) -> (value == null) ? 1 : value + 1);
}
return charMap;
}
public Map<Character, AtomicInteger> charFrequencyWithGetAndIncrement(String sentence) {
Map<Character, AtomicInteger> charMap = new HashMap<>();
for (int c = 0; c < sentence.length(); c++) {
charMap.putIfAbsent(sentence.charAt(c), new AtomicInteger(0));
charMap.get(sentence.charAt(c))
.incrementAndGet();
}
return charMap;
}
public Map<Character, AtomicInteger> charFrequencyWithGetAndIncrementComputeIfAbsent(String sentence) {
Map<Character, AtomicInteger> charMap = new HashMap<>();
for (int c = 0; c < sentence.length(); c++) {
charMap.computeIfAbsent(sentence.charAt(c), k -> new AtomicInteger(0))
.incrementAndGet();
}
return charMap;
}
}
@@ -0,0 +1,51 @@
package com.baeldung.map.readandwritefile;
import java.io.Serializable;
import java.util.Objects;
public class Student implements Serializable {
private static final long serialVersionUID = 1L;
private String firstName;
private String lastName;
/** Default constructor for JSON serialization */
public Student() {
}
public Student(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
Student student = (Student) o;
return Objects.equals(firstName, student.firstName) && Objects.equals(lastName, student.lastName);
}
@Override
public int hashCode() {
return super.hashCode();
}
}
@@ -0,0 +1,60 @@
package com.baeldung.map;
import static org.junit.Assert.assertTrue;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertThrows;
import org.junit.jupiter.api.Test;
class LimitMaxSizeHashMapByCustomHashMapUnitTest {
private final int MAX_SIZE = 4;
private HashMapWithMaxSizeLimit<Integer, String> hashMapWithMaxSizeLimit;
@Test
void givenCustomHashMapObject_whenThereIsNoLimit_thenDoesNotThrowException() {
hashMapWithMaxSizeLimit = new HashMapWithMaxSizeLimit<Integer, String>();
assertDoesNotThrow(() -> {
for (int i = 0; i < 10000; i++) {
hashMapWithMaxSizeLimit.put(i, i + "");
}
});
}
@Test
void givenCustomHashMapObject_whenLimitNotReached_thenDoesNotThrowException() {
hashMapWithMaxSizeLimit = new HashMapWithMaxSizeLimit<Integer, String>(MAX_SIZE);
assertDoesNotThrow(() -> {
for (int i = 0; i < 4; i++) {
hashMapWithMaxSizeLimit.put(i, i + "");
}
});
}
@Test
void givenCustomHashMapObject_whenReplacingValueWhenLimitIsReached_thenDoesNotThrowException() {
hashMapWithMaxSizeLimit = new HashMapWithMaxSizeLimit<Integer, String>(MAX_SIZE);
assertDoesNotThrow(() -> {
hashMapWithMaxSizeLimit.put(1, "One");
hashMapWithMaxSizeLimit.put(2, "Two");
hashMapWithMaxSizeLimit.put(3, "Three");
hashMapWithMaxSizeLimit.put(4, "Four");
hashMapWithMaxSizeLimit.put(4, "4");
});
}
@Test
void givenCustomHashMapObject_whenLimitExceeded_thenThrowsException() {
hashMapWithMaxSizeLimit = new HashMapWithMaxSizeLimit<Integer, String>(MAX_SIZE);
Exception exception = assertThrows(RuntimeException.class, () -> {
for (int i = 0; i < 5; i++) {
hashMapWithMaxSizeLimit.put(i, i + "");
}
});
String messageThrownWhenSizeExceedsLimit = "Max size exceeded!";
String actualMessage = exception.getMessage();
assertTrue(actualMessage.equals(messageThrownWhenSizeExceedsLimit));
}
}
@@ -0,0 +1,38 @@
package com.baeldung.map;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import java.util.LinkedHashMap;
import java.util.Map;
import org.junit.jupiter.api.Test;
class LimitMaxSizeHashMapByLinkedHashMapUnitTest {
@Test
void givenLinkedHashMapObject_whenAddingNewEntry_thenEldestEntryIsRemoved() {
final int MAX_SIZE = 4;
LinkedHashMap<Integer, String> linkedHashMap;
linkedHashMap = new LinkedHashMap<Integer, String>() {
private static final long serialVersionUID = 1L;
@Override
protected boolean removeEldestEntry(Map.Entry<Integer, String> eldest) {
return size() > MAX_SIZE;
}
};
linkedHashMap.put(1, "One");
linkedHashMap.put(2, "Two");
linkedHashMap.put(3, "Three");
linkedHashMap.put(4, "Four");
linkedHashMap.put(5, "Five");
String[] expectedArrayAfterFive = { "Two", "Three", "Four", "Five" };
assertArrayEquals(expectedArrayAfterFive, linkedHashMap.values()
.toArray());
linkedHashMap.put(6, "Six");
String[] expectedArrayAfterSix = { "Three", "Four", "Five", "Six" };
assertArrayEquals(expectedArrayAfterSix, linkedHashMap.values()
.toArray());
}
}
@@ -0,0 +1,141 @@
package com.baeldung.map;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import org.junit.jupiter.api.Test;
class Player {
private String name;
private Integer score = 0;
public Player(String name, Integer score) {
this.name = name;
this.score = score;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof Player)) {
return false;
}
Player player = (Player) o;
if (!Objects.equals(name, player.name)) {
return false;
}
return Objects.equals(score, player.score);
}
@Override
public int hashCode() {
int result = name != null ? name.hashCode() : 0;
result = 31 * result + (score != null ? score.hashCode() : 0);
return result;
}
public String getName() {
return name;
}
public int getScore() {
return score;
}
}
public class LinkedHashMapSortByValueUnitTest {
private static LinkedHashMap<String, Integer> MY_MAP = new LinkedHashMap<>();
static {
MY_MAP.put("key a", 4);
MY_MAP.put("key b", 1);
MY_MAP.put("key c", 3);
MY_MAP.put("key d", 2);
MY_MAP.put("key e", 5);
}
private static LinkedHashMap<String, Integer> EXPECTED_MY_MAP = new LinkedHashMap<>();
static {
EXPECTED_MY_MAP.put("key b", 1);
EXPECTED_MY_MAP.put("key d", 2);
EXPECTED_MY_MAP.put("key c", 3);
EXPECTED_MY_MAP.put("key a", 4);
EXPECTED_MY_MAP.put("key e", 5);
}
private static final LinkedHashMap<String, Player> PLAYERS = new LinkedHashMap<>();
static {
PLAYERS.put("player a", new Player("Eric", 9));
PLAYERS.put("player b", new Player("Kai", 7));
PLAYERS.put("player c", new Player("Amanda", 20));
PLAYERS.put("player d", new Player("Kevin", 4));
}
private static final LinkedHashMap<String, Player> EXPECTED_PLAYERS = new LinkedHashMap<>();
static {
EXPECTED_PLAYERS.put("player d", new Player("Kevin", 4));
EXPECTED_PLAYERS.put("player b", new Player("Kai", 7));
EXPECTED_PLAYERS.put("player a", new Player("Eric", 9));
EXPECTED_PLAYERS.put("player c", new Player("Amanda", 20));
}
@Test
void whenUsingCollectionSort_thenGetExpectedResult() {
List<Map.Entry<String, Integer>> entryList = new ArrayList<>(MY_MAP.entrySet());
Collections.sort(entryList, new Comparator<Map.Entry<String, Integer>>() {
@Override
public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {
return o1.getValue()
.compareTo(o2.getValue());
}
});
LinkedHashMap<String, Integer> result = new LinkedHashMap<>();
for (Map.Entry<String, Integer> e : entryList) {
result.put(e.getKey(), e.getValue());
}
assertEquals(EXPECTED_MY_MAP, result);
}
@Test
void whenUsingEntrycomparingByValueAndFillAMap_thenGetExpectedResult() {
LinkedHashMap<String, Integer> result = new LinkedHashMap<>();
MY_MAP.entrySet()
.stream()
.sorted(Map.Entry.comparingByValue())
.forEachOrdered(entry -> result.put(entry.getKey(), entry.getValue()));
assertEquals(EXPECTED_MY_MAP, result);
}
@Test
void whenUsingEntrycomparingByValueAndCollect_thenGetExpectedResult() {
LinkedHashMap<String, Integer> result = MY_MAP.entrySet()
.stream()
.sorted(Map.Entry.comparingByValue())
.collect(LinkedHashMap::new, (map, entry) -> map.put(entry.getKey(), entry.getValue()), Map::putAll);
assertEquals(EXPECTED_MY_MAP, result);
}
@Test
void whenUsingEntrycomparingByValueAndComparator_thenGetExpectedResult() {
LinkedHashMap<String, Player> result = PLAYERS.entrySet()
.stream()
.sorted(Map.Entry.comparingByValue(Comparator.comparing(Player::getScore)))
.collect(LinkedHashMap::new, (map, entry) -> map.put(entry.getKey(), entry.getValue()), Map::putAll);
assertEquals(EXPECTED_PLAYERS, result);
}
}
@@ -0,0 +1,98 @@
package com.baeldung.map;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.util.HashMap;
import java.util.Map;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.*;
class Magic {
public String nullFunc() {
return null;
}
public String strFunc(String input) {
return input + ": A nice string";
}
}
public class PutIfAbsentVsComputeIfAbsentUnitTest {
private static final Map<String, String> MY_MAP = new HashMap<>();
private Magic magic = new Magic();
@BeforeEach
void resetTheMap() {
MY_MAP.clear();
MY_MAP.put("Key A", "value A");
MY_MAP.put("Key B", "value B");
MY_MAP.put("Key C", "value C");
MY_MAP.put("Key Null", null);
}
@Test
void whenCallingPutIfAbsentWithAbsentKey_thenGetNull() {
String putResult = MY_MAP.putIfAbsent("new key1", magic.nullFunc());
assertNull(putResult);
putResult = MY_MAP.putIfAbsent("new key2", magic.strFunc("new key2"));
assertNull(putResult);
putResult = MY_MAP.putIfAbsent("Key Null", magic.strFunc("Key Null"));
assertNull(putResult);
}
@Test
void whenCallingComputeIfAbsentWithAbsentKey_thenGetExpectedResult() {
String computeResult = MY_MAP.computeIfAbsent("new key1", k -> magic.nullFunc());
assertNull(computeResult);
computeResult = MY_MAP.computeIfAbsent("new key2", k -> magic.strFunc(k));
assertEquals("new key2: A nice string", computeResult);
computeResult = MY_MAP.computeIfAbsent("Key Null", k -> magic.strFunc(k));
assertEquals("Key Null: A nice string", computeResult);
}
@Test
void whenCallingPutIfAbsentWithAbsentKey_thenNullIsPut() {
assertEquals(4, MY_MAP.size()); // initial: 4 entries
MY_MAP.putIfAbsent("new key", magic.nullFunc());
assertEquals(5, MY_MAP.size());
assertTrue(MY_MAP.containsKey("new key")); // new entry has been added to the map
assertNull(MY_MAP.get("new key"));
}
@Test
void whenCallingComputeIfAbsentWithAbsentKey_thenNullIsNotPut() {
assertEquals(4, MY_MAP.size()); // initial: 4 entries
MY_MAP.computeIfAbsent("new key", k -> magic.nullFunc());
assertEquals(4, MY_MAP.size());
assertFalse(MY_MAP.containsKey("new key")); // <- no new entry added
}
@Test
void whenCallingPutIfAbsent_thenFunctionIsAlwaysCalled() {
Magic spyMagic = spy(magic);
MY_MAP.putIfAbsent("Key A", spyMagic.strFunc("Key A"));
verify(spyMagic, times(1)).strFunc(anyString());
MY_MAP.putIfAbsent("new key", spyMagic.strFunc("new key"));
verify(spyMagic, times(2)).strFunc(anyString());
}
@Test
void whenCallingComputeIfAbsent_thenFunctionIsCalledOnDemand() {
Magic spyMagic = spy(magic);
MY_MAP.computeIfAbsent("Key A", k -> spyMagic.strFunc(k));
verify(spyMagic, never()).strFunc(anyString());
MY_MAP.computeIfAbsent("new key", k -> spyMagic.strFunc(k));
verify(spyMagic, times(1)).strFunc(anyString());
}
}
@@ -0,0 +1,105 @@
package com.baeldung.map.incrementmapkey;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.junit.Assert;
import org.junit.Test;
import com.baeldung.map.incrementmapkey.IncrementMapValueWays;
public class IncrementMapValueUnitTest {
@Test
public void givenString_whenUsingContainsKey_thenReturnFreqMap() {
String string = "the quick brown fox jumps over the lazy dog";
IncrementMapValueWays ic = new IncrementMapValueWays();
Map<Character, Integer> actualMap = ic.charFrequencyUsingContainsKey(string);
Map<Character, Integer> expectedMap = getExpectedMap();
Assert.assertEquals(expectedMap, actualMap);
}
@Test
public void givenString_whenUsingGetOrDefault_thenReturnFreqMap() {
String string = "the quick brown fox jumps over the lazy dog";
IncrementMapValueWays ic = new IncrementMapValueWays();
Map<Character, Integer> actualMap = ic.charFrequencyUsingGetOrDefault(string);
Map<Character, Integer> expectedMap = getExpectedMap();
Assert.assertEquals(expectedMap, actualMap);
}
@Test
public void givenString_whenUsingMapMerge_thenReturnFreqMap() {
String string = "the quick brown fox jumps over the lazy dog";
IncrementMapValueWays ic = new IncrementMapValueWays();
Map<Character, Integer> actualMap = ic.charFrequencyUsingMerge(string);
Map<Character, Integer> expectedMap = getExpectedMap();
Assert.assertEquals(expectedMap, actualMap);
}
@Test
public void givenString_whenUsingMapCompute_thenReturnFreqMap() {
String string = "the quick brown fox jumps over the lazy dog";
IncrementMapValueWays ic = new IncrementMapValueWays();
Map<Character, Integer> actualMap = ic.charFrequencyUsingCompute(string);
Map<Character, Integer> expectedMap = getExpectedMap();
Assert.assertEquals(expectedMap, actualMap);
}
@Test
public void givenString_whenUsingGuava_thenReturnFreqMap() {
String string = "the quick brown fox jumps over the lazy dog";
IncrementMapValueWays ic = new IncrementMapValueWays();
Map<Character, Long> actualMap = ic.charFrequencyUsingAtomicMap(string);
Map<Character, Integer> expectedMap = getExpectedMap();
Assert.assertEquals(expectedMap.keySet(), actualMap.keySet());
}
@Test
public void givenString_whenUsingIncrementAndGet_thenReturnFreqMap() {
String string = "the quick brown fox jumps over the lazy dog";
IncrementMapValueWays ic = new IncrementMapValueWays();
Map<Character, AtomicInteger> actualMap = ic.charFrequencyWithGetAndIncrement(string);
Assert.assertEquals(getExpectedMap().keySet(), actualMap.keySet());
}
@Test
public void givenString_whenUsingIncrementAndGetAndComputeIfAbsent_thenReturnFreqMap() {
String string = "the quick brown fox jumps over the lazy dog";
IncrementMapValueWays ic = new IncrementMapValueWays();
Map<Character, AtomicInteger> actualMap = ic.charFrequencyWithGetAndIncrementComputeIfAbsent(string);
Assert.assertEquals(getExpectedMap().keySet(), actualMap.keySet());
}
@Test
public void givenString_whenUsingConcurrentMapCompute_thenReturnFreqMap() throws InterruptedException {
Map<Character, Integer> charMap = new ConcurrentHashMap<>();
Thread thread1 = new Thread(() -> {
IncrementMapValueWays ic = new IncrementMapValueWays();
ic.charFrequencyWithConcurrentMap("the quick brown", charMap);
});
Thread thread2 = new Thread(() -> {
IncrementMapValueWays ic = new IncrementMapValueWays();
ic.charFrequencyWithConcurrentMap(" fox jumps over the lazy dog", charMap);
});
thread1.start();
thread2.start();
thread1.join();
thread2.join();
Map<Character, Integer> expectedMap = getExpectedMap();
Assert.assertEquals(expectedMap, charMap);
}
private Map<Character, Integer> getExpectedMap() {
return Stream.of(
new Object[][] { { ' ', 8 }, { 'a', 1 }, { 'b', 1 }, { 'c', 1 }, { 'd', 1 }, { 'e', 3 }, { 'f', 1 }, { 'g', 1 }, { 'h', 2 }, { 'i', 1 }, { 'j', 1 }, { 'k', 1 }, { 'l', 1 }, { 'm', 1 }, { 'n', 1 }, { 'o', 4 }, { 'p', 1 }, { 'q', 1 }, { 'r', 2 },
{ 's', 1 }, { 't', 2 }, { 'u', 2 }, { 'v', 1 }, { 'w', 1 }, { 'x', 1 }, { 'y', 1 }, { 'z', 1 } })
.collect(Collectors.toMap(data -> (Character) data[0], data -> (Integer) data[1]));
}
}
@@ -0,0 +1,85 @@
package com.baeldung.map.linkedhashmapfirstandlastentry;
import org.junit.jupiter.api.Test;
import java.lang.reflect.Field;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map.Entry;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
public class GetFirstAndLastEntryFromLinkedHashMapUnitTest {
private static final LinkedHashMap<String, String> THE_MAP = new LinkedHashMap<>();
static {
THE_MAP.put("key one", "a1 b1 c1");
THE_MAP.put("key two", "a2 b2 c2");
THE_MAP.put("key three", "a3 b3 c3");
THE_MAP.put("key four", "a4 b4 c4");
}
@Test
void whenIteratingEntrySet_thenGetExpectedResult() {
Entry<String, String> firstEntry = THE_MAP.entrySet().iterator().next();
assertEquals("key one", firstEntry.getKey());
assertEquals("a1 b1 c1", firstEntry.getValue());
Entry<String, String> lastEntry = null;
Iterator<Entry<String, String>> it = THE_MAP.entrySet().iterator();
while (it.hasNext()) {
lastEntry = it.next();
}
assertNotNull(lastEntry);
assertEquals("key four", lastEntry.getKey());
assertEquals("a4 b4 c4", lastEntry.getValue());
}
@Test
void whenConvertingEntriesToArray_thenGetExpectedResult() {
Entry<String, String>[] theArray = new Entry[THE_MAP.size()];
THE_MAP.entrySet().toArray(theArray);
Entry<String, String> firstEntry = theArray[0];
assertEquals("key one", firstEntry.getKey());
assertEquals("a1 b1 c1", firstEntry.getValue());
Entry<String, String> lastEntry = theArray[THE_MAP.size() - 1];
assertEquals("key four", lastEntry.getKey());
assertEquals("a4 b4 c4", lastEntry.getValue());
}
@Test
void whenUsingStreamAPI_thenGetExpectedResult() {
Entry<String, String> firstEntry = THE_MAP.entrySet().stream().findFirst().get();
assertEquals("key one", firstEntry.getKey());
assertEquals("a1 b1 c1", firstEntry.getValue());
Entry<String, String> lastEntry = THE_MAP.entrySet().stream().skip(THE_MAP.size() - 1).findFirst().get();
assertNotNull(lastEntry);
assertEquals("key four", lastEntry.getKey());
assertEquals("a4 b4 c4", lastEntry.getValue());
}
@Test
void whenUsingReflection_thenGetExpectedResult() throws NoSuchFieldException, IllegalAccessException {
Field head = THE_MAP.getClass().getDeclaredField("head");
head.setAccessible(true);
Entry<String, String> firstEntry = (Entry<String, String>) head.get(THE_MAP);
assertEquals("key one", firstEntry.getKey());
assertEquals("a1 b1 c1", firstEntry.getValue());
Field tail = THE_MAP.getClass().getDeclaredField("tail");
tail.setAccessible(true);
Entry<String, String> lastEntry = (Entry<String, String>) tail.get(THE_MAP);
assertEquals("key four", lastEntry.getKey());
assertEquals("a4 b4 c4", lastEntry.getValue());
}
}
@@ -0,0 +1,135 @@
package com.baeldung.map.readandwritefile;
import static org.assertj.core.api.Assertions.assertThat;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.lang.reflect.Type;
import java.nio.file.Files;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.stream.Collectors;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import org.junit.After;
import org.junit.Test;
import org.junit.Before;
public class ReadAndWriteFileWithHashMapUnitTest {
private static final Map<Integer, Student> STUDENT_DATA = new HashMap<>();
static {
STUDENT_DATA.put(1234, new Student("Henry", "Winter"));
STUDENT_DATA.put(5678, new Student("Richard", "Papen"));
}
private File file;
@Before
public void createFile() throws IOException {
file = File.createTempFile("student", ".data");
}
@After
public void deleteFile() {
file.delete();
}
@Test
public void givenHashMap_whenWrittenAsPropertiesFile_thenReloadedMapIsIdentical() throws IOException {
// Given a map containing student data
Map<String, String> studentData = new HashMap<>();
studentData.put("student.firstName", "Henry");
studentData.put("student.lastName", "Winter");
// When converting to a Properties object and writing to a file
Properties props = new Properties();
props.putAll(studentData);
try (OutputStream output = Files.newOutputStream(file.toPath())) {
props.store(output, null);
}
// Then the map resulting from loading the Properties file is identical
Properties propsFromFile = new Properties();
try (InputStream input = Files.newInputStream(file.toPath())) {
propsFromFile.load(input);
}
Map<String, String> studentDataFromProps = propsFromFile.stringPropertyNames()
.stream()
.collect(Collectors.toMap(key -> key, props::getProperty));
assertThat(studentDataFromProps).isEqualTo(studentData);
}
@Test
public void givenHashMap_whenSerializedToFile_thenDeserializedMapIsIdentical() throws IOException, ClassNotFoundException {
// Given a map containing student data (STUDENT_DATA)
// When serializing the map to a file
try (FileOutputStream fileOutput = new FileOutputStream(file); ObjectOutputStream objectStream = new ObjectOutputStream(fileOutput)) {
objectStream.writeObject(STUDENT_DATA);
}
// Then read the file back into a map and check the contents
Map<Integer, Student> studentsFromFile;
try (FileInputStream fileReader = new FileInputStream(file); ObjectInputStream objectStream = new ObjectInputStream(fileReader)) {
studentsFromFile = (HashMap<Integer, Student>) objectStream.readObject();
}
assertThat(studentsFromFile).isEqualTo(STUDENT_DATA);
}
@Test
public void givenHashMap_whenSerializedToFileWithJackson_thenDeserializedMapIsIdentical() throws IOException {
// Given a map containing student data (STUDENT_DATA)
// When converting to JSON with Jackson and writing to a file
ObjectMapper mapper = new ObjectMapper();
try (FileOutputStream fileOutput = new FileOutputStream(file)) {
mapper.writeValue(fileOutput, STUDENT_DATA);
}
// Then deserialize the file back into a map and check that it's identical
Map<Integer, Student> mapFromFile;
try (FileInputStream fileInput = new FileInputStream(file)) {
// Create a TypeReference so we can deserialize the parameterized type
TypeReference<HashMap<Integer, Student>> mapType = new TypeReference<HashMap<Integer, Student>>() {
};
mapFromFile = mapper.readValue(fileInput, mapType);
}
assertThat(mapFromFile).isEqualTo(STUDENT_DATA);
}
@Test
public void givenHashMap_whenSerializedToFileWithGson_thenDeserializedMapIsIdentical() throws IOException {
// Given a map containing student data (STUDENT_DATA)
// When converting to JSON using Gson and writing to a file
Gson gson = new Gson();
try (FileWriter writer = new FileWriter(file)) {
gson.toJson(STUDENT_DATA, writer);
}
// Then deserialize the file back into a map and check that it's identical
Map<Integer, Student> studentsFromFile;
try (FileReader reader = new FileReader(file)) {
Type mapType = new TypeToken<HashMap<Integer, Student>>() {
}.getType();
studentsFromFile = gson.fromJson(reader, mapType);
}
assertThat(studentsFromFile).isEqualTo(STUDENT_DATA);
}
}
@@ -0,0 +1,66 @@
package com.baeldung.writehashmaptocsvfile;
import org.junit.jupiter.api.Test;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVPrinter;
import static org.junit.Assert.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class WriteHashmaptoCVSFileUnitTest {
public Map<String, String> employeeData;
public WriteHashmaptoCVSFileUnitTest() {
employeeData = new HashMap<>();
employeeData.put("Name", "John Doe");
employeeData.put("Title", "Software Engineer");
employeeData.put("Department", "Engineering");
employeeData.put("Salary", "75000");
}
@Test
public void givenEmployeeData_whenWriteToCSVUsingFileWriter_thenCSVFileIsCreated() {
try (FileWriter csvWriter = new FileWriter("employee_data.csv")) {
// Write header row
csvWriter.append("Name,Title,Department,Salary\n");
// Write data row
csvWriter.append(employeeData.get("Name")).append(",");
csvWriter.append(employeeData.get("Title")).append(",");
csvWriter.append(employeeData.get("Department")).append(",");
csvWriter.append(employeeData.get("Salary")).append("\n");
} catch (IOException e) {
e.printStackTrace();
}
// Ensure the CSV file exists
assertTrue(new File("employee_data.csv").exists(), "CSV file does not exist!");
}
@Test
public void givenCSVFile_whenWriteToCSVUsingApacheCommons_thenContentsMatchExpected() {
try (CSVPrinter csvPrinter = new CSVPrinter(new FileWriter("employee_data2.csv"), CSVFormat.DEFAULT)) {
// Write header row
csvPrinter.printRecord("Name", "Title", "Department", "Salary");
// Write data row
csvPrinter.printRecord(employeeData.get("Name"), employeeData.get("Title"), employeeData.get("Department"), employeeData.get("Salary"));
} catch (IOException e) {
e.printStackTrace();
}
// Ensure the CSV file exists
assertTrue(new File("employee_data2.csv").exists());
}
}
@@ -0,0 +1,150 @@
package com.baeldung.concurrent.completablefuture;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.stream.Collectors;
import org.junit.Test;
public class CompletableFutureUnitTest {
@Test
public void givenAsyncTask_whenProcessingAsyncSucceed_thenReturnSuccess() throws ExecutionException, InterruptedException {
Microservice mockMicroserviceA = mock(Microservice.class);
Microservice mockMicroserviceB = mock(Microservice.class);
when(mockMicroserviceA.retrieveAsync(any())).thenReturn(CompletableFuture.completedFuture("Hello"));
when(mockMicroserviceB.retrieveAsync(any())).thenReturn(CompletableFuture.completedFuture("World"));
CompletableFuture<String> resultFuture = processAsync(List.of(mockMicroserviceA, mockMicroserviceB));
String result = resultFuture.get();
assertEquals("HelloWorld", result);
}
@Test
public void givenAsyncTask_whenProcessingAsyncWithException_thenReturnException() throws ExecutionException, InterruptedException {
Microservice mockMicroserviceA = mock(Microservice.class);
Microservice mockMicroserviceB = mock(Microservice.class);
when(mockMicroserviceA.retrieveAsync(any())).thenReturn(CompletableFuture.completedFuture("Hello"));
when(mockMicroserviceB.retrieveAsync(any())).thenReturn(CompletableFuture.failedFuture(new RuntimeException("Simulated Exception")));
CompletableFuture<String> resultFuture = processAsync(List.of(mockMicroserviceA, mockMicroserviceB));
// Use assertThrows to verify that the expected exception is thrown
ExecutionException exception = assertThrows(ExecutionException.class, resultFuture::get);
// Assert the exception message
assertEquals("Simulated Exception", exception.getCause()
.getMessage());
}
@Test
public void givenAsyncTask_whenProcessingAsyncWithTimeout_thenHandleTimeoutException() throws ExecutionException, InterruptedException {
Microservice mockMicroserviceA = mock(Microservice.class);
Microservice mockMicroserviceB = mock(Microservice.class);
Executor delayedExecutor = CompletableFuture.delayedExecutor(200, TimeUnit.MILLISECONDS);
when(mockMicroserviceA.retrieveAsync(any())).thenReturn(CompletableFuture.supplyAsync(() -> "Hello", delayedExecutor));
Executor delayedExecutor2 = CompletableFuture.delayedExecutor(500, TimeUnit.MILLISECONDS);
when(mockMicroserviceB.retrieveAsync(any())).thenReturn(CompletableFuture.supplyAsync(() -> "World", delayedExecutor2));
CompletableFuture<String> resultFuture = processAsync(List.of(mockMicroserviceA, mockMicroserviceB));
assertThrows(TimeoutException.class, () -> resultFuture.get(300, TimeUnit.MILLISECONDS));
}
@Test
public void givenCompletableFuture_whenCompleted_thenStateIsDone() {
Executor delayedExecutor = CompletableFuture.delayedExecutor(200, TimeUnit.MILLISECONDS);
CompletableFuture<String> cf1 = CompletableFuture.supplyAsync(() -> "Hello", delayedExecutor);
CompletableFuture<String> cf2 = CompletableFuture.supplyAsync(() -> " World");
CompletableFuture<String> cf3 = CompletableFuture.supplyAsync(() -> "!");
CompletableFuture<String>[] cfs = new CompletableFuture[] { cf1, cf2, cf3 };
CompletableFuture<Void> allCf = CompletableFuture.allOf(cfs);
assertFalse(allCf.isDone());
allCf.join();
String result = Arrays.stream(cfs)
.map(CompletableFuture::join)
.collect(Collectors.joining());
assertFalse(allCf.isCancelled());
assertTrue(allCf.isDone());
assertFalse(allCf.isCompletedExceptionally());
assertEquals(result, "Hello World!");
}
@Test
public void givenCompletableFuture_whenCompletedWithException_thenStateIsCompletedExceptionally() throws ExecutionException, InterruptedException {
Executor delayedExecutor = CompletableFuture.delayedExecutor(200, TimeUnit.MILLISECONDS);
CompletableFuture<String> cf1 = CompletableFuture.supplyAsync(() -> "Hello", delayedExecutor);
CompletableFuture<String> cf2 = CompletableFuture.failedFuture(new RuntimeException("Simulated Exception"));
CompletableFuture<String> cf3 = CompletableFuture.supplyAsync(() -> "!");
CompletableFuture<String>[] cfs = new CompletableFuture[] { cf1, cf2, cf3 };
CompletableFuture<Void> allCf = CompletableFuture.allOf(cfs);
assertFalse(allCf.isDone());
assertFalse(allCf.isCompletedExceptionally());
// Exception is expected, assert the cause
CompletionException exception = assertThrows(CompletionException.class, allCf::join);
assertEquals("Simulated Exception", exception.getCause()
.getMessage());
assertTrue(allCf.isCompletedExceptionally());
assertTrue(allCf.isDone());
assertFalse(allCf.isCancelled());
}
@Test
public void givenCompletableFuture_whenCancelled_thenStateIsCancelled() throws ExecutionException, InterruptedException {
Executor delayedExecutor = CompletableFuture.delayedExecutor(200, TimeUnit.MILLISECONDS);
CompletableFuture<String> cf1 = CompletableFuture.supplyAsync(() -> "Hello", delayedExecutor);
CompletableFuture<String> cf2 = CompletableFuture.supplyAsync(() -> " World");
CompletableFuture<String> cf3 = CompletableFuture.supplyAsync(() -> "!");
CompletableFuture<String>[] cfs = new CompletableFuture[] { cf1, cf2, cf3 };
CompletableFuture<Void> allCf = CompletableFuture.allOf(cfs);
assertFalse(allCf.isDone());
assertFalse(allCf.isCompletedExceptionally());
allCf.cancel(true);
assertTrue(allCf.isCancelled());
assertTrue(allCf.isDone());
}
CompletableFuture<String> processAsync(List<Microservice> microservices) {
List<CompletableFuture<String>> dataFetchFutures = fetchDataAsync(microservices);
return combineResults(dataFetchFutures);
}
private List<CompletableFuture<String>> fetchDataAsync(List<Microservice> microservices) {
return microservices.stream()
.map(client -> client.retrieveAsync(""))
.collect(Collectors.toList());
}
private CompletableFuture<String> combineResults(List<CompletableFuture<String>> dataFetchFutures) {
return CompletableFuture.allOf(dataFetchFutures.toArray(new CompletableFuture[0]))
.thenApply(v -> dataFetchFutures.stream()
.map(future -> future.exceptionally(ex -> {
throw new CompletionException(ex);
})
.join())
.collect(Collectors.joining()));
}
interface Microservice {
CompletableFuture<String> retrieveAsync(String input);
}
}
@@ -85,12 +85,12 @@
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<jcabi-aspects.version>0.22.6</jcabi-aspects.version>
<aspectjrt.version>1.9.5</aspectjrt.version>
<aspectjrt.version>1.9.20.1</aspectjrt.version>
<cactoos.version>0.43</cactoos.version>
<ea-async.version>1.2.3</ea-async.version>
<jcabi-maven-plugin.version>0.14.1</jcabi-maven-plugin.version>
<aspectjtools.version>1.9.1</aspectjtools.version>
<aspectjweaver.version>1.9.1</aspectjweaver.version>
<aspectjtools.version>1.9.20.1</aspectjtools.version>
<aspectjweaver.version>1.9.20.1</aspectjweaver.version>
</properties>
</project>
@@ -0,0 +1,4 @@
### Relevant Articles:
- [Why wait() Requires Synchronization?](https://www.baeldung.com/java-wait-necessary-synchronization)
- [Working with Exceptions in Java CompletableFuture](https://www.baeldung.com/java-exceptions-completablefuture)
@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>core-java-concurrency-advanced-5</artifactId>
<name>core-java-concurrency-advanced-5</name>
<packaging>jar</packaging>
<parent>
<groupId>com.baeldung.core-java-modules</groupId>
<artifactId>core-java-modules</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<build>
<finalName>core-java-concurrency-advanced-5</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
</configuration>
</plugin>
</plugins>
</build>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
</project>
@@ -0,0 +1,30 @@
package com.baeldung.callback.completablefuture;
import java.util.concurrent.CompletableFuture;
public class CompletableFutureCallbackExample {
public static void main(String[] args) {
CompletableFuture<String> completableFuture = new CompletableFuture<>();
Runnable runnable = downloadFile(completableFuture);
completableFuture.whenComplete((res, error) -> {
if (error != null) {
// handle the exception scenario
} else if (res != null) {
// send data to DB
}
});
new Thread(runnable).start();
}
private static Runnable downloadFile(CompletableFuture<String> completableFuture) {
return () -> {
try {
//logic to download file
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
completableFuture.complete("pic.jpg");
};
}
}
@@ -0,0 +1,42 @@
package com.baeldung.callback.listenablefuture;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
public class ListenableFutureCallbackExample {
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(1);
ListeningExecutorService pool = MoreExecutors.listeningDecorator(executorService);
ListenableFuture<String> listenableFuture = pool.submit(downloadFile());
Futures.addCallback(listenableFuture, new FutureCallback<String>() {
@Override
public void onSuccess(String result) {
// code to push fileName to DB
}
@Override
public void onFailure(Throwable throwable) {
// code to take appropriate action when there is an error
}
}, executorService);
}
private static Callable<String> downloadFile() {
return () -> {
// Mimicking the downloading of a file by adding a sleep call
Thread.sleep(5000);
return "pic.jpg";
};
}
}

Some files were not shown because too many files have changed in this diff Show More