Merge branch 'eugenp:master' into master

This commit is contained in:
Mladen Savic 2021-07-27 13:43:07 +02:00 committed by GitHub
commit 2242df334f
220 changed files with 6786 additions and 237 deletions

View File

@ -84,38 +84,6 @@
</executions>
</plugin>
<plugin>
<groupId>com.bazaarvoice.maven.plugins</groupId>
<artifactId>process-exec-maven-plugin</artifactId>
<version>${process-exec-maven-plugin.version}</version>
<executions>
<!--Start Blade -->
<execution>
<id>blade-process</id>
<phase>pre-integration-test</phase>
<goals>
<goal>start</goal>
</goals>
<configuration>
<name>Blade</name>
<waitForInterrupt>false</waitForInterrupt>
<arguments>
<argument>java</argument>
<argument>-jar</argument>
<argument>blade.jar</argument>
</arguments>
</configuration>
</execution>
<!--Stop all processes in reverse order -->
<execution>
<id>stop-all</id>
<phase>post-integration-test</phase>
<goals>
<goal>stop-all</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>${assembly.plugin.version}</version>

View File

@ -17,8 +17,8 @@ import java.nio.file.Paths;
import java.security.NoSuchAlgorithmException;
import java.time.Duration;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.jupiter.api.Disabled;
public class HttpRequestUnitTest {
@ -51,10 +51,10 @@ public class HttpRequestUnitTest {
/*
* This test will fail as soon as the given URL returns a HTTP 2 response.
* Therefore, let's leave it commented out.
* Therefore, let's leave it ignored.
* */
@Test
@Disabled
@Test
@Ignore
public void shouldFallbackToHttp1_1WhenWebsiteDoesNotUseHttp2() throws IOException, InterruptedException, URISyntaxException, NoSuchAlgorithmException {
HttpRequest request = HttpRequest.newBuilder()
.uri(new URI("https://postman-echo.com/get"))

View File

@ -0,0 +1,3 @@
### Relevant articles:
- [Collect a Java Stream to an Immutable Collection](https://www.baeldung.com/java-stream-immutable-collection)

View File

@ -0,0 +1,48 @@
<?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-16</artifactId>
<version>0.1.0-SNAPSHOT</version>
<name>core-java-16</name>
<packaging>jar</packaging>
<url>http://maven.apache.org</url>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-modules</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../../</relativePath>
</parent>
<dependencies>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>${assertj.version}</version>
<scope>test</scope>
</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>
</configuration>
</plugin>
</plugins>
</build>
<properties>
<maven.compiler.source.version>16</maven.compiler.source.version>
<maven.compiler.target.version>16</maven.compiler.target.version>
<assertj.version>3.6.1</assertj.version>
</properties>
</project>

View File

@ -0,0 +1,23 @@
package com.baeldung.streams;
import java.util.List;
import java.util.stream.Stream;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
public class StreamToImmutableUnitTest {
@Test
public void whenUsingStreamToList_thenReturnImmutableList() {
List<String> immutableList = Stream.of("a", "b", "c", "d")
.toList();
Assertions.assertThrows(UnsupportedOperationException.class, () -> {
immutableList.add("e");
});
}
}

View File

@ -10,3 +10,5 @@
- [Overview of Java Built-in Annotations](https://www.baeldung.com/java-default-annotations)
- [Creating a Custom Annotation in Java](https://www.baeldung.com/java-custom-annotation)
- [Efficient Word Frequency Calculator in Java](https://www.baeldung.com/java-word-frequency)
- [Why Missing Annotations Dont Cause ClassNotFoundException](https://www.baeldung.com/classnotfoundexception-missing-annotation)
- [Valid @SuppressWarnings Warning Names](https://www.baeldung.com/java-suppresswarnings-valid-names)

View File

@ -0,0 +1,46 @@
package com.baeldung.annotations;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
@SuppressWarnings({"serial", "unchecked"})
public class ClassWithSuppressWarningsNames implements Serializable {
// private static final long serialVersionUID = -1166032307853492833L;
@SuppressWarnings("unused")
public static void suppressBoxingWarning() {
int value = 5;
int unusedVar = 10; // no warning here
List<Integer> list = new ArrayList<>();
list.add(Integer.valueOf(value));
}
@SuppressWarnings("deprecated")
void suppressDeprecatedWarning() {
ClassWithSuppressWarningsNames cls = new ClassWithSuppressWarningsNames();
cls.deprecatedMethod(); // no warning here
}
@SuppressWarnings("fallthrough")
String suppressFallthroughWarning() {
int day = 5;
switch (day) {
case 5:
return "This is day 5";
// break; // no warning here
case 10:
return "This is day 10";
// break;
default:
return "This default day";
}
}
@Deprecated
String deprecatedMethod() {
return "deprecated method";
}
}

View File

@ -0,0 +1,8 @@
package com.baeldung.missingannotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface A {
}

View File

@ -0,0 +1,10 @@
package com.baeldung.missingannotation;
@A
@C(D.class)
public class B {
public static void main(String[] args) {
System.out.println("It worked");
}
}

View File

@ -0,0 +1,9 @@
package com.baeldung.missingannotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface C {
Class<?> value();
}

View File

@ -0,0 +1,4 @@
package com.baeldung.missingannotation;
public class D {
}

View File

@ -6,3 +6,4 @@
- [ArrayList vs. LinkedList vs. HashMap in Java](https://www.baeldung.com/java-arraylist-vs-linkedlist-vs-hashmap)
- [Java Deque vs. Stack](https://www.baeldung.com/java-deque-vs-stack)
- [Collection.toArray(new T[0]) or .toArray(new T[size])](https://www.baeldung.com/java-collection-toarray-methods)

View File

@ -2,3 +2,4 @@
- [Binary Semaphore vs Reentrant Lock](https://www.baeldung.com/java-binary-semaphore-vs-reentrant-lock)
- [Bad Practices With Synchronization](https://www.baeldung.com/java-synchronization-bad-practices)
- [Start Two Threads at the Exact Same Time in Java](https://www.baeldung.com/java-start-two-threads-at-same-time)

View File

@ -0,0 +1,86 @@
package com.baeldung.threadsstartatsametime;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.Phaser;
public class ThreadsStartAtSameTime {
public static void main(String[] args) throws BrokenBarrierException, InterruptedException {
usingCountDownLatch();
Thread.sleep(30);
usingCyclicBarrier();
Thread.sleep(30);
usingPhaser();
}
private static void usingCountDownLatch() throws InterruptedException {
System.out.println("===============================================");
System.out.println(" >>> Using CountDownLatch <<<<");
System.out.println("===============================================");
CountDownLatch latch = new CountDownLatch(1);
WorkerWithCountDownLatch worker1 = new WorkerWithCountDownLatch("Worker with latch 1", latch);
WorkerWithCountDownLatch worker2 = new WorkerWithCountDownLatch("Worker with latch 2", latch);
worker1.start();
worker2.start();
Thread.sleep(10);//simulation of some actual work
System.out.println("-----------------------------------------------");
System.out.println(" Now release the latch:");
System.out.println("-----------------------------------------------");
latch.countDown();
}
private static void usingCyclicBarrier() throws BrokenBarrierException, InterruptedException {
System.out.println("\n===============================================");
System.out.println(" >>> Using CyclicBarrier <<<<");
System.out.println("===============================================");
CyclicBarrier barrier = new CyclicBarrier(3);
WorkerWithCyclicBarrier worker1 = new WorkerWithCyclicBarrier("Worker with barrier 1", barrier);
WorkerWithCyclicBarrier worker2 = new WorkerWithCyclicBarrier("Worker with barrier 2", barrier);
worker1.start();
worker2.start();
Thread.sleep(10);//simulation of some actual work
System.out.println("-----------------------------------------------");
System.out.println(" Now open the barrier:");
System.out.println("-----------------------------------------------");
barrier.await();
}
private static void usingPhaser() throws InterruptedException {
System.out.println("\n===============================================");
System.out.println(" >>> Using Phaser <<<");
System.out.println("===============================================");
Phaser phaser = new Phaser();
phaser.register();
WorkerWithPhaser worker1 = new WorkerWithPhaser("Worker with phaser 1", phaser);
WorkerWithPhaser worker2 = new WorkerWithPhaser("Worker with phaser 2", phaser);
worker1.start();
worker2.start();
Thread.sleep(10);//simulation of some actual work
System.out.println("-----------------------------------------------");
System.out.println(" Now open the phaser barrier:");
System.out.println("-----------------------------------------------");
phaser.arriveAndAwaitAdvance();
}
}

View File

@ -0,0 +1,24 @@
package com.baeldung.threadsstartatsametime;
import java.time.Instant;
import java.util.concurrent.CountDownLatch;
public class WorkerWithCountDownLatch extends Thread {
private CountDownLatch latch;
public WorkerWithCountDownLatch(String name, CountDownLatch latch) {
this.latch = latch;
setName(name);
}
@Override public void run() {
try {
System.out.printf("[ %s ] created, blocked by the latch\n", getName());
latch.await();
System.out.printf("[ %s ] starts at: %s\n", getName(), Instant.now());
// do actual work here...
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

View File

@ -0,0 +1,25 @@
package com.baeldung.threadsstartatsametime;
import java.time.Instant;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
public class WorkerWithCyclicBarrier extends Thread {
private CyclicBarrier barrier;
public WorkerWithCyclicBarrier(String name, CyclicBarrier barrier) {
this.barrier = barrier;
this.setName(name);
}
@Override public void run() {
try {
System.out.printf("[ %s ] created, blocked by the barrier\n", getName());
barrier.await();
System.out.printf("[ %s ] starts at: %s\n", getName(), Instant.now());
// do actual work here...
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
}
}

View File

@ -0,0 +1,26 @@
package com.baeldung.threadsstartatsametime;
import java.time.Instant;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Phaser;
public class WorkerWithPhaser extends Thread {
private Phaser phaser;
public WorkerWithPhaser(String name, Phaser phaser) {
this.phaser = phaser;
phaser.register();
setName(name);
}
@Override public void run() {
try {
System.out.printf("[ %s ] created, blocked by the phaser\n", getName());
phaser.arriveAndAwaitAdvance();
System.out.printf("[ %s ] starts at: %s\n", getName(), Instant.now());
// do actual work here...
} catch (IllegalStateException e) {
e.printStackTrace();
}
}
}

View File

@ -13,4 +13,5 @@ This module contains articles about basic Java concurrency
- [Why are Local Variables Thread-Safe in Java](https://www.baeldung.com/java-local-variables-thread-safe)
- [How to Stop Execution After a Certain Time in Java](https://www.baeldung.com/java-stop-execution-after-certain-time)
- [How to Handle InterruptedException in Java](https://www.baeldung.com/java-interrupted-exception)
- [How to Get the Number of Threads in a Java Process](https://www.baeldung.com/java-get-number-of-threads)
- [[<-- Prev]](/core-java-modules/core-java-concurrency-basic)

View File

@ -36,6 +36,16 @@
<build>
<finalName>core-java-io-conversions-2</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${source.version}</source>
<target>${target.version}</target>
</configuration>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/resources</directory>
@ -45,6 +55,8 @@
</build>
<properties>
<source.version>11</source.version>
<target.version>11</target.version>
<json.version>20200518</json.version>
<opencsv.version>4.1</opencsv.version>
</properties>

View File

@ -21,11 +21,11 @@ import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.Scanner;
import java.util.UUID;
@ -70,6 +70,16 @@ public class JavaInputStreamToXUnitTest {
assertThat(text, equalTo(originalString));
}
@Test
public void givenUsingJava9_whenConvertingAnInputStreamToAString_thenCorrect() throws IOException {
final String originalString = randomAlphabetic(DEFAULT_SIZE);
final InputStream inputStream = new ByteArrayInputStream(originalString.getBytes());
final String text = new String(inputStream.readAllBytes(), StandardCharsets.UTF_8);
assertThat(text, equalTo(originalString));
}
@Test
public final void givenUsingJava7_whenConvertingAnInputStreamToAString_thenCorrect() throws IOException {
final String originalString = randomAlphabetic(DEFAULT_SIZE);
@ -155,15 +165,13 @@ public class JavaInputStreamToXUnitTest {
@Test
public final void whenConvertingToFile_thenCorrect() throws IOException {
final InputStream initialStream = new FileInputStream(new File("src/test/resources/sample.txt"));
final byte[] buffer = new byte[initialStream.available()];
initialStream.read(buffer);
final Path path = Paths.get("src/test/resources/sample.txt");
final byte[] buffer = java.nio.file.Files.readAllBytes(path);
final File targetFile = new File("src/test/resources/targetFile.tmp");
final OutputStream outStream = new FileOutputStream(targetFile);
outStream.write(buffer);
IOUtils.closeQuietly(initialStream);
IOUtils.closeQuietly(outStream);
}

View File

@ -7,3 +7,4 @@ This module contains articles about core features in the Java language
- [What are Compile-time Constants in Java?](https://www.baeldung.com/java-compile-time-constants)
- [Java Objects.hash() vs Objects.hashCode()](https://www.baeldung.com/java-objects-hash-vs-objects-hashcode)
- [Referencing a Method in Javadoc Comments](https://www.baeldung.com/java-method-in-javadoc)
- [Tiered Compilation in JVM](https://www.baeldung.com/jvm-tiered-compilation)

View File

@ -21,6 +21,16 @@
<artifactId>jmh-core</artifactId>
<version>${jmh-core.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-generator-annprocess</artifactId>

View File

@ -0,0 +1,21 @@
package com.baeldung.tieredcompilation;
public class Article {
private String name;
private String author;
public Article(String name, String author) {
this.name = name;
this.author = author;
}
public String getName() {
return name;
}
public String getAuthor() {
return author;
}
}

View File

@ -0,0 +1,7 @@
package com.baeldung.tieredcompilation;
public interface Formatter {
<T> String format(T object) throws Exception;
}

View File

@ -0,0 +1,15 @@
package com.baeldung.tieredcompilation;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.json.JsonMapper;
public class JsonFormatter implements Formatter {
private static final JsonMapper mapper = new JsonMapper();
@Override
public <T> String format(T object) throws JsonProcessingException {
return mapper.writeValueAsString(object);
}
}

View File

@ -0,0 +1,17 @@
package com.baeldung.tieredcompilation;
public class TieredCompilation {
public static void main(String[] args) throws Exception {
for (int i = 0; i < 1_000_000; i++) {
Formatter formatter;
if (i < 500_000) {
formatter = new JsonFormatter();
} else {
formatter = new XmlFormatter();
}
formatter.format(new Article("Tiered Compilation in JVM", "Baeldung"));
}
}
}

View File

@ -0,0 +1,15 @@
package com.baeldung.tieredcompilation;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
public class XmlFormatter implements Formatter {
private static final XmlMapper mapper = new XmlMapper();
@Override
public <T> String format(T object) throws JsonProcessingException {
return mapper.writeValueAsString(object);
}
}

View File

@ -5,4 +5,5 @@ This module contains article about constructors in Java
### Relevant Articles:
- [A Guide to Constructors in Java](https://www.baeldung.com/java-constructors)
- [Java Copy Constructor](https://www.baeldung.com/java-copy-constructor)
- [Cannot Reference “X” Before Supertype Constructor Has Been Called](https://www.baeldung.com/java-cannot-reference-x-before-supertype-constructor-error)
- [Cannot Reference “X” Before Supertype Constructor Has Been Called](https://www.baeldung.com/java-cannot-reference-x-before-supertype-constructor-error)
- [Private Constructors in Java](https://www.baeldung.com/java-private-constructors)

View File

@ -9,4 +9,5 @@ This module contains articles about modifiers in Java
- [The “final” Keyword in Java](https://www.baeldung.com/java-final)
- [A Guide to the Static Keyword in Java](https://www.baeldung.com/java-static)
- [Static and Default Methods in Interfaces in Java](https://www.baeldung.com/java-static-default-methods)
- [The strictfp Keyword in Java](https://www.baeldung.com/java-strictfp)
- [The strictfp Keyword in Java](https://www.baeldung.com/java-strictfp)
- [Static Classes Versus the Singleton Pattern in Java](https://www.baeldung.com/java-static-class-vs-singleton)

View File

@ -0,0 +1,30 @@
package com.baeldung.staticsingletondifference;
public class CachingSingleton implements SingletonInterface {
private CachingSingleton() {
}
private static class SingletonHolder {
public static final CachingSingleton instance = new CachingSingleton();
}
public static CachingSingleton getInstance() {
return SingletonHolder.instance;
}
@Override
public String describeMe() {
return "Caching Responsibilities";
}
@Override
public String passOnLocks(MyLock lock) {
return lock.takeLock(1);
}
@Override
public void increment() {
throw new UnsupportedOperationException("Not Supported Here");
}
}

View File

@ -0,0 +1,36 @@
package com.baeldung.staticsingletondifference;
public class FileSystemSingleton implements SingletonInterface{
private int filesWritten;
private FileSystemSingleton() {
}
private static class SingletonHolder {
public static final FileSystemSingleton instance = new FileSystemSingleton();
}
public static FileSystemSingleton getInstance() {
return SingletonHolder.instance;
}
@Override
public String describeMe() {
return "File System Responsibilities";
}
@Override
public String passOnLocks(MyLock lock) {
return lock.takeLock(2);
}
@Override
public void increment() {
this.filesWritten++;
}
public int getFilesWritten() {
return filesWritten;
}
}

View File

@ -0,0 +1,8 @@
package com.baeldung.staticsingletondifference;
public class MyLock {
protected String takeLock(int locks) {
return "Taken Specific Lock";
}
}

View File

@ -0,0 +1,49 @@
package com.baeldung.staticsingletondifference;
import java.io.ObjectStreamException;
import java.io.Serializable;
public class SerializableCloneableSingleton implements SingletonInterface, Serializable, Cloneable {
private static final long serialVersionUID = -1917003064592196223L;
private int state;
private SerializableCloneableSingleton() {
}
private static class SingletonHolder {
public static final SerializableCloneableSingleton instance = new SerializableCloneableSingleton();
}
public static SerializableCloneableSingleton getInstance() {
return SingletonHolder.instance;
}
@Override
public String describeMe() {
throw new UnsupportedOperationException("Not Supported Here");
}
@Override
public String passOnLocks(MyLock lock) {
throw new UnsupportedOperationException("Not Supported Here");
}
@Override
public void increment() {
this.state++;
}
public int getState() {
return state;
}
private Object readResolve() throws ObjectStreamException {
return SingletonHolder.instance;
}
public Object cloneObject() throws CloneNotSupportedException {
return this.clone();
}
}

View File

@ -0,0 +1,10 @@
package com.baeldung.staticsingletondifference;
public interface SingletonInterface {
public String describeMe();
public String passOnLocks(MyLock lock);
public void increment();
}

View File

@ -0,0 +1,20 @@
package com.baeldung.staticsingletondifference;
public class SingletonLock extends MyLock {
private SingletonLock() {
}
private static class SingletonHolder {
public static final SingletonLock instance = new SingletonLock();
}
public static SingletonLock getInstance() {
return SingletonHolder.instance;
}
@Override
public String takeLock(int locks) {
return "Taken Singleton Lock";
}
}

View File

@ -0,0 +1,8 @@
package com.baeldung.staticsingletondifference;
public class SubUtility extends SuperUtility {
public static String echoIt(String data) {
return data;
}
}

View File

@ -0,0 +1,8 @@
package com.baeldung.staticsingletondifference;
public class SuperUtility {
public static String echoIt(String data) {
return "SUPER";
}
}

View File

@ -0,0 +1,77 @@
package com.baeldung.staticsingletondifference;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.stream.IntStream;
import org.junit.Assert;
import org.junit.Test;
public class ForSingletonsUnitTest {
@Test
public void whenStaticUtilClassInheritance_thenOverridingFails() {
SuperUtility superUtility = new SubUtility();
Assert.assertNotEquals("ECHO", superUtility.echoIt("ECHO"));
Assert.assertEquals("SUPER", superUtility.echoIt("ECHO"));
}
@Test
public void whenSingletonDerivesBaseClass_thenRuntimePolymorphism() {
MyLock myLock = new MyLock();
Assert.assertEquals("Taken Specific Lock", myLock.takeLock(10));
myLock = SingletonLock.getInstance();
Assert.assertEquals("Taken Singleton Lock", myLock.takeLock(10));
}
@Test
public void whenSingletonImplementsInterface_thenRuntimePolymorphism() {
SingletonInterface singleton = FileSystemSingleton.getInstance();
Assert.assertEquals("File System Responsibilities", singleton.describeMe());
singleton = CachingSingleton.getInstance();
Assert.assertEquals("Caching Responsibilities", singleton.describeMe());
}
@Test
public void whenSingleton_thenPassAsArguments() {
SingletonInterface singleton = FileSystemSingleton.getInstance();
Assert.assertEquals("Taken Singleton Lock", singleton.passOnLocks(SingletonLock.getInstance()));
}
@Test
public void whenSingleton_thenAllowState() {
SingletonInterface singleton = FileSystemSingleton.getInstance();
IntStream.range(0, 5)
.forEach(i -> singleton.increment());
Assert.assertEquals(5, ((FileSystemSingleton) singleton).getFilesWritten());
}
@Test
public void whenSingleton_thenAllowSerializationDeserialization() {
SingletonInterface singleton = SerializableCloneableSingleton.getInstance();
singleton.increment();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
new ObjectOutputStream(baos).writeObject(singleton);
SerializableCloneableSingleton singletonNew = (SerializableCloneableSingleton) new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray())).readObject();
Assert.assertEquals(1, singletonNew.getState());
Assert.assertEquals(singleton.hashCode(), singletonNew.hashCode());
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
@Test
public void whenSingleton_thenAllowCloneable() {
SerializableCloneableSingleton singleton = SerializableCloneableSingleton.getInstance();
singleton.increment();
try {
Assert.assertEquals(2, ((SerializableCloneableSingleton) singleton.cloneObject()).getState());
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}

View File

@ -3,3 +3,5 @@
This module contains articles about Java operators
## Relevant Articles:
- [Logical vs Bitwise OR Operator](https://www.baeldung.com/java-logical-vs-bitwise-or-operator)

View File

@ -0,0 +1,120 @@
package com.baeldung.oroperators;
import org.junit.Test;
import java.util.Arrays;
import static org.junit.Assert.*;
public class BitmaskingUnitTest {
@Test
public void givenIntegerShouldPrintBinaryRepresentation() {
// given
int intRepresentation = 1094795523;
// expected
String stringRepresentation = getStringRepresentation(intRepresentation);
assertEquals(stringRepresentation, "01000001010000010100000100000011");
}
private String getStringRepresentation(int intRepresentation) {
String binaryString = Integer.toBinaryString(intRepresentation);
return padWithZeros(binaryString);
}
private String padWithZeros(String binaryString) {
return String.format("%" + 32 + "s", binaryString).replace(' ', '0');
}
@Test
public void givenBinaryRepresentationShouldReturnNumber() {
// given
String stringRepresentation = "01000001010000010100000100000011";
// expected
int intRepresentation = Integer.parseUnsignedInt(stringRepresentation, 2);
assertEquals(intRepresentation, 1094795523);
}
@Test
public void givenBinaryRepresentationShouldReturnCharacter() {
// given
String stringRepresentation = "010000010100000101000001";
// expected
assertEquals(binaryToText(stringRepresentation), "AAA");
}
@Test
public void givenIntAndPositionNumberShouldReturnBitValue() {
// given
String stringRepresentation = "010000010100000101000001000000011";
int intRepresentation = Integer.parseUnsignedInt(stringRepresentation, 2);
// when
boolean value1 = extractValueAtPosition(intRepresentation, 1);
boolean value2 = extractValueAtPosition(intRepresentation, 2);
boolean value3 = extractValueAtPosition(intRepresentation, 3);
// then
assertTrue(value1);
assertTrue(value2);
assertFalse(value3);
}
@Test
public void givenIntegerShouldExtractLastThreeBytes() {
// given
int intRepresentation = 1094795523;
// when
int lastThreeBites = intRepresentation >> 8;
// expected
String stringRepresentation = getStringRepresentation(lastThreeBites);
assertEquals(stringRepresentation, "00000000010000010100000101000001");
assertEquals(binaryToText(stringRepresentation), "AAA");
}
@Test
public void givenIntegerShouldApplyMask() {
// given
int intRepresentation = Integer.parseUnsignedInt("00000000010000010100000101000001", 2);
int mask = Integer.parseUnsignedInt("00000000000000000000000000000011", 2);
int mask2 = Integer.parseUnsignedInt("00000000000000000000000000000001", 2);
// when
int masked = intRepresentation & mask;
int masked2 = intRepresentation & mask2;
// expected
assertEquals(getStringRepresentation(masked), "00000000000000000000000000000001");
assertEquals(getStringRepresentation(masked2), "00000000000000000000000000000001");
assertNotEquals(masked, mask);
assertEquals(masked2, mask2);
assertFalse((intRepresentation & mask) == mask);
}
private boolean extractValueAtPosition(int intRepresentation, int position) {
String mask = getStringRepresentation(1 << (position - 1));
System.out.println(getStringRepresentation(intRepresentation));
System.out.println(mask);
System.out.println("-------------------------------- &");
System.out.println(getStringRepresentation((intRepresentation) & (1 << (position - 1))));
System.out.println();
return ((intRepresentation) & (1 << (position - 1))) != 0;
}
private static String binaryToText(String stringRepresentation) {
return Arrays.stream(stringRepresentation.split("(?<=\\G.{8})"))
.filter(eightBits -> !eightBits.equals("00000000"))
.map(eightBits -> (char)Integer.parseInt(eightBits, 2))
.collect(
StringBuilder::new,
StringBuilder::append,
StringBuilder::append
).toString();
}
}

View File

@ -47,6 +47,24 @@
<artifactId>javax.mail</artifactId>
<version>1.6.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.github.seancfoley/ipaddress -->
<dependency>
<groupId>com.github.seancfoley</groupId>
<artifactId>ipaddress</artifactId>
<version>${seancfoley.ipaddress.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.github.jgonian/commons-ip-math -->
<dependency>
<groupId>com.github.jgonian</groupId>
<artifactId>commons-ip-math</artifactId>
<version>${jgonian.commons-ip-math.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.googlecode.java-ipv6/java-ipv6 -->
<dependency>
<groupId>com.googlecode.java-ipv6</groupId>
<artifactId>java-ipv6</artifactId>
<version>${googlecode.ipv6.version}</version>
</dependency>
</dependencies>
<build>
@ -66,6 +84,9 @@
<jetty.embeded.version>9.4.31.v20200723</jetty.embeded.version>
<tomcat.embeded.version>10.0.0-M7</tomcat.embeded.version>
<assertj.version>3.11.1</assertj.version>
<seancfoley.ipaddress.version>5.3.3</seancfoley.ipaddress.version>
<jgonian.commons-ip-math.version>1.32</jgonian.commons-ip-math.version>
<googlecode.ipv6.version>0.17</googlecode.ipv6.version>
</properties>
</project>

View File

@ -0,0 +1,81 @@
package com.baeldung.ipingivenrange;
import java.net.InetAddress;
import java.net.UnknownHostException;
import inet.ipaddr.IPAddress;
import inet.ipaddr.IPAddressSeqRange;
import inet.ipaddr.IPAddressString;
import inet.ipaddr.AddressStringException;
import com.github.jgonian.ipmath.Ipv4;
import com.github.jgonian.ipmath.Ipv4Range;
import com.github.jgonian.ipmath.Ipv6;
import com.github.jgonian.ipmath.Ipv6Range;
import com.googlecode.ipv6.IPv6Address;
import com.googlecode.ipv6.IPv6AddressRange;
public class IPWithGivenRangeCheck {
// using IPAddress library
public static boolean checkIPIsInGivenRange(String inputIP, String rangeStartIP, String rangeEndIP) throws AddressStringException {
IPAddress startIPAddress = new IPAddressString(rangeStartIP).getAddress();
IPAddress endIPAddress = new IPAddressString(rangeEndIP).getAddress();
IPAddressSeqRange ipRange = startIPAddress.toSequentialRange(endIPAddress);
IPAddress inputIPAddress = new IPAddressString(inputIP).toAddress();
return ipRange.contains(inputIPAddress);
}
// using Commons IP Math library for IPv4
public static boolean checkIPv4IsInRange(String inputIP, String rangeStartIP, String rangeEndIP) {
Ipv4 startIPAddress = Ipv4.of(rangeStartIP);
Ipv4 endIPAddress = Ipv4.of(rangeEndIP);
Ipv4Range ipRange = Ipv4Range.from(startIPAddress)
.to(endIPAddress);
Ipv4 inputIPAddress = Ipv4.of(inputIP);
return ipRange.contains(inputIPAddress);
}
// using Commons IP Math library for IPv6
public static boolean checkIPv6IsInRange(String inputIP, String rangeStartIP, String rangeEndIP) {
Ipv6 startIPAddress = Ipv6.of(rangeStartIP);
Ipv6 endIPAddress = Ipv6.of(rangeEndIP);
Ipv6Range ipRange = Ipv6Range.from(startIPAddress)
.to(endIPAddress);
Ipv6 inputIPAddress = Ipv6.of(inputIP);
return ipRange.contains(inputIPAddress);
}
// checking IP is in range by converting it to an integer
public static boolean checkIPv4IsInRangeByConvertingToInt(String inputIP, String rangeStartIP, String rangeEndIP) throws UnknownHostException {
long startIPAddress = ipToLongInt(InetAddress.getByName(rangeStartIP));
long endIPAddress = ipToLongInt(InetAddress.getByName(rangeEndIP));
long inputIPAddress = ipToLongInt(InetAddress.getByName(inputIP));
return (inputIPAddress >= startIPAddress && inputIPAddress <= endIPAddress);
}
private static long ipToLongInt(InetAddress ipAddress) {
long resultIP = 0;
byte[] ipAddressOctets = ipAddress.getAddress();
for (byte octet : ipAddressOctets) {
resultIP <<= 8;
resultIP |= octet & 0xFF;
}
return resultIP;
}
// using Java IPv6 library (which internally uses two long integers to store ip address)
public static boolean checkIPv6IsInRangeByIPv6library(String inputIP, String rangeStartIP, String rangeEndIP) {
IPv6Address startIPAddress = IPv6Address.fromString(rangeStartIP);
IPv6Address endIPAddress = IPv6Address.fromString(rangeEndIP);
IPv6AddressRange ipRange = IPv6AddressRange.fromFirstAndLast(startIPAddress, endIPAddress);
IPv6Address inputIPAddress = IPv6Address.fromString(inputIP);
return ipRange.contains(inputIPAddress);
}
}

View File

@ -0,0 +1,58 @@
package com.baeldung.ipingivenrange;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;
import com.baeldung.ipingivenrange.IPWithGivenRangeCheck;
class IPWithGivenRangeCheckUnitTest {
@Test
void givenIPv4Addresses_whenIsInRange_thenReturnsTrue() throws Exception {
// test for IPAddress library
assertTrue(IPWithGivenRangeCheck.checkIPIsInGivenRange("192.220.3.0", "192.210.0.0", "192.255.0.0"));
// test for Common IP Math library
assertTrue(IPWithGivenRangeCheck.checkIPv4IsInRange("192.220.3.0", "192.210.0.0", "192.255.0.0"));
// test for IPv4 by converting it to an integer and checking if it falls under the specified range.
assertTrue(IPWithGivenRangeCheck.checkIPv4IsInRangeByConvertingToInt("192.220.3.0", "192.210.0.0", "192.255.0.0"));
}
@Test
void givenIPv4Addresses_whenIsNotInRange_thenReturnsFalse() throws Exception {
// test for IPAddress library
assertFalse(IPWithGivenRangeCheck.checkIPIsInGivenRange("192.200.0.0", "192.210.0.0", "192.255.0.0"));
// test for Common IP Math library
assertFalse(IPWithGivenRangeCheck.checkIPv4IsInRange("192.200.0.0", "192.210.0.0", "192.255.0.0"));
// test for IPv4 by converting it to an integer and checking if it falls under the specified range.
assertFalse(IPWithGivenRangeCheck.checkIPv4IsInRangeByConvertingToInt("192.200.0.0", "192.210.0.0", "192.255.0.0"));
}
@Test
void givenIPv6Addresses_whenIsInRange_thenReturnsTrue() throws Exception {
// test for IPAddress library
assertTrue(IPWithGivenRangeCheck.checkIPIsInGivenRange("2001:db8:85a3::8a03:a:b", "2001:db8:85a3::8a00:ff:ffff", "2001:db8:85a3::8a2e:370:7334"));
// test for Common IP Math library
assertTrue(IPWithGivenRangeCheck.checkIPv6IsInRange("2001:db8:85a3::8a03:a:b", "2001:db8:85a3::8a00:ff:ffff", "2001:db8:85a3::8a2e:370:7334"));
// test for Java IPv6 library
assertTrue(IPWithGivenRangeCheck.checkIPv6IsInRangeByIPv6library("fe80::226:2dff:fefa:dcba", "fe80::226:2dff:fefa:cd1f", "fe80::226:2dff:fefa:ffff"));
}
@Test
void givenIPv6Addresses_whenIsNotInRange_thenReturnsFalse() throws Exception {
// test for IPAddress library
assertFalse(IPWithGivenRangeCheck.checkIPIsInGivenRange("2002:db8:85a3::8a03:a:b", "2001:db8:85a3::8a00:ff:ffff", "2001:db8:85a3::8a2e:370:7334"));
// test for Common IP Math library
assertFalse(IPWithGivenRangeCheck.checkIPv6IsInRange("2002:db8:85a3::8a03:a:b", "2001:db8:85a3::8a00:ff:ffff", "2001:db8:85a3::8a2e:370:7334"));
// test for Java IPv6 library
assertFalse(IPWithGivenRangeCheck.checkIPv6IsInRangeByIPv6library("2002:db8:85a3::8a03:a:b", "2001:db8:85a3::8a00:ff:ffff", "2001:db8:85a3::8a2e:370:7334"));
}
}

View File

@ -1,3 +1,5 @@
### Relevant Articles:
- [Non-Capturing Regex Groups in Java](https://www.baeldung.com/java-regex-non-capturing-groups)
- [Lookahead and Lookbehind in Java Regex](https://www.baeldung.com/java-regex-lookahead-lookbehind)
- [Converting Camel Case and Title Case to Words in Java](https://www.baeldung.com/java-camel-case-title-case-to-words)

View File

@ -0,0 +1,27 @@
package com.baeldung.regex.camelcasetowords;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Convert a string in camelCase or TitleCase into a list of words
*/
public class CamelCaseToWords {
private static final Pattern WORD_FINDER = Pattern.compile("(([A-Z]?[a-z]+)|([A-Z]))");
/**
* Find the words in mixed case string like ThisIsText or HereIsSomeText
* @param text the text to parse
* @return the list of words to process
*/
public static List<String> findWordsInMixedCase(String text) {
Matcher matcher = WORD_FINDER.matcher(text);
List<String> words = new ArrayList<>();
while (matcher.find()) {
words.add(matcher.group(0));
}
return words;
}
}

View File

@ -0,0 +1,43 @@
package com.baeldung.regex.camelcasetowords;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class Recapitalize {
private static final Set<String> STOP_WORDS = Stream.of("a", "an", "the", "and",
"but", "for", "at", "by", "to", "or")
.collect(Collectors.toSet());
public static String sentenceCase(List<String> words) {
List<String> capitalized = new ArrayList<>();
for (int i = 0; i < words.size(); i++) {
String currentWord = words.get(i);
if (i == 0) {
capitalized.add(capitalizeFirst(currentWord));
} else {
capitalized.add(currentWord.toLowerCase());
}
}
return String.join(" ", capitalized) + ".";
}
public static String capitalizeMyTitle(List<String> words) {
List<String> capitalized = new ArrayList<>();
for (int i = 0; i < words.size(); i++) {
String currentWord = words.get(i);
if (i == 0 || !STOP_WORDS.contains(currentWord.toLowerCase())) {
capitalized.add(capitalizeFirst(currentWord));
} else {
capitalized.add(currentWord.toLowerCase());
}
}
return String.join(" ", capitalized);
}
private static String capitalizeFirst(String word) {
return word.substring(0, 1).toUpperCase() + word.substring(1).toLowerCase();
}
}

View File

@ -0,0 +1,39 @@
package com.baeldung.regex.camelcasetowords;
import org.junit.jupiter.api.Test;
import static com.baeldung.regex.camelcasetowords.CamelCaseToWords.findWordsInMixedCase;
import static org.assertj.core.api.Assertions.assertThat;
class CamelCaseToWordsUnitTest {
@Test
void givenPlainStringWithNonLetters_thenFindsWords() {
assertThat(findWordsInMixedCase("some words"))
.containsExactly("some", "words");
}
@Test
void givenWordsInCamelCase_thenFindsWords() {
assertThat(findWordsInMixedCase("thisIsCamelCaseText"))
.containsExactly("this", "Is", "Camel", "Case", "Text");
}
@Test
void givenWordsInTitleCase_thenFindsWords() {
assertThat(findWordsInMixedCase("ThisIsTitleCaseText"))
.containsExactly("This", "Is", "Title", "Case", "Text");
}
@Test
void givenWordsAcrossMultipleTexts_thenFindsWords() {
assertThat(findWordsInMixedCase("ThisIsTitleCaseText --- andSoIsThis"))
.containsExactly("This", "Is", "Title", "Case", "Text", "and", "So", "Is", "This");
}
@Test
void givenCamelCaseHasASingleLetterWord_thenItCanBeSplit() {
assertThat(findWordsInMixedCase("thisHasASingleLetterWord"))
.containsExactly("this", "Has", "A", "Single", "Letter", "Word");
}
}

View File

@ -0,0 +1,35 @@
package com.baeldung.regex.camelcasetowords;
import org.junit.jupiter.api.Test;
import java.util.Arrays;
import static com.baeldung.regex.camelcasetowords.Recapitalize.*;
import static org.assertj.core.api.Assertions.assertThat;
class RecapitalizeUnitTest {
@Test
void givenWords_thenCanComposeSentence() {
assertThat(sentenceCase(Arrays.asList("these", "Words", "Form", "A", "Sentence")))
.isEqualTo("These words form a sentence.");
}
@Test
void givenNonStopWords_thenTitleIsComposed() {
assertThat(capitalizeMyTitle(Arrays.asList("title", "words", "capitalize")))
.isEqualTo("Title Words Capitalize");
}
@Test
void givenStopWords_thenTitleHasThemInLowerCase() {
assertThat(capitalizeMyTitle(Arrays.asList("this", "is", "A", "title", "with", "a", "stop", "word", "or", "two")))
.isEqualTo("This Is a Title With a Stop Word or Two");
}
@Test
void givenStopWordIsFirstWord_thenTitleHasItCapitalized() {
assertThat(capitalizeMyTitle(Arrays.asList("a", "stop", "word", "first")))
.isEqualTo("A Stop Word First");
}
}

View File

@ -17,4 +17,5 @@ This module contains articles about core Java Security
- [InvalidAlgorithmParameterException: Wrong IV Length](https://www.baeldung.com/java-invalidalgorithmparameter-exception)
- [The java.security.egd JVM Option](https://www.baeldung.com/java-security-egd)
- [RSA in Java](https://www.baeldung.com/java-rsa)
- [3DES in Java](https://www.baeldung.com/java-3des)
- More articles: [[<-- prev]](/core-java-modules/core-java-security)

View File

@ -0,0 +1,90 @@
package com.baeldung.des;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
public class TripleDESUnitTest {
@Test
public void given3DesKey_whenEncryptAndDecryptString_thenCompareResults() throws Exception {
byte[] secretKey = "9mng65v8jf4lxn93nabf981m".getBytes();
byte[] iv = "a76nb5h9".getBytes();
String secretMessage = "Baeldung secret message";
SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey, "DESede");
IvParameterSpec ivSpec = new IvParameterSpec(iv);
Cipher encryptCipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
encryptCipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivSpec);
byte[] secretMessagesBytes = secretMessage.getBytes(StandardCharsets.UTF_8);
byte[] encryptedMessageBytes = encryptCipher.doFinal(secretMessagesBytes);
Cipher decryptCipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
decryptCipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivSpec);
byte[] decryptedMessageBytes = decryptCipher.doFinal(encryptedMessageBytes);
String decryptedMessage = new String(decryptedMessageBytes, StandardCharsets.UTF_8);
Assertions.assertEquals(secretMessage, decryptedMessage);
}
@Test
public void given3DesKey_whenEncryptAndDecryptFile_thenCompareResults() throws Exception {
byte[] secretKey = "9mng65v8jf4lxn93nabf981m".getBytes();
byte[] iv = "a76nb5h9".getBytes();
SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey, "DESede");
IvParameterSpec ivSpec = new IvParameterSpec(iv);
String originalContent = "some secret message";
Path tempFile = Files.createTempFile("temp", "txt");
writeString(tempFile, originalContent);
byte[] fileBytes = Files.readAllBytes(tempFile);
Cipher encryptCipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
encryptCipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivSpec);
byte[] encryptedFileBytes = encryptCipher.doFinal(fileBytes);
try (FileOutputStream stream = new FileOutputStream(tempFile.toFile())) {
stream.write(encryptedFileBytes);
}
encryptedFileBytes = Files.readAllBytes(tempFile);
Cipher decryptCipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
decryptCipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivSpec);
byte[] decryptedFileBytes = decryptCipher.doFinal(encryptedFileBytes);
try (FileOutputStream stream = new FileOutputStream(tempFile.toFile())) {
stream.write(decryptedFileBytes);
}
String fileContent = readString(tempFile);
Assertions.assertEquals(originalContent, fileContent);
}
private void writeString(Path path, String content) throws Exception {
try (BufferedWriter writer = Files.newBufferedWriter(path)) {
writer.write(content);
}
}
private String readString(Path path) throws Exception {
StringBuilder resultStringBuilder = new StringBuilder();
try (BufferedReader br = new BufferedReader(new FileReader(path.toFile()))) {
String line;
while ((line = br.readLine()) != null) {
resultStringBuilder.append(line);
}
}
return resultStringBuilder.toString();
}
}

View File

@ -0,0 +1,26 @@
*.class
0.*
#folders#
/target
/neoDb*
/data
/src/main/webapp/WEB-INF/classes
*/META-INF/*
.resourceCache
# Packaged files #
*.jar
*.war
*.ear
# Files generated by integration tests
*.txt
backup-pom.xml
/bin/
/temp
#IntelliJ specific
.idea/
*.iml

View File

@ -0,0 +1,3 @@
## Relevant Articles:
- [Count Occurrences Using Java groupingBy Collector](https://www.baeldung.com/java-groupingby-count)

View File

@ -0,0 +1,63 @@
<?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-streams-4</artifactId>
<version>0.1.0-SNAPSHOT</version>
<name>core-java-streams</name>
<packaging>jar</packaging>
<parent>
<groupId>com.baeldung.core-java-modules</groupId>
<artifactId>core-java-modules</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../</relativePath>
</parent>
<dependencies>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.junit</groupId>
<artifactId>junit-bom</artifactId>
<version>${junit-jupiter.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
<build>
<finalName>core-java-streams-4</finalName>
<resources>
<resource>
<directory>src/main</directory>
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
<configuration>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
<compilerArgument>-parameters</compilerArgument>
</configuration>
</plugin>
</plugins>
</build>
<properties>
<!-- testing -->
<maven-compiler-plugin.version>3.1</maven-compiler-plugin.version>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
</project>

View File

@ -0,0 +1,84 @@
package com.baeldung.streamcollectors;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.junit.Assert;
import org.junit.Test;
public class StreamGroupingByCollectorUnitTest {
@Test
public void givenListOfStrings_whenGroupingEqualStrings_thenUseCollectorsGroupingByToGroupEqualStringsAndCountOfOccurrences() {
List<String> list = new ArrayList<>(Arrays.asList("Foo", "Bar", "Bar", "Foo", "Bar"));
Map<String, Long> result = list.stream().collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
Assert.assertEquals(new Long(2), result.get("Foo"));
Assert.assertEquals(new Long(3), result.get("Bar"));
}
@Test
public void givenListOfStrings_whenGroupingEqualLengthStrings_thenUseCollectorsGroupingByConcurrentToGroupEqualLengthStringsAndCountOfOccurrences() {
List<String> list = new ArrayList<>(Arrays.asList("Adam", "Bill", "Jack", "Joe", "Ian"));
Map<Integer, Long> result = list.stream().collect(Collectors.groupingByConcurrent(String::length, Collectors.counting()));
Assert.assertEquals(new Long(2), result.get(3));
Assert.assertEquals(new Long(3), result.get(4));
}
@Test
public void givenListOfEmployees_whenGroupingDepartmentId_thenUseCollectorsGroupingByDepartmentIdAndCountNumberOfEmployeesWithinEveryDepartment() {
List<Employee> list = new ArrayList<>(Arrays.asList(new Employee(1, "Joe", 1), new Employee(2, "Josh", 1), new Employee(3, "Jamie", 2), new Employee(4, "Jim", 2), new Employee(5, "Jack", 2)));
Map<Integer, Long> result = list.stream().collect(Collectors.groupingBy(Employee::getDepartmentId, Collectors.counting()));
Assert.assertEquals(new Long(2), result.get(1));
Assert.assertEquals(new Long(3), result.get(2));
}
static class Employee {
Integer employeeId;
String employeeName;
Integer departmentId;
Employee(Integer employeeId, String employeeName, Integer departmentId) {
this.employeeId = employeeId;
this.employeeName = employeeName;
this.departmentId = departmentId;
}
public Integer getEmployeeId() {
return employeeId;
}
public void setEmployeeId(Integer employeeId) {
this.employeeId = employeeId;
}
public String getEmployeeName() {
return employeeName;
}
public void setEmployeeName(String employeeName) {
this.employeeName = employeeName;
}
public Integer getDepartmentId() {
return departmentId;
}
public void setDepartmentId(Integer departmentId) {
this.departmentId = departmentId;
}
}
}

View File

@ -7,4 +7,6 @@ This module contains articles about string conversions from/to another type.
- [Convert String to Byte Array and Reverse in Java](https://www.baeldung.com/java-string-to-byte-array)
- [Convert Character Array to String in Java](https://www.baeldung.com/java-char-array-to-string)
- [Converting String to BigDecimal in Java](https://www.baeldung.com/java-string-to-bigdecimal)
- [Converting String to BigInteger in Java](https://www.baeldung.com/java-string-to-biginteger)
- [Convert a String to Camel Case](https://www.baeldung.com/java-string-to-camel-case)
- More articles: [[<-- prev]](/core-java-string-conversions)

View File

@ -33,7 +33,39 @@
<version>${hamcrest.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.ibm.icu</groupId>
<artifactId>icu4j</artifactId>
<version>${icu.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${commons-lang3.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-text</artifactId>
<version>${commons-text.version}</version>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>${assertj.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<properties>
<icu.version>64.2</icu.version>
<assertj.version>3.12.2</assertj.version>
<commons-text.version>1.9</commons-text.version>
<guava.version>30.1.1-jre</guava.version>
</properties>
<build>
<finalName>core-java-string-conversions-2</finalName>

View File

@ -0,0 +1,109 @@
package com.baeldung.stringtocamelcase;
import com.google.common.base.CaseFormat;
import com.ibm.icu.lang.UCharacter;
import com.ibm.icu.text.BreakIterator;
import org.apache.commons.text.CaseUtils;
import org.apache.commons.text.WordUtils;
import java.util.Arrays;
import java.util.stream.Collectors;
public class StringToCamelCase {
public static String toCamelCaseByIteration(String text, char delimiter) {
if (text == null || text.isEmpty()) {
return text;
}
boolean shouldConvertNextCharToLower = true;
StringBuilder builder = new StringBuilder();
for (int i = 0; i < text.length(); i++) {
char currentChar = text.charAt(i);
if (currentChar == delimiter) {
shouldConvertNextCharToLower = false;
} else if (shouldConvertNextCharToLower) {
builder.append(Character.toLowerCase(currentChar));
} else {
builder.append(Character.toUpperCase(currentChar));
shouldConvertNextCharToLower = true;
}
}
return builder.toString();
}
public static String toCamelCaseBySplitting(String text, String delimiter) {
if (text == null || text.isEmpty()) {
return text;
}
String[] words = text.split(delimiter);
StringBuilder builder = new StringBuilder();
for (int i = 0, wordsLength = words.length; i < wordsLength; i++) {
String word = words[i];
if (i == 0) {
//Make the first word all lowercase
word = word.isEmpty() ? word : word.toLowerCase();
} else {
//Convert the first character to Uppercase and others to lowercase
// e.g sTRING =====> String
word = word.isEmpty() ? word : Character.toUpperCase(word.charAt(0)) + word.substring(1).toLowerCase();
}
builder.append(word);
}
return builder.toString();
}
public static String toCamelCaseBySplittingUsingStreams(String text, String delimiter) {
if (text == null || text.isEmpty()) {
return text;
}
String[] words = text.split(delimiter);
//Convert the first word to lowercase and then every
//other word to Title Case.
String firstWord = words[0].toLowerCase();
String otherWords = Arrays.stream(words, 1, words.length)
.filter(word -> !word.isEmpty())
.map(word -> Character.toUpperCase(word.charAt(0)) + word.substring(1).toLowerCase())
.collect(Collectors.joining(""));
return firstWord + otherWords;
}
public static String toCamelCaseByRegex(String text) {
StringBuilder builder = new StringBuilder();
String[] words = text.split("[\\W_]+");
for (int i = 0; i < words.length; i++) {
String word = words[i];
if (i == 0) {
word = word.isEmpty() ? word : word.toLowerCase();
} else {
word = word.isEmpty() ? word : Character.toUpperCase(word.charAt(0)) + word.substring(1).toLowerCase();
}
builder.append(word);
}
return builder.toString();
}
//Third-Party Libraries
public static String toCamelCaseUsingICU4J(String text, String delimiter) {
if (text == null || text.isEmpty()) {
return text;
}
text = UCharacter.toTitleCase(text, BreakIterator.getTitleInstance()).replaceAll(delimiter, "");
StringBuilder builder = new StringBuilder(text);
builder.setCharAt(0, Character.toLowerCase(text.charAt(0)));
return builder.toString();
}
public static String toCamelCaseUsingGuava(String text, String delimiter) {
String toUpperUnderscore = text.toUpperCase().replaceAll(delimiter, "_");
return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, toUpperUnderscore);
}
public static String toCamelCaseUsingApacheCommons(String text, char delimiter) {
text = WordUtils.capitalizeFully(text, delimiter).replaceAll(String.valueOf(delimiter), "");
StringBuilder builder = new StringBuilder(text);
builder.setCharAt(0, Character.toLowerCase(text.charAt(0)));
return builder.toString();
}
}

View File

@ -0,0 +1,44 @@
package com.baeldung.stringtobybiginteger;
import static org.junit.Assert.assertEquals;
import java.math.BigInteger;
import org.junit.Test;
public class StringToBigIntegerUnitTest {
@Test
public void whenGetStringWithOutRadix_thenOK() {
String inputString = "878";
BigInteger result = new BigInteger(inputString);
assertEquals("878", result.toString());
}
@Test
public void whenGetStringWithRadix_thenOK() {
String inputString = "290f98";
BigInteger result = new BigInteger(inputString, 16);
assertEquals("2690968", result.toString());
}
@Test(expected = NumberFormatException.class)
public void whenGetStringWithOutRadix_thenThrowError() {
String inputString = "290f98";
new BigInteger(inputString);
}
@Test(expected = NumberFormatException.class)
public void whenGetStringWithRadix_thenThrowError() {
String inputString = "290f98";
new BigInteger(inputString, 7);
}
@Test
public void whenGetStringUsingByte_thenOk() {
String inputString = "290f98";
byte[] inputStringBytes = inputString.getBytes();
BigInteger result = new BigInteger(inputStringBytes);
assertEquals("290f98", new String(result.toByteArray()));
}
}

View File

@ -0,0 +1,111 @@
package com.baeldung.stringtocamelcase;
import com.google.common.base.CaseFormat;
import org.apache.commons.text.CaseUtils;
import org.junit.Test;
import static com.baeldung.stringtocamelcase.StringToCamelCase.*;
import static org.assertj.core.api.Assertions.*;
public class StringToCamelCaseUnitTest {
@Test
public void givenStringWithWhiteSpaces_WhenToCamelCaseByIteration_ThenReturnCamelCase() {
assertThat(toCamelCaseByIteration("THIS STRING SHOULD BE IN CAMEL CASE", ' ')).isEqualTo("thisStringShouldBeInCamelCase");
}
@Test
public void givenStringWithUnderscores_WhenToCamelCaseByIteration_ThenReturnCamelCase() {
assertThat(toCamelCaseByIteration("THIS_STRING_SHOULD_BE_IN_CAMEL_CASE", '_')).isEqualTo("thisStringShouldBeInCamelCase");
}
@Test
public void givenStringWithWhiteSpaces_WhenToCamelCaseBySplitting_ThenReturnCamelCase() {
assertThat(toCamelCaseBySplitting("THIS STRING SHOULD BE IN CAMEL CASE", " ")).isEqualTo("thisStringShouldBeInCamelCase");
}
@Test
public void givenStringWithUnderscores_WhenToCamelCaseBySplitting_ThenReturnCamelCase() {
assertThat(toCamelCaseBySplitting("THIS_STRING_SHOULD_BE_IN_CAMEL_CASE", "_")).isEqualTo("thisStringShouldBeInCamelCase");
}
@Test
public void givenStringWithWhiteSpaces_WhenToCamelCaseBySplittingUsingStreams_ThenReturnCamelCase() {
assertThat(toCamelCaseBySplittingUsingStreams("THIS STRING SHOULD BE IN CAMEL CASE", " ")).isEqualTo("thisStringShouldBeInCamelCase");
}
@Test
public void givenStringWithUnderscores_WhenToCamelCaseBySplittingUsingStreams_ThenReturnCamelCase() {
assertThat(toCamelCaseBySplittingUsingStreams("THIS_STRING_SHOULD_BE_IN_CAMEL_CASE", "_")).isEqualTo("thisStringShouldBeInCamelCase");
}
@Test
public void givenStringWithWhiteSpaces_WhenToCamelCaseUsingApacheCommonsText_ThenReturnCamelCase() {
assertThat(CaseUtils.toCamelCase("THIS STRING SHOULD BE IN CAMEL CASE", false, ' '))
.isEqualTo("thisStringShouldBeInCamelCase");
}
@Test
public void givenStringWithUnderscores_WhenToCamelCaseUsingApacheCommonsText_ThenReturnCamelCase() {
assertThat(CaseUtils.toCamelCase("THIS_STRING_SHOULD_BE_IN_CAMEL_CASE", false, '_'))
.isEqualTo("thisStringShouldBeInCamelCase");
}
@Test
public void givenStringWithWhiteSpaces_WhenToCamelCaseUsingICU4J_ThenReturnCamelCase() {
assertThat(toCamelCaseUsingICU4J("THIS STRING SHOULD BE IN CAMEL CASE", " ")).isEqualTo("thisStringShouldBeInCamelCase");
}
@Test
public void givenStringWithUnderscores_WhenToCamelCaseUsingICU4J_ThenReturnCamelCase() {
assertThat(toCamelCaseUsingICU4J("THIS_STRING_SHOULD_BE_IN_CAMEL_CASE", "_")).isEqualTo("thisStringShouldBeInCamelCase");
}
@Test
public void givenStringWithWhiteSpaces_WhenToCamelCaseUsingGuava_ThenReturnCamelCase() {
assertThat(toCamelCaseUsingGuava("THIS STRING SHOULD BE IN CAMEL CASE", " ")).isEqualTo("thisStringShouldBeInCamelCase");
}
@Test
public void givenStringWithUnderscores_WhenToCamelCaseUsingGuava_ThenReturnCamelCase() {
assertThat(toCamelCaseUsingGuava("THIS_STRING_SHOULD_BE_IN_CAMEL_CASE", "_")).isEqualTo("thisStringShouldBeInCamelCase");
}
@Test
public void givenStringWithWhiteSpaces_WhenToCamelCaseUsingApacheCommons_ThenReturnCamelCase() {
assertThat(toCamelCaseUsingApacheCommons("THIS STRING SHOULD BE IN CAMEL CASE", ' ')).isEqualTo("thisStringShouldBeInCamelCase");
}
@Test
public void givenStringWithUnderscores_WhenToCamelCaseUsingApacheCommons_ThenReturnCamelCase() {
assertThat(toCamelCaseUsingApacheCommons("THIS_STRING_SHOULD_BE_IN_CAMEL_CASE", '_')).isEqualTo("thisStringShouldBeInCamelCase");
}
@Test
public void givenStringWithWhiteSpaces_WhenToCamelCaseByRegex_ThenReturnCamelCase() {
assertThat(toCamelCaseByRegex("THIS STRING SHOULD BE IN CAMEL CASE")).isEqualTo("thisStringShouldBeInCamelCase");
}
@Test
public void givenStringWithWhiteUnderscores_WhenToCamelCaseByRegex_ThenReturnCamelCase() {
assertThat(toCamelCaseByRegex("THIS_STRING_SHOULD_BE_IN_CAMEL_CASE")).isEqualTo("thisStringShouldBeInCamelCase");
}
@Test
public void givenRandomString_WhenToCamelCaseByRegex_ThenReturnCamelCase() {
assertThat(toCamelCaseByRegex("Please Turn this56738 to camel Case")).isEqualTo("pleaseTurnThis56738ToCamelCase");
}
@Test
public void givenRandomStringWithDifferentDelimiters_WhenToCamelCaseByRegex_ThenReturnCamelCase() {
assertThat(toCamelCaseByRegex("Please Turn this56738 to camel Case This should-be_in;camel-case")).isEqualTo("pleaseTurnThis56738ToCamelCaseThisShouldBeInCamelCase");
}
@Test
public void givenUppercaseWordWithUnderscores_WhenCaseFormatToLowerCamel_ThenReturnCamelCase() {
assertThat(CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, "THIS_STRING_SHOULD_BE_IN_CAMEL_CASE")).isEqualTo("thisStringShouldBeInCamelCase");
}
}

View File

@ -12,3 +12,4 @@
- [A Guide to the ResourceBundle](http://www.baeldung.com/java-resourcebundle)
- [Merging java.util.Properties Objects](https://www.baeldung.com/java-merging-properties)
- [Deserialization Vulnerabilities in Java](https://www.baeldung.com/java-deserialization-vulnerabilities)
- [Generating Alphanumeric UUID String in Java](https://www.baeldung.com/java-generate-alphanumeric-uuid)

View File

@ -176,8 +176,8 @@ public class UUIDGenerator {
byte[] hash = md.digest(bytes);
long msb = peekLong(hash, 0, ByteOrder.BIG_ENDIAN);
long lsb = peekLong(hash, 8, ByteOrder.BIG_ENDIAN);
long msb = getLeastAndMostSignificantBitsVersion5(hash, 0);
long lsb = getLeastAndMostSignificantBitsVersion5(hash, 8);
// Set the version field
msb &= ~(0xfL << 12);
msb |= ((long) 5) << 12;
@ -191,18 +191,11 @@ public class UUIDGenerator {
}
}
private static long peekLong(final byte[] src, final int offset, final ByteOrder order) {
private static long getLeastAndMostSignificantBitsVersion5(final byte[] src, final int offset) {
long ans = 0;
if (order == ByteOrder.BIG_ENDIAN) {
for (int i = offset; i < offset + 8; i += 1) {
ans <<= 8;
ans |= src[i] & 0xffL;
}
} else {
for (int i = offset + 7; i >= offset; i -= 1) {
ans <<= 8;
ans |= src[i] & 0xffL;
}
for (int i = offset + 7; i >= offset; i -= 1) {
ans <<= 8;
ans |= src[i] & 0xffL;
}
return ans;
}

View File

@ -63,11 +63,11 @@ class UUIDGeneratorUnitTest {
}
@Test
public void version_5_UUID_is_correctly_generated_for_domain_baeldung_com_without_namespace() throws UnsupportedEncodingException {
public void version_5_UUID_is_correctly_generated_for_domain_baeldung_name() {
UUID uuid = UUIDGenerator.generateType5UUID("baeldung.com");
assertEquals("a3c27ab0-2b46-55ef-b50e-0e5c57bfea94", uuid.toString());
assertEquals("efd5462b-b07a-52a3-94ea-bf575c0e0e75", uuid.toString());
assertEquals(5, uuid.version());
assertEquals(2, uuid.variant());
}

View File

@ -48,7 +48,6 @@
<module>core-java-concurrency-collections</module>
<module>core-java-concurrency-collections-2</module>
<module>core-java-console</module>
<!--<module>core-java-8-datetime</module> --> <!-- unit test case failure -->
<module>core-java-8-datetime-2</module>
<module>core-java-date-operations-2</module>
<module>core-java-8-datetime</module>
@ -63,7 +62,6 @@
<module>core-java-io-4</module>
<module>core-java-io-apis</module>
<module>core-java-io-conversions</module>
<module>core-java-io-conversions-2</module>
<module>core-java-jar</module>
<module>core-java-jndi</module>
<module>core-java-jvm</module>
@ -103,6 +101,7 @@
<module>core-java-streams</module>
<module>core-java-streams-2</module>
<module>core-java-streams-3</module>
<module>core-java-streams-4</module>
<module>core-java-string-algorithms</module>
<module>core-java-string-algorithms-2</module>
<module>core-java-string-algorithms-3</module>

View File

@ -0,0 +1,15 @@
package com.baeldung.lrucache;
import java.util.Optional;
public interface Cache<K, V> {
boolean put(K key, V value);
Optional<V> get(K key);
int size();
boolean isEmpty();
void clear();
}

View File

@ -0,0 +1,31 @@
package com.baeldung.lrucache;
/**
* Created by arash on 09.07.21.
*/
public class CacheElement<K,V> {
private K key;
private V value;
public CacheElement(K key, V value) {
this.value = value;
this.key = key;
}
public K getKey() {
return key;
}
public void setKey(K key) {
this.key = key;
}
public V getValue() {
return value;
}
public void setValue(V value) {
this.value = value;
}
}

View File

@ -0,0 +1,163 @@
package com.baeldung.lrucache;
import java.util.Collection;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class DoublyLinkedList<T> {
private DummyNode<T> dummyNode;
private LinkedListNode<T> head;
private LinkedListNode<T> tail;
private AtomicInteger size;
private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
public DoublyLinkedList() {
this.dummyNode = new DummyNode<T>(this);
clear();
}
public void clear() {
this.lock.writeLock().lock();
try {
head = dummyNode;
tail = dummyNode;
size = new AtomicInteger(0);
} finally {
this.lock.writeLock().unlock();
}
}
public int size() {
this.lock.readLock().lock();
try {
return size.get();
} finally {
this.lock.readLock().unlock();
}
}
public boolean isEmpty() {
this.lock.readLock().lock();
try {
return head.isEmpty();
} finally {
this.lock.readLock().unlock();
}
}
public boolean contains(T value) {
this.lock.readLock().lock();
try {
return search(value).hasElement();
} finally {
this.lock.readLock().unlock();
}
}
public LinkedListNode<T> search(T value) {
this.lock.readLock().lock();
try {
return head.search(value);
} finally {
this.lock.readLock().unlock();
}
}
public LinkedListNode<T> add(T value) {
this.lock.writeLock().lock();
try {
head = new Node<T>(value, head, this);
if (tail.isEmpty()) {
tail = head;
}
size.incrementAndGet();
return head;
} finally {
this.lock.writeLock().unlock();
}
}
public boolean addAll(Collection<T> values) {
this.lock.writeLock().lock();
try {
for (T value : values) {
if (add(value).isEmpty()) {
return false;
}
}
return true;
} finally {
this.lock.writeLock().unlock();
}
}
public LinkedListNode<T> remove(T value) {
this.lock.writeLock().lock();
try {
LinkedListNode<T> linkedListNode = head.search(value);
if (!linkedListNode.isEmpty()) {
if (linkedListNode == tail) {
tail = tail.getPrev();
}
if (linkedListNode == head) {
head = head.getNext();
}
linkedListNode.detach();
size.decrementAndGet();
}
return linkedListNode;
} finally {
this.lock.writeLock().unlock();
}
}
public LinkedListNode<T> removeTail() {
this.lock.writeLock().lock();
try {
LinkedListNode<T> oldTail = tail;
if (oldTail == head) {
tail = head = dummyNode;
} else {
tail = tail.getPrev();
oldTail.detach();
}
if (!oldTail.isEmpty()) {
size.decrementAndGet();
}
return oldTail;
} finally {
this.lock.writeLock().unlock();
}
}
public LinkedListNode<T> moveToFront(LinkedListNode<T> node) {
return node.isEmpty() ? dummyNode : updateAndMoveToFront(node, node.getElement());
}
public LinkedListNode<T> updateAndMoveToFront(LinkedListNode<T> node, T newValue) {
this.lock.writeLock().lock();
try {
if (node.isEmpty() || (this != (node.getListReference()))) {
return dummyNode;
}
detach(node);
add(newValue);
return head;
} finally {
this.lock.writeLock().unlock();
}
}
private void detach(LinkedListNode<T> node) {
if (node != tail) {
node.detach();
if (node == head) {
head = head.getNext();
}
size.decrementAndGet();
} else {
removeTail();
}
}
}

View File

@ -0,0 +1,62 @@
package com.baeldung.lrucache;
/**
* Created by arash on 09.07.21.
*/
public class DummyNode<T> implements LinkedListNode<T> {
private DoublyLinkedList<T> list;
public DummyNode(DoublyLinkedList<T> list) {
this.list = list;
}
@Override
public boolean hasElement() {
return false;
}
@Override
public boolean isEmpty() {
return true;
}
@Override
public T getElement() throws NullPointerException {
throw new NullPointerException();
}
@Override
public void detach() {
return;
}
@Override
public DoublyLinkedList<T> getListReference() {
return list;
}
@Override
public LinkedListNode<T> setPrev(LinkedListNode<T> next) {
return next;
}
@Override
public LinkedListNode<T> setNext(LinkedListNode<T> prev) {
return prev;
}
@Override
public LinkedListNode<T> getPrev() {
return this;
}
@Override
public LinkedListNode<T> getNext() {
return this;
}
@Override
public LinkedListNode<T> search(T value) {
return this;
}
}

View File

@ -0,0 +1,100 @@
package com.baeldung.lrucache;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class LRUCache<K, V> implements Cache<K, V> {
private int size;
private Map<K, LinkedListNode<CacheElement<K, V>>> linkedListNodeMap;
private DoublyLinkedList<CacheElement<K, V>> doublyLinkedList;
private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
public LRUCache(int size) {
this.size = size;
this.linkedListNodeMap = new ConcurrentHashMap<>(size);
this.doublyLinkedList = new DoublyLinkedList<>();
}
@Override
public boolean put(K key, V value) {
this.lock.writeLock().lock();
try {
CacheElement<K, V> item = new CacheElement<K, V>(key, value);
LinkedListNode<CacheElement<K, V>> newNode;
if (this.linkedListNodeMap.containsKey(key)) {
LinkedListNode<CacheElement<K, V>> node = this.linkedListNodeMap.get(key);
newNode = doublyLinkedList.updateAndMoveToFront(node, item);
} else {
if (this.size() >= this.size) {
this.evictElement();
}
newNode = this.doublyLinkedList.add(item);
}
if (newNode.isEmpty()) {
return false;
}
this.linkedListNodeMap.put(key, newNode);
return true;
} finally {
this.lock.writeLock().unlock();
}
}
@Override
public Optional<V> get(K key) {
this.lock.readLock().lock();
try {
LinkedListNode<CacheElement<K, V>> linkedListNode = this.linkedListNodeMap.get(key);
if (linkedListNode != null && !linkedListNode.isEmpty()) {
linkedListNodeMap.put(key, this.doublyLinkedList.moveToFront(linkedListNode));
return Optional.of(linkedListNode.getElement().getValue());
}
return Optional.empty();
} finally {
this.lock.readLock().unlock();
}
}
@Override
public int size() {
this.lock.readLock().lock();
try {
return doublyLinkedList.size();
} finally {
this.lock.readLock().unlock();
}
}
@Override
public boolean isEmpty() {
return size() == 0;
}
@Override
public void clear() {
this.lock.writeLock().lock();
try {
linkedListNodeMap.clear();
doublyLinkedList.clear();
} finally {
this.lock.writeLock().unlock();
}
}
private boolean evictElement() {
this.lock.writeLock().lock();
try {
LinkedListNode<CacheElement<K, V>> linkedListNode = doublyLinkedList.removeTail();
if (linkedListNode.isEmpty()) {
return false;
}
linkedListNodeMap.remove(linkedListNode.getElement().getKey());
return true;
} finally {
this.lock.writeLock().unlock();
}
}
}

View File

@ -0,0 +1,23 @@
package com.baeldung.lrucache;
public interface LinkedListNode<V> {
boolean hasElement();
boolean isEmpty();
V getElement() throws NullPointerException;
void detach();
DoublyLinkedList<V> getListReference();
LinkedListNode<V> setPrev(LinkedListNode<V> prev);
LinkedListNode<V> setNext(LinkedListNode<V> next);
LinkedListNode<V> getPrev();
LinkedListNode<V> getNext();
LinkedListNode<V> search(V value);
}

View File

@ -0,0 +1,71 @@
package com.baeldung.lrucache;
/**
* Created by arash on 09.07.21.
*/
public class Node<T> implements LinkedListNode<T> {
private T value;
private DoublyLinkedList<T> list;
private LinkedListNode next;
private LinkedListNode prev;
public Node(T value, LinkedListNode<T> next, DoublyLinkedList<T> list) {
this.value = value;
this.next = next;
this.setPrev(next.getPrev());
this.prev.setNext(this);
this.next.setPrev(this);
this.list = list;
}
@Override
public boolean hasElement() {
return true;
}
@Override
public boolean isEmpty() {
return false;
}
public T getElement() {
return value;
}
public void detach() {
this.prev.setNext(this.getNext());
this.next.setPrev(this.getPrev());
}
@Override
public DoublyLinkedList<T> getListReference() {
return this.list;
}
@Override
public LinkedListNode<T> setPrev(LinkedListNode<T> prev) {
this.prev = prev;
return this;
}
@Override
public LinkedListNode<T> setNext(LinkedListNode<T> next) {
this.next = next;
return this;
}
@Override
public LinkedListNode<T> getPrev() {
return this.prev;
}
@Override
public LinkedListNode<T> getNext() {
return this.next;
}
@Override
public LinkedListNode<T> search(T value) {
return this.getElement() == value ? this : this.getNext().search(value);
}
}

View File

@ -0,0 +1,51 @@
package com.baeldung.lrucache;
import org.junit.Test;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.IntStream;
import static org.junit.Assert.*;
public class LRUCacheUnitTest {
@Test
public void addSomeDataToCache_WhenGetData_ThenIsEqualWithCacheElement() {
LRUCache<String, String> lruCache = new LRUCache<>(3);
lruCache.put("1", "test1");
lruCache.put("2", "test2");
lruCache.put("3", "test3");
assertEquals("test1", lruCache.get("1").get());
assertEquals("test2", lruCache.get("2").get());
assertEquals("test3", lruCache.get("3").get());
}
@Test
public void addDataToCacheToTheNumberOfSize_WhenAddOneMoreData_ThenLeastRecentlyDataWillEvict() {
LRUCache<String, String> lruCache = new LRUCache<>(3);
lruCache.put("1", "test1");
lruCache.put("2", "test2");
lruCache.put("3", "test3");
lruCache.put("4", "test4");
assertFalse(lruCache.get("1").isPresent());
}
@Test
public void runMultiThreadTask_WhenPutDataInConcurrentToCache_ThenNoDataLost() throws Exception {
final int size = 50;
final ExecutorService executorService = Executors.newFixedThreadPool(5);
Cache<Integer, String> cache = new LRUCache<>(size);
CountDownLatch countDownLatch = new CountDownLatch(size);
try {
IntStream.range(0, size).<Runnable>mapToObj(key -> () -> {
cache.put(key, "value" + key);
countDownLatch.countDown();
}).forEach(executorService::submit);
countDownLatch.await();
} finally {
executorService.shutdown();
}
assertEquals(cache.size(), size);
IntStream.range(0, size).forEach(i -> assertEquals("value" + i, cache.get(i).get()));
}
}

View File

@ -0,0 +1,3 @@
## Relevant Articles:
- [Guavas Futures and ListenableFuture](https://www.baeldung.com/guava-futures-listenablefuture)

View File

@ -0,0 +1,14 @@
<?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">
<parent>
<artifactId>guava-modules</artifactId>
<groupId>com.baeldung</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>guava-concurrency</artifactId>
</project>

View File

@ -0,0 +1,105 @@
package com.baeldung.guava.future;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import com.baeldung.guava.future.exception.ListenableFutureException;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListenableFutureTask;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
public class ListenableFutureService {
private final ListeningExecutorService lExecService;
public ListenableFutureService() {
this.lExecService = MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor());
}
public ListenableFutureService(ListeningExecutorService lExecService) {
this.lExecService = lExecService;
}
public ListenableFuture<String> fetchConfig(String configKey) {
return lExecService.submit(() -> {
TimeUnit.MILLISECONDS.sleep(500);
return String.format("%s.%d", configKey, new Random().nextInt(Integer.MAX_VALUE));
});
}
public FutureTask<String> fetchConfigTask(String configKey) {
return new FutureTask<>(() -> {
TimeUnit.MILLISECONDS.sleep(500);
return String.format("%s.%d", configKey, new Random().nextInt(Integer.MAX_VALUE));
});
}
public ListenableFutureTask<String> fetchConfigListenableTask(String configKey) {
return ListenableFutureTask.create(() -> {
TimeUnit.MILLISECONDS.sleep(500);
return String.format("%s.%d", configKey, new Random().nextInt(Integer.MAX_VALUE));
});
}
public ListenableFuture<Integer> succeedingTask() {
return Futures.immediateFuture(new Random().nextInt(Integer.MAX_VALUE));
}
public <T> ListenableFuture<T> failingTask() {
return Futures.immediateFailedFuture(new ListenableFutureException());
}
public ListenableFuture<Integer> getCartId() {
return lExecService.submit(() -> {
TimeUnit.MILLISECONDS.sleep(500);
return new Random().nextInt(Integer.MAX_VALUE);
});
}
public ListenableFuture<String> getCustomerName() {
String[] names = new String[] { "Mark", "Jane", "June" };
return lExecService.submit(() -> {
TimeUnit.MILLISECONDS.sleep(500);
return names[new Random().nextInt(names.length)];
});
}
public ListenableFuture<List<String>> getCartItems() {
String[] items = new String[] { "Apple", "Orange", "Mango", "Pineapple" };
return lExecService.submit(() -> {
TimeUnit.MILLISECONDS.sleep(500);
int noOfItems = new Random().nextInt(items.length);
if (noOfItems == 0) ++noOfItems;
return Arrays.stream(items, 0, noOfItems).collect(Collectors.toList());
});
}
public ListenableFuture<String> generateUsername(String firstName) {
return lExecService.submit(() -> {
TimeUnit.MILLISECONDS.sleep(500);
return firstName.replaceAll("[^a-zA-Z]+","")
.concat("@service.com");
});
}
public ListenableFuture<String> generatePassword(String username) {
return lExecService.submit(() -> {
TimeUnit.MILLISECONDS.sleep(500);
if (username.contains("@")) {
String[] parts = username.split("@");
return parts[0] + "123@" + parts[1];
} else {
return username + "123";
}
});
}
}

View File

@ -0,0 +1,4 @@
package com.baeldung.guava.future.exception;
public class ListenableFutureException extends Exception {
}

View File

@ -0,0 +1,277 @@
package com.baeldung.guava.future;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.function.UnaryOperator;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.junit.jupiter.api.Test;
import com.baeldung.guava.future.exception.ListenableFutureException;
import com.google.common.base.Function;
import com.google.common.util.concurrent.AsyncCallable;
import com.google.common.util.concurrent.AsyncFunction;
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 ListenableFutureComplexUnitTest {
@Test
public void givenAllSucceedingTasks_whenAllAsList_thenAllSuccess() {
final ListeningExecutorService listeningExecService = MoreExecutors.newDirectExecutorService();
final ListenableFutureService service = new ListenableFutureService(listeningExecService);
ListenableFuture<String> task1 = service.fetchConfig("config.0");
ListenableFuture<String> task2 = service.fetchConfig("config.1");
ListenableFuture<String> task3 = service.fetchConfig("config.2");
ListenableFuture<List<String>> configsTask = Futures.allAsList(task1, task2, task3);
Futures.addCallback(configsTask, new FutureCallback<List<String>>() {
@Override
public void onSuccess(@Nullable List<String> configResults) {
assertNotNull(configResults);
assertEquals(3, configResults.size());
for (int i = 0; i < 3; i++) {
assertTrue(configResults.get(i)
.contains("config." + i));
}
}
@Override
public void onFailure(Throwable t) {
fail("Unexpected failure detected", t);
}
}, listeningExecService);
}
@Test
public void givenOneFailingTask_whenAllAsList_thenFailure() {
final ListeningExecutorService listeningExecService = MoreExecutors.newDirectExecutorService();
final ListenableFutureService service = new ListenableFutureService(listeningExecService);
ListenableFuture<String> task1 = service.fetchConfig("config.0");
ListenableFuture<String> task2 = service.failingTask();
ListenableFuture<String> task3 = service.fetchConfig("config.2");
ListenableFuture<List<String>> configsTask = Futures.allAsList(task1, task2, task3);
Futures.addCallback(configsTask, new FutureCallback<List<String>>() {
@Override
public void onSuccess(@Nullable List<String> configResults) {
fail("Expected a failed future");
}
@Override
public void onFailure(Throwable t) {
assertTrue(t instanceof ListenableFutureException);
}
}, listeningExecService);
}
@Test
public void givenOneFailingTask_whenSuccessfulAsList_thenSomeSuccess() {
final ListeningExecutorService listeningExecService = MoreExecutors.newDirectExecutorService();
final ListenableFutureService service = new ListenableFutureService(listeningExecService);
ListenableFuture<String> task1 = service.fetchConfig("config.0");
ListenableFuture<String> task2 = service.failingTask();
ListenableFuture<String> task3 = service.fetchConfig("config.2");
ListenableFuture<List<String>> configsTask = Futures.successfulAsList(task1, task2, task3);
Futures.addCallback(configsTask, new FutureCallback<List<String>>() {
@Override
public void onSuccess(@Nullable List<String> configResults) {
assertNotNull(configResults);
assertTrue(configResults.get(0).contains("config.0"));
assertNull(configResults.get(1));
assertTrue(configResults.get(2).contains("config.2"));
}
@Override
public void onFailure(Throwable t) {
fail("Unexpected failure detected", t);
}
}, listeningExecService);
}
@Test
public void givenAllSucceedingTasks_whenAllSucceed_thenSuccess() {
ListeningExecutorService listeningExecService = MoreExecutors.newDirectExecutorService();
ListenableFutureService service = new ListenableFutureService(listeningExecService);
ListenableFuture<Integer> cartIdTask = service.getCartId();
ListenableFuture<String> customerNameTask = service.getCustomerName();
ListenableFuture<List<String>> cartItemsTask = service.getCartItems();
ListenableFuture<CartInfo> cartInfoTask = Futures.whenAllSucceed(cartIdTask, customerNameTask, cartItemsTask)
.call(() -> {
int cartId = Futures.getDone(cartIdTask);
String customerName = Futures.getDone(customerNameTask);
List<String> cartItems = Futures.getDone(cartItemsTask);
return new CartInfo(cartId, customerName, cartItems);
}, listeningExecService);
Futures.addCallback(cartInfoTask, new FutureCallback<CartInfo>() {
@Override
public void onSuccess(@Nullable CartInfo result) {
assertNotNull(result);
assertTrue(result.cartId >= 0);
assertFalse(result.customerName.isEmpty());
assertFalse(result.cartItems.isEmpty());
}
@Override
public void onFailure(Throwable t) {
fail("Unexpected failure detected", t);
}
}, listeningExecService);
}
@Test
public void givenAllSucceedingTasks_whenAllComplete_thenSomeSuccess() {
ListeningExecutorService listeningExecService = MoreExecutors.newDirectExecutorService();
ListenableFutureService service = new ListenableFutureService(listeningExecService);
ListenableFuture<Integer> cartIdTask = service.getCartId();
ListenableFuture<String> customerNameTask = service.failingTask();
ListenableFuture<List<String>> cartItemsTask = service.getCartItems();
ListenableFuture<CartInfo> cartInfoTask = Futures.whenAllComplete(cartIdTask, customerNameTask, cartItemsTask)
.call(() -> {
Integer cartId = getOrNull(cartIdTask);
String customerName = getOrNull(customerNameTask);
List<String> cartItems = getOrNull(cartItemsTask);
return new CartInfo(cartId, customerName, cartItems);
}, listeningExecService);
Futures.addCallback(cartInfoTask, new FutureCallback<CartInfo>() {
@Override
public void onSuccess(@Nullable CartInfo result) {
assertNotNull(result);
assertTrue(result.cartId >= 0);
assertNull(result.customerName);
assertFalse(result.cartItems.isEmpty());
}
@Override
public void onFailure(Throwable t) {
fail("Unexpected failure detected", t);
}
}, listeningExecService);
}
@Test
public void whenTransform_thenTransformSuccess() {
ListeningExecutorService listenExecService = MoreExecutors.newDirectExecutorService();
ListenableFutureService service = new ListenableFutureService(listenExecService);
ListenableFuture<List<String>> cartItemsTask = service.getCartItems();
Function<List<String>, Integer> itemCountFunc = cartItems -> {
assertNotNull(cartItems);
return cartItems.size();
};
ListenableFuture<Integer> itemCountTask = Futures.transform(cartItemsTask, itemCountFunc, listenExecService);
Futures.addCallback(itemCountTask, new FutureCallback<Integer>() {
@Override
public void onSuccess(@Nullable Integer cartItemCount) {
assertNotNull(cartItemCount);
assertTrue(cartItemCount > 0);
}
@Override
public void onFailure(Throwable t) {
fail("Unexpected failure detected", t);
}
}, listenExecService);
}
@Test
public void whenSubmitAsync_thenSuccess() {
ListeningExecutorService executor = MoreExecutors.newDirectExecutorService();
ListenableFutureService service = new ListenableFutureService(executor);
AsyncCallable<String> asyncConfigTask = () -> {
ListenableFuture<String> configTask = service.fetchConfig("config.a");
TimeUnit.MILLISECONDS.sleep(500); //some long running task
return configTask;
};
ListenableFuture<String> configTask = Futures.submitAsync(asyncConfigTask, executor);
Futures.addCallback(configTask, new FutureCallback<String>() {
@Override
public void onSuccess(@Nullable String result) {
assertNotNull(result);
assertTrue(result.contains("config.a"));
}
@Override
public void onFailure(Throwable t) {
fail("Unexpected failure detected", t);
}
}, executor);
}
@Test
public void whenAsyncTransform_thenSuccess() {
ListeningExecutorService executor = MoreExecutors.newDirectExecutorService();
ListenableFutureService service = new ListenableFutureService(executor);
ListenableFuture<String> usernameTask = service.generateUsername("john");
AsyncFunction<String, String> passwordFunc = username -> {
ListenableFuture<String> generatePasswordTask = service.generatePassword(username);
TimeUnit.MILLISECONDS.sleep(500); // some long running task
return generatePasswordTask;
};
ListenableFuture<String> passwordTask = Futures.transformAsync(usernameTask, passwordFunc, executor);
Futures.addCallback(passwordTask, new FutureCallback<String>() {
@Override
public void onSuccess(@Nullable String password) {
assertNotNull(password);
assertTrue(password.contains("john"));
assertTrue(password.contains("@"));
}
@Override
public void onFailure(Throwable t) {
fail("Unexpected failure detected", t);
}
}, executor);
}
private static <T> T getOrNull(ListenableFuture<T> future) {
try {
return Futures.getDone(future);
} catch (ExecutionException e) {
return null;
}
}
static class CartInfo {
Integer cartId;
String customerName;
List<String> cartItems;
public CartInfo(Integer cartId, String customerName, List<String> cartItems) {
this.cartId = cartId;
this.customerName = customerName;
this.cartItems = cartItems;
}
}
}

View File

@ -0,0 +1,122 @@
package com.baeldung.guava.future;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
import org.junit.jupiter.api.Test;
import com.baeldung.guava.future.exception.ListenableFutureException;
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.ListenableFutureTask;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
public class ListenableFutureSimpleUnitTest {
@Test
public void whenSubmitToListeningExecutor_thenSuccess() throws ExecutionException, InterruptedException {
ExecutorService execService = Executors.newSingleThreadExecutor();
ListeningExecutorService listeningExecService = MoreExecutors.listeningDecorator(execService);
ListenableFuture<Integer> asyncTask = listeningExecService.submit(() -> {
TimeUnit.MILLISECONDS.sleep(500); // long running task
return 5;
});
assertEquals(5, asyncTask.get());
}
@Test
public void
givenJavaExecutor_whenSubmitListeningTask_thenSuccess() throws ExecutionException, InterruptedException {
Executor executor = Executors.newSingleThreadExecutor();
ListenableFutureService service = new ListenableFutureService();
FutureTask<String> configFuture = service.fetchConfigTask("future.value");
executor.execute(configFuture);
assertTrue(configFuture.get().contains("future.value"));
ListenableFutureTask<String> configListenableFuture =
service.fetchConfigListenableTask("listenable.value");
executor.execute(configListenableFuture);
assertTrue(configListenableFuture.get().contains("listenable.value"));
}
@Test
public void givenNonFailingTask_whenCallbackListen_thenSuccess() {
Executor listeningExecutor = MoreExecutors.directExecutor();
ListenableFuture<Integer> succeedingTask = new ListenableFutureService().succeedingTask();
Futures.addCallback(succeedingTask, new FutureCallback<Integer>() {
@Override
public void onSuccess(Integer result) {
assertNotNull(result);
assertTrue(result >= 0);
}
@Override
public void onFailure(Throwable t) {
fail("Succeeding task cannot failed", t);
}
}, listeningExecutor);
}
@Test
public void givenFailingTask_whenCallbackListen_thenThrows() {
Executor listeningExecutor = MoreExecutors.directExecutor();
ListenableFuture<Integer> failingTask = new ListenableFutureService().failingTask();
Futures.addCallback(failingTask, new FutureCallback<Integer>() {
@Override
public void onSuccess(Integer result) {
fail("Failing task cannot succeed");
}
@Override
public void onFailure(Throwable t) {
assertTrue(t instanceof ListenableFutureException);
}
}, listeningExecutor);
}
@Test
public void givenNonFailingTask_whenDirectListen_thenListenerExecutes() {
Executor listeningExecutor = MoreExecutors.directExecutor();
int nextTask = 1;
Set<Integer> runningTasks = ConcurrentHashMap.newKeySet();
runningTasks.add(nextTask);
ListenableFuture<Integer> nonFailingTask = new ListenableFutureService().succeedingTask();
nonFailingTask.addListener(() -> runningTasks.remove(nextTask), listeningExecutor);
assertTrue(runningTasks.isEmpty());
}
@Test
public void givenFailingTask_whenDirectListen_thenListenerExecutes() {
final Executor listeningExecutor = MoreExecutors.directExecutor();
int nextTask = 1;
Set<Integer> runningTasks = ConcurrentHashMap.newKeySet();
runningTasks.add(nextTask);
final ListenableFuture<Integer> failingTask = new ListenableFutureService().failingTask();
failingTask.addListener(() -> runningTasks.remove(nextTask),listeningExecutor);
assertTrue(runningTasks.isEmpty());
}
}

View File

@ -24,6 +24,7 @@
<module>guava-collections-list</module>
<module>guava-collections-map</module>
<module>guava-collections-set</module>
<module>guava-concurrency</module>
<module>guava-io</module>
</modules>

View File

@ -11,4 +11,5 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring
- [How to Set TLS Version in Apache HttpClient](https://www.baeldung.com/apache-httpclient-tls)
- [Reading an HTTP Response Body as a String in Java](https://www.baeldung.com/java-http-response-body-as-string)
- [How To Get Cookies From the Apache HttpClient Response](https://www.baeldung.com/java-apache-httpclient-cookies)
- [Enabling Logging for Apache HttpClient](https://www.baeldung.com/java-httpclient-enable-logging)
- More articles: [[<-- prev]](../httpclient)

View File

@ -26,6 +26,11 @@
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents.client5</groupId>
<artifactId>httpclient5</artifactId>
<version>${httpclient5.version}</version>
</dependency>
<!-- rest template -->
<dependency>
<groupId>org.springframework.boot</groupId>
@ -63,6 +68,7 @@
<properties>
<httpclient.version>4.5.8</httpclient.version>
<httpclient5.version>5.1</httpclient5.version>
<maven.compiler.source.version>11</maven.compiler.source.version>
<maven.compiler.target.version>11</maven.compiler.target.version>
<spring-boot.version>2.1.7.RELEASE</spring-boot.version>

View File

@ -0,0 +1,29 @@
package com.baeldung.httpclient.readresponsebodystring;
import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.core5.http.HttpEntity;
import org.apache.hc.core5.http.ParseException;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
public class ApacheHttpClient5UnitTest {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
public static final String DUMMY_URL = "https://postman-echo.com/get";
@Test
public void whenUseApacheHttpClient_thenCorrect() throws IOException, ParseException {
HttpGet request = new HttpGet(DUMMY_URL);
try (CloseableHttpClient client = HttpClients.createDefault(); CloseableHttpResponse response = client.execute(request)) {
HttpEntity entity = response.getEntity();
logger.debug("Response -> {}", EntityUtils.toString(entity));
}
}
}

View File

@ -7,10 +7,13 @@ import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
public class ApacheHttpClientUnitTest {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
public static final String DUMMY_URL = "https://postman-echo.com/get";
@Test
@ -19,8 +22,7 @@ public class ApacheHttpClientUnitTest {
try (CloseableHttpClient client = HttpClients.createDefault(); CloseableHttpResponse response = client.execute(request)) {
HttpEntity entity = response.getEntity();
String result = EntityUtils.toString(entity);
System.out.println("Response -> " + result);
logger.debug("Response -> {}", EntityUtils.toString(entity));
}
}
}

View File

@ -0,0 +1,15 @@
<configuration debug="false">
<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%date [%level] %logger - %msg %n</pattern>
</encoder>
</appender>
<logger name="com.baeldung.httpclient.readresponsebodystring" level="debug"/>
<logger name="org.apache.http" level="debug"/>
<logger name="org.apache.hc.client5.http" level="debug"/>
<root level="WARN">
<appender-ref ref="stdout"/>
</root>
</configuration>

View File

@ -3,3 +3,4 @@
- [Probability in Java](https://www.baeldung.com/java-probability)
- [Understanding the & 0xff Value in Java](https://www.baeldung.com/java-and-0xff)
- [Determine if an Integers Square Root Is an Integer in Java](https://www.baeldung.com/java-find-if-square-root-is-integer)
- [Guide to Java BigInteger](https://www.baeldung.com/java-biginteger)

View File

@ -0,0 +1,76 @@
package com.baeldung.biginteger;
import org.junit.jupiter.api.Test;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class BigIntegerUnitTest {
@Test
void givenPositiveAndNegativeAndZeroBigInteger_whenGetSigNumValue_shouldReturnOneAndMinusOneAndZero() {
assertEquals(1, BigInteger.TEN.signum());
assertEquals(-1, BigInteger.TEN.negate().signum());
assertEquals(0, BigInteger.ZERO.signum());
}
@Test
void givenByteArrays_whenCreateBigInteger_shouldTranslateToTwosComplementBinary() {
assertEquals(new BigInteger("1"), new BigInteger(new byte[]{0b1}));
assertEquals(new BigInteger("2"), new BigInteger(new byte[]{0b10}));
assertEquals(new BigInteger("4"), new BigInteger(new byte[]{0b100}));
}
@Test
void givenSingleByte_whenCreateBigIntegerAndDifferentSigNum_thenOppositeValues() {
byte[] bytes = { (byte) -128 }; // 0b1000_0000
BigInteger positive = new BigInteger(1, bytes);
BigInteger negative = new BigInteger(-1, bytes);
assertEquals(new BigInteger("128"), positive);
assertEquals("10000000", positive.toString(2));
assertEquals(new BigInteger("-128"), negative);
assertEquals("-10000000", negative.toString(2));
}
@Test
void givenZeroBigInteger_whenCheckMagnitude_thenIsEmpty() {
assertEquals(0, BigInteger.ZERO.bitCount());
assertEquals(BigInteger.ZERO, new BigInteger(0, new byte[]{}));
}
@Test
void given63rdBitSet_whenCreateBigInteger_thenIsLargerThanLongByOne() {
// first
BigInteger bi1 = BigInteger.ZERO.setBit(63);
String str1 = bi1.toString(2);
// second
byte[] bytes = ByteBuffer.allocate(Long.BYTES).putLong(Long.MIN_VALUE).array();
BigInteger bi2 = new BigInteger(1, bytes);
String str2 = bi2.toString(2);
largerThanLongAssertionSet(bi1, str1);
assertEquals(bi1, bi2);
largerThanLongAssertionSet(bi2, str2);
}
private static void largerThanLongAssertionSet(BigInteger bi, String str)
{
assertEquals(64, bi.bitLength());
assertEquals(1, bi.signum());
assertEquals("9223372036854775808", bi.toString());
assertEquals(BigInteger.ONE, bi.subtract(BigInteger.valueOf(Long.MAX_VALUE)));
assertEquals(64, str.length());
assertTrue(str.matches("^10{63}$")); // 1000 0000
}
}

View File

@ -487,7 +487,7 @@
<properties>
<lifecycle.mapping.version>1.0.0</lifecycle.mapping.version>
<mvc.api.version>1.0.0</mvc.api.version>
<mvc.api.version>1.0-edr2</mvc.api.version>
<java.min.version>1.8</java.min.version>
<maven.min.version>3.0.0</maven.min.version>
<javaee_api.version>7.0</javaee_api.version>

View File

@ -0,0 +1,54 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app-deployment
spec:
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 2
maxUnavailable: 1
selector:
matchLabels:
app: web-app
replicas: 3
template:
metadata:
labels:
app: web-app
spec:
containers:
- name: web-app
image: hello-world:nanoserver-1809
volumeMounts:
- name: counter
mountPath: /app/
volumes:
- name: counter
persistentVolumeClaim:
claimName: counter
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: counter
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 50Mi
storageClassName: default
---
apiVersion: v1
kind: Service
metadata:
name: web-app-service
spec:
ports:
- name: http
port: 80
nodePort: 30080
selector:
name: web-app
type: NodePort

View File

@ -0,0 +1,11 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: counter
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 50Mi
storageClassName: default

View File

@ -0,0 +1,12 @@
apiVersion: v1
kind: Service
metadata:
name: web-app-service
spec:
ports:
- name: http
port: 80
nodePort: 30080
selector:
name: web-app
type: NodePort

View File

@ -0,0 +1,10 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: myclaim
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 5Gi

View File

@ -0,0 +1,13 @@
apiVersion: v1
kind: Service
metadata:
name: nginx
labels:
app: nginx
spec:
ports:
- port: 80
name: web
clusterIP: None
selector:
app: nginx

View File

@ -0,0 +1,28 @@
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
spec:
selector:
matchLabels:
app: nginx
serviceName: "nginx"
replicas: 3
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
name: web
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
volumes:
- name: www
persistentVolumeClaim:
claimName: myclaim

View File

@ -0,0 +1,11 @@
FROM adoptopenjdk:11-jre-hotspot as builder
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} application.jar
RUN java -Djarmode=layertools -jar application.jar extract
FROM adoptopenjdk:11-jre-hotspot
COPY --from=builder dependencies/ ./
COPY --from=builder snapshot-dependencies/ ./
COPY --from=builder spring-boot-loader/ ./
COPY --from=builder application/ ./
ENTRYPOINT ["java", "org.springframework.boot.loader.JarLauncher"]

View File

@ -0,0 +1,86 @@
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-boot-2</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>./../../parent-boot-2</relativePath>
</parent>
<artifactId>k8s-admission-controller</artifactId>
<name>k8s-admission-controller</name>
<description>Demo project for Spring Boot</description>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
<mainClass>com.baeldung.kubernetes.admission.Application</mainClass>
<layers>
<enabled>true</enabled>
</layers>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,17 @@
package com.baeldung.kubernetes.admission;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import com.baeldung.kubernetes.admission.config.AdmissionControllerProperties;
@SpringBootApplication
@EnableConfigurationProperties(AdmissionControllerProperties.class)
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}

View File

@ -0,0 +1,18 @@
/**
*
*/
package com.baeldung.kubernetes.admission.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import lombok.Data;
@ConfigurationProperties(prefix = "admission-controller")
@Data
public class AdmissionControllerProperties {
private boolean disabled;
private String annotation = "com.baeldung/wait-for-it";
private String waitForItImage = "willwill/wait-for-it";
}

View File

@ -0,0 +1,27 @@
/**
*
*/
package com.baeldung.kubernetes.admission.controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.baeldung.kubernetes.admission.dto.AdmissionReviewResponse;
import com.baeldung.kubernetes.admission.service.AdmissionService;
import com.fasterxml.jackson.databind.node.ObjectNode;
import lombok.RequiredArgsConstructor;
import reactor.core.publisher.Mono;
@RestController
@RequiredArgsConstructor
public class AdmissionReviewController {
private final AdmissionService admissionService;
@PostMapping(path = "/mutate")
public Mono<AdmissionReviewResponse> processAdmissionReviewRequest(@RequestBody Mono<ObjectNode> request) {
return request.map((body) -> admissionService.processAdmission(body));
}
}

View File

@ -0,0 +1,31 @@
/**
*
*/
package com.baeldung.kubernetes.admission.dto;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import lombok.Builder;
import lombok.Data;
/**
* Result sent to the API server after reviewing and, possibly
* modifying the incoming request
*/
@Builder
@Data
public class AdmissionReviewData {
final String uid;
final boolean allowed;
@JsonInclude(Include.NON_NULL)
final String patchType;
@JsonInclude(Include.NON_NULL)
final String patch;
@JsonInclude(Include.NON_NULL)
final AdmissionStatus status;
}

View File

@ -0,0 +1,23 @@
package com.baeldung.kubernetes.admission.dto;
public class AdmissionReviewException extends RuntimeException {
private static final long serialVersionUID = 1L;
private final int code;
public AdmissionReviewException(int code, String message) {
super(message);
this.code = code;
}
public AdmissionReviewException(String message) {
super(message);
this.code = 400;
}
public int getCode() {
return code;
}
}

View File

@ -0,0 +1,25 @@
/**
*
*/
package com.baeldung.kubernetes.admission.dto;
import lombok.Builder;
import lombok.Builder.Default;
import lombok.Data;
/**
* Response "envelope" sent back to the API Server
*/
@Builder
@Data
public class AdmissionReviewResponse {
@Default
final String apiVersion = "admission.k8s.io/v1";
@Default
final String kind = "AdmissionReview";
final AdmissionReviewData response;
}

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