Merge branch 'master' into multifilepart
This commit is contained in:
commit
87e69cb30f
algorithms-modules/algorithms-miscellaneous-7/src/test/java/com/baeldung/algorithms/connect4
apache-kafka-2
log4j.propertiespom.xml
src
main/java/com/baeldung/kafka/message/ordering
test
java/com/baeldung/kafka/message/ordering
ExternalSequenceWithTimeWindowLiveTest.javaMultiplePartitionLiveTest.javaSinglePartitionLiveTest.java
resources
atomikos
aws-modules
core-java-modules
core-java-17/src
main/java/com/baeldung/deserializationfilters
test/java/com/baeldung/deserializationfilters
core-java-8-datetime-2
README.mdpom.xml
src
main/java/com/baeldung
maxdate
parsingDates
rounddate
test/java/com/baeldung
maxdate
parsingDates
rounddate
core-java-8-datetime
core-java-8/src/main/java/com/baeldung/streamreduce
core-java-collections-5
README.md
src
main/java/com/baeldung/collectionssortcomplexity
test/java/com/baeldung/vectors
toarraymethod
core-java-collections-conversions-2
core-java-collections-maps-7
README.mdpom.xml
src
main/java/com/baeldung/map/readandwritefile
test/java/com/baeldung/map
linkedhashmapfirstandlastentry
readandwritefile
core-java-concurrency-advanced-5/src/test/java/com/baeldung/exceptions_completablefuture
core-java-concurrency-basic-3
README.md
src
main/java/com/baeldung/concurrent/synchronizestatic
atomicinteger
none
reentrantlock
synchronizedblock
synchronizedclass
synchronizedmethod
test/java/com/baeldung/concurrent/synchronizestatic
core-java-conditionals
core-java-console
core-java-date-operations-1
core-java-date-operations-2
core-java-date-operations-3
core-java-datetime-conversion
core-java-datetime-string
core-java-documentation
core-java-hex/test/java/com/baeldung/hextoint
core-java-io-5
core-java-io-apis-2
core-java-io-conversions-2
core-java-io/src
core-java-jndi
core-java-lang-6
pom.xml
src/main/java/com/baeldung
core-java-numbers-6/src/test/java/com/baeldung/genericnumberscomparator
core-java-numbers-conversions/src/test/java/com/baeldung/floatdoubleconversions
core-java-optional
129
algorithms-modules/algorithms-miscellaneous-7/src/test/java/com/baeldung/algorithms/connect4/GameBoard.java
Normal file
129
algorithms-modules/algorithms-miscellaneous-7/src/test/java/com/baeldung/algorithms/connect4/GameBoard.java
Normal file
@ -0,0 +1,129 @@
|
||||
package com.baeldung.algorithms.connect4;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class GameBoard {
|
||||
private final List<List<Piece>> columns;
|
||||
|
||||
private final int rows;
|
||||
|
||||
public GameBoard(int columns, int rows) {
|
||||
this.rows = rows;
|
||||
this.columns = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < columns; ++i) {
|
||||
this.columns.add(new ArrayList<>());
|
||||
}
|
||||
}
|
||||
|
||||
public int getRows() {
|
||||
return rows;
|
||||
}
|
||||
|
||||
public int getColumns() {
|
||||
return columns.size();
|
||||
}
|
||||
|
||||
public Piece getCell(int x, int y) {
|
||||
assert(x >= 0 && x < getColumns());
|
||||
assert(y >= 0 && y < getRows());
|
||||
|
||||
List<Piece> column = columns.get(x);
|
||||
|
||||
if (column.size() > y) {
|
||||
return column.get(y);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean move(int x, Piece player) {
|
||||
assert(x >= 0 && x < getColumns());
|
||||
|
||||
List<Piece> column = columns.get(x);
|
||||
|
||||
if (column.size() >= this.rows) {
|
||||
throw new IllegalArgumentException("That column is full");
|
||||
}
|
||||
|
||||
column.add(player);
|
||||
|
||||
return checkWin(x, column.size() - 1, player);
|
||||
}
|
||||
|
||||
private boolean checkWin(int x, int y, Piece player) {
|
||||
// Vertical line
|
||||
if (checkLine(x, y, 0, -1, player)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (int offset = 0; offset < 4; ++offset) {
|
||||
// Horizontal line
|
||||
if (checkLine(x - 3 + offset, y, 1, 0, player)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Leading diagonal
|
||||
if (checkLine(x - 3 + offset, y + 3 - offset, 1, -1, player)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Trailing diagonal
|
||||
if (checkLine(x - 3 + offset, y - 3 + offset, 1, 1, player)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean checkLine(int x1, int y1, int xDiff, int yDiff, Piece player) {
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
int x = x1 + (xDiff * i);
|
||||
int y = y1 + (yDiff * i);
|
||||
|
||||
if (x < 0 || x > columns.size() - 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (y < 0 || y > rows - 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (player != getCell(x, y)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder result = new StringBuilder();
|
||||
|
||||
for (int y = getRows() - 1; y >= 0; --y) {
|
||||
for (int x = 0; x < getColumns(); ++x) {
|
||||
Piece piece = getCell(x, y);
|
||||
|
||||
result.append("|");
|
||||
if (piece == null) {
|
||||
result.append(" ");
|
||||
} else if (piece == Piece.PLAYER_1) {
|
||||
result.append("X");
|
||||
} else if (piece == Piece.PLAYER_2) {
|
||||
result.append("O");
|
||||
}
|
||||
}
|
||||
|
||||
result.append("|\n");
|
||||
for (int i = 0; i < getColumns(); ++i) {
|
||||
result.append("+-");
|
||||
}
|
||||
result.append("+\n");
|
||||
}
|
||||
|
||||
return result.toString();
|
||||
}
|
||||
}
|
40
algorithms-modules/algorithms-miscellaneous-7/src/test/java/com/baeldung/algorithms/connect4/GameUnitTest.java
Normal file
40
algorithms-modules/algorithms-miscellaneous-7/src/test/java/com/baeldung/algorithms/connect4/GameUnitTest.java
Normal file
@ -0,0 +1,40 @@
|
||||
package com.baeldung.algorithms.connect4;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
public class GameUnitTest {
|
||||
@Test
|
||||
public void blankGame() {
|
||||
GameBoard gameBoard = new GameBoard(8, 6);
|
||||
|
||||
System.out.println(gameBoard);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void playedGame() {
|
||||
GameBoard gameBoard = new GameBoard(8, 6);
|
||||
|
||||
assertFalse(gameBoard.move(3, Piece.PLAYER_1));
|
||||
assertFalse(gameBoard.move(2, Piece.PLAYER_2));
|
||||
|
||||
assertFalse(gameBoard.move(4, Piece.PLAYER_1));
|
||||
assertFalse(gameBoard.move(3, Piece.PLAYER_2));
|
||||
|
||||
assertFalse(gameBoard.move(5, Piece.PLAYER_1));
|
||||
assertFalse(gameBoard.move(6, Piece.PLAYER_2));
|
||||
|
||||
assertFalse(gameBoard.move(5, Piece.PLAYER_1));
|
||||
assertFalse(gameBoard.move(4, Piece.PLAYER_2));
|
||||
|
||||
assertFalse(gameBoard.move(5, Piece.PLAYER_1));
|
||||
assertFalse(gameBoard.move(5, Piece.PLAYER_2));
|
||||
|
||||
assertFalse(gameBoard.move(6, Piece.PLAYER_1));
|
||||
assertTrue(gameBoard.move(4, Piece.PLAYER_2));
|
||||
|
||||
System.out.println(gameBoard);
|
||||
}
|
||||
}
|
6
algorithms-modules/algorithms-miscellaneous-7/src/test/java/com/baeldung/algorithms/connect4/Piece.java
Normal file
6
algorithms-modules/algorithms-miscellaneous-7/src/test/java/com/baeldung/algorithms/connect4/Piece.java
Normal file
@ -0,0 +1,6 @@
|
||||
package com.baeldung.algorithms.connect4;
|
||||
|
||||
public enum Piece {
|
||||
PLAYER_1,
|
||||
PLAYER_2
|
||||
}
|
2
algorithms-modules/algorithms-miscellaneous-7/src/test/java/com/baeldung/algorithms/connect4/README.md
Normal file
2
algorithms-modules/algorithms-miscellaneous-7/src/test/java/com/baeldung/algorithms/connect4/README.md
Normal file
@ -0,0 +1,2 @@
|
||||
## Relevant Articles
|
||||
- [Implement Connect 4 Game with Java](https://www.baeldung.com/java-connect-4-game)
|
@ -1 +0,0 @@
|
||||
log4j.rootLogger=INFO, stdout
|
@ -23,11 +23,6 @@
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<version>${org.slf4j.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-log4j12</artifactId>
|
||||
<version>${org.slf4j.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
@ -57,6 +52,11 @@
|
||||
<version>${lombok.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>${jackson.databind.version} </version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<properties>
|
||||
@ -64,6 +64,7 @@
|
||||
<kafka.version>2.8.0</kafka.version>
|
||||
<testcontainers-kafka.version>1.15.3</testcontainers-kafka.version>
|
||||
<testcontainers-jupiter.version>1.15.3</testcontainers-jupiter.version>
|
||||
<jackson.databind.version>2.15.2</jackson.databind.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
@ -0,0 +1,11 @@
|
||||
package com.baeldung.kafka.message.ordering;
|
||||
|
||||
public class Config {
|
||||
public static final String CONSUMER_VALUE_DESERIALIZER_SERIALIZED_CLASS = "value.deserializer.serializedClass";
|
||||
public static final String MULTI_PARTITION_TOPIC = "multi_partition_topic";
|
||||
public static final String SINGLE_PARTITION_TOPIC = "single_partition_topic";
|
||||
|
||||
public static final int MULTIPLE_PARTITIONS = 5;
|
||||
public static final int SINGLE_PARTITION = 1;
|
||||
public static final short REPLICATION_FACTOR = 1;
|
||||
}
|
61
apache-kafka-2/src/main/java/com/baeldung/kafka/message/ordering/payload/UserEvent.java
Normal file
61
apache-kafka-2/src/main/java/com/baeldung/kafka/message/ordering/payload/UserEvent.java
Normal file
@ -0,0 +1,61 @@
|
||||
package com.baeldung.kafka.message.ordering.payload;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class UserEvent implements Comparable<UserEvent> {
|
||||
private String userEventId;
|
||||
private long eventNanoTime;
|
||||
private long globalSequenceNumber;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public UserEvent() {
|
||||
// Required for Jackson Serialization and Deserialization
|
||||
}
|
||||
|
||||
public UserEvent(String userEventId) {
|
||||
this.userEventId = userEventId;
|
||||
}
|
||||
|
||||
public String getUserEventId() {
|
||||
return userEventId;
|
||||
}
|
||||
|
||||
public long getEventNanoTime() {
|
||||
return eventNanoTime;
|
||||
}
|
||||
|
||||
public void setEventNanoTime(long eventNanoTime) {
|
||||
this.eventNanoTime = eventNanoTime;
|
||||
}
|
||||
|
||||
public long getGlobalSequenceNumber() {
|
||||
return globalSequenceNumber;
|
||||
}
|
||||
|
||||
public void setGlobalSequenceNumber(long globalSequenceNumber) {
|
||||
this.globalSequenceNumber = globalSequenceNumber;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(UserEvent other) {
|
||||
return Long.compare(this.globalSequenceNumber, other.globalSequenceNumber);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (!(obj instanceof UserEvent)) {
|
||||
return false;
|
||||
}
|
||||
UserEvent userEvent = (UserEvent) obj;
|
||||
return this.globalSequenceNumber == userEvent.globalSequenceNumber;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(globalSequenceNumber);
|
||||
}
|
||||
}
|
||||
|
34
apache-kafka-2/src/main/java/com/baeldung/kafka/message/ordering/serialization/JacksonDeserializer.java
Normal file
34
apache-kafka-2/src/main/java/com/baeldung/kafka/message/ordering/serialization/JacksonDeserializer.java
Normal file
@ -0,0 +1,34 @@
|
||||
package com.baeldung.kafka.message.ordering.serialization;
|
||||
|
||||
import com.baeldung.kafka.message.ordering.Config;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import org.apache.kafka.common.serialization.Deserializer;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Configured via {@link org.apache.kafka.clients.consumer.ConsumerConfig#VALUE_DESERIALIZER_CLASS_CONFIG}
|
||||
*/
|
||||
public class JacksonDeserializer<T> implements Deserializer<T> {
|
||||
private final ObjectMapper objectMapper = new ObjectMapper();
|
||||
private Class<T> type;
|
||||
|
||||
@Override
|
||||
public void configure(Map<String, ?> configs, boolean isKey) {
|
||||
this.type = (Class<T>) configs.get(Config.CONSUMER_VALUE_DESERIALIZER_SERIALIZED_CLASS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T deserialize(String topic, byte[] bytes) {
|
||||
if (bytes == null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return objectMapper.readValue(bytes, type);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Error deserializing value", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
24
apache-kafka-2/src/main/java/com/baeldung/kafka/message/ordering/serialization/JacksonSerializer.java
Normal file
24
apache-kafka-2/src/main/java/com/baeldung/kafka/message/ordering/serialization/JacksonSerializer.java
Normal file
@ -0,0 +1,24 @@
|
||||
package com.baeldung.kafka.message.ordering.serialization;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import org.apache.kafka.common.serialization.Serializer;
|
||||
|
||||
/**
|
||||
* Configured via {@link org.apache.kafka.clients.producer.ProducerConfig#VALUE_SERIALIZER_CLASS_CONFIG}
|
||||
*/
|
||||
public class JacksonSerializer<T> implements Serializer<T> {
|
||||
private final ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
@Override
|
||||
public byte[] serialize(String topic, T data) {
|
||||
if (data == null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return objectMapper.writeValueAsBytes(data);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Error serializing value", e);
|
||||
}
|
||||
}
|
||||
}
|
126
apache-kafka-2/src/test/java/com/baeldung/kafka/message/ordering/ExternalSequenceWithTimeWindowLiveTest.java
Normal file
126
apache-kafka-2/src/test/java/com/baeldung/kafka/message/ordering/ExternalSequenceWithTimeWindowLiveTest.java
Normal file
@ -0,0 +1,126 @@
|
||||
package com.baeldung.kafka.message.ordering;
|
||||
|
||||
import com.baeldung.kafka.message.ordering.payload.UserEvent;
|
||||
import com.baeldung.kafka.message.ordering.serialization.JacksonDeserializer;
|
||||
import com.baeldung.kafka.message.ordering.serialization.JacksonSerializer;
|
||||
|
||||
import org.apache.kafka.clients.admin.*;
|
||||
import org.apache.kafka.clients.consumer.ConsumerConfig;
|
||||
import org.apache.kafka.clients.consumer.ConsumerRecords;
|
||||
import org.apache.kafka.clients.consumer.KafkaConsumer;
|
||||
import org.apache.kafka.clients.producer.KafkaProducer;
|
||||
import org.apache.kafka.clients.producer.ProducerConfig;
|
||||
import org.apache.kafka.clients.producer.ProducerRecord;
|
||||
import org.apache.kafka.clients.producer.RecordMetadata;
|
||||
import org.apache.kafka.common.serialization.LongDeserializer;
|
||||
import org.apache.kafka.common.serialization.LongSerializer;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.testcontainers.containers.KafkaContainer;
|
||||
import org.testcontainers.junit.jupiter.Container;
|
||||
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||
import org.testcontainers.utility.DockerImageName;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat;
|
||||
|
||||
@Testcontainers
|
||||
public class ExternalSequenceWithTimeWindowLiveTest {
|
||||
|
||||
private static Admin admin;
|
||||
private static KafkaProducer<Long, UserEvent> producer;
|
||||
private static KafkaConsumer<Long, UserEvent> consumer;
|
||||
private static final Duration TIMEOUT_WAIT_FOR_MESSAGES = Duration.ofSeconds(5);
|
||||
private static final long BUFFER_PERIOD_NS = Duration.ofSeconds(5)
|
||||
.toNanos();
|
||||
private static Logger logger = LoggerFactory.getLogger(ExternalSequenceWithTimeWindowLiveTest.class);
|
||||
|
||||
@Container
|
||||
private static final KafkaContainer KAFKA_CONTAINER = new KafkaContainer(DockerImageName.parse("confluentinc/cp-kafka:latest"));
|
||||
|
||||
@BeforeAll
|
||||
static void setup() throws ExecutionException, InterruptedException {
|
||||
KAFKA_CONTAINER.addExposedPort(9092);
|
||||
|
||||
Properties adminProperties = new Properties();
|
||||
adminProperties.put(AdminClientConfig.BOOTSTRAP_SERVERS_CONFIG, KAFKA_CONTAINER.getBootstrapServers());
|
||||
|
||||
Properties producerProperties = new Properties();
|
||||
producerProperties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, KAFKA_CONTAINER.getBootstrapServers());
|
||||
producerProperties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, LongSerializer.class.getName());
|
||||
producerProperties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, JacksonSerializer.class.getName());
|
||||
|
||||
Properties consumerProperties = new Properties();
|
||||
consumerProperties.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, KAFKA_CONTAINER.getBootstrapServers());
|
||||
consumerProperties.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, LongDeserializer.class.getName());
|
||||
consumerProperties.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, JacksonDeserializer.class.getName());
|
||||
consumerProperties.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest");
|
||||
consumerProperties.put(Config.CONSUMER_VALUE_DESERIALIZER_SERIALIZED_CLASS, UserEvent.class);
|
||||
consumerProperties.put(ConsumerConfig.GROUP_ID_CONFIG, "test-group");
|
||||
admin = Admin.create(adminProperties);
|
||||
producer = new KafkaProducer<>(producerProperties);
|
||||
consumer = new KafkaConsumer<>(consumerProperties);
|
||||
admin.createTopics(ImmutableList.of(new NewTopic(Config.MULTI_PARTITION_TOPIC, Config.MULTIPLE_PARTITIONS, Config.REPLICATION_FACTOR)))
|
||||
.all()
|
||||
.get();
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
static void destroy() {
|
||||
KAFKA_CONTAINER.stop();
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenMultiplePartitions_whenPublishedToKafkaAndConsumedWithExtSeqNumberAndTimeWindow_thenCheckForMessageOrder() throws ExecutionException, InterruptedException {
|
||||
List<UserEvent> sentUserEventList = new ArrayList<>();
|
||||
List<UserEvent> receivedUserEventList = new ArrayList<>();
|
||||
for (long sequenceNumber = 1; sequenceNumber <= 10; sequenceNumber++) {
|
||||
UserEvent userEvent = new UserEvent(UUID.randomUUID()
|
||||
.toString());
|
||||
userEvent.setEventNanoTime(System.nanoTime());
|
||||
userEvent.setGlobalSequenceNumber(sequenceNumber);
|
||||
Future<RecordMetadata> future = producer.send(new ProducerRecord<>(Config.MULTI_PARTITION_TOPIC, sequenceNumber, userEvent));
|
||||
sentUserEventList.add(userEvent);
|
||||
RecordMetadata metadata = future.get();
|
||||
logger.info("User Event ID: " + userEvent.getUserEventId() + ", Partition : " + metadata.partition());
|
||||
}
|
||||
|
||||
consumer.subscribe(Collections.singletonList(Config.MULTI_PARTITION_TOPIC));
|
||||
List<UserEvent> buffer = new ArrayList<>();
|
||||
long lastProcessedTime = System.nanoTime();
|
||||
ConsumerRecords<Long, UserEvent> records = consumer.poll(TIMEOUT_WAIT_FOR_MESSAGES);
|
||||
records.forEach(record -> {
|
||||
buffer.add(record.value());
|
||||
});
|
||||
while (!buffer.isEmpty()) {
|
||||
if (System.nanoTime() - lastProcessedTime > BUFFER_PERIOD_NS) {
|
||||
processBuffer(buffer, receivedUserEventList);
|
||||
lastProcessedTime = System.nanoTime();
|
||||
}
|
||||
records = consumer.poll(TIMEOUT_WAIT_FOR_MESSAGES);
|
||||
records.forEach(record -> {
|
||||
buffer.add(record.value());
|
||||
});
|
||||
}
|
||||
assertThat(receivedUserEventList).isEqualTo(sentUserEventList)
|
||||
.containsExactlyElementsOf(sentUserEventList);
|
||||
}
|
||||
|
||||
private static void processBuffer(List<UserEvent> buffer, List<UserEvent> receivedUserEventList) {
|
||||
Collections.sort(buffer);
|
||||
buffer.forEach(userEvent -> {
|
||||
receivedUserEventList.add(userEvent);
|
||||
logger.info("Processing message with Global Sequence number: " + userEvent.getGlobalSequenceNumber() + ", User Event Id: " + userEvent.getUserEventId());
|
||||
});
|
||||
buffer.clear();
|
||||
}
|
||||
}
|
105
apache-kafka-2/src/test/java/com/baeldung/kafka/message/ordering/MultiplePartitionLiveTest.java
Normal file
105
apache-kafka-2/src/test/java/com/baeldung/kafka/message/ordering/MultiplePartitionLiveTest.java
Normal file
@ -0,0 +1,105 @@
|
||||
package com.baeldung.kafka.message.ordering;
|
||||
|
||||
import com.baeldung.kafka.message.ordering.payload.UserEvent;
|
||||
import com.baeldung.kafka.message.ordering.serialization.JacksonDeserializer;
|
||||
import com.baeldung.kafka.message.ordering.serialization.JacksonSerializer;
|
||||
|
||||
import org.apache.kafka.clients.admin.*;
|
||||
import org.apache.kafka.clients.consumer.ConsumerConfig;
|
||||
import org.apache.kafka.clients.consumer.ConsumerRecords;
|
||||
import org.apache.kafka.clients.consumer.KafkaConsumer;
|
||||
import org.apache.kafka.clients.producer.KafkaProducer;
|
||||
import org.apache.kafka.clients.producer.ProducerConfig;
|
||||
import org.apache.kafka.clients.producer.ProducerRecord;
|
||||
import org.apache.kafka.clients.producer.RecordMetadata;
|
||||
import org.apache.kafka.common.serialization.LongDeserializer;
|
||||
import org.apache.kafka.common.serialization.LongSerializer;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.testcontainers.containers.KafkaContainer;
|
||||
import org.testcontainers.junit.jupiter.Container;
|
||||
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||
import org.testcontainers.utility.DockerImageName;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat;
|
||||
|
||||
@Testcontainers
|
||||
public class MultiplePartitionLiveTest {
|
||||
|
||||
private static Admin admin;
|
||||
private static KafkaProducer<Long, UserEvent> producer;
|
||||
private static KafkaConsumer<Long, UserEvent> consumer;
|
||||
private static final Duration TIMEOUT_WAIT_FOR_MESSAGES = Duration.ofSeconds(5);
|
||||
|
||||
private static Logger logger = LoggerFactory.getLogger(MultiplePartitionLiveTest.class);
|
||||
@Container
|
||||
private static final KafkaContainer KAFKA_CONTAINER = new KafkaContainer(DockerImageName.parse("confluentinc/cp-kafka:latest"));
|
||||
|
||||
@BeforeAll
|
||||
static void setup() throws ExecutionException, InterruptedException {
|
||||
KAFKA_CONTAINER.addExposedPort(9092);
|
||||
|
||||
Properties adminProperties = new Properties();
|
||||
adminProperties.put(AdminClientConfig.BOOTSTRAP_SERVERS_CONFIG, KAFKA_CONTAINER.getBootstrapServers());
|
||||
|
||||
Properties producerProperties = new Properties();
|
||||
producerProperties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, KAFKA_CONTAINER.getBootstrapServers());
|
||||
producerProperties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, LongSerializer.class.getName());
|
||||
producerProperties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, JacksonSerializer.class.getName());
|
||||
|
||||
Properties consumerProperties = new Properties();
|
||||
consumerProperties.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, KAFKA_CONTAINER.getBootstrapServers());
|
||||
consumerProperties.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, LongDeserializer.class.getName());
|
||||
consumerProperties.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, JacksonDeserializer.class.getName());
|
||||
consumerProperties.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest");
|
||||
consumerProperties.put(Config.CONSUMER_VALUE_DESERIALIZER_SERIALIZED_CLASS, UserEvent.class);
|
||||
consumerProperties.put(ConsumerConfig.GROUP_ID_CONFIG, "test-group");
|
||||
admin = Admin.create(adminProperties);
|
||||
producer = new KafkaProducer<>(producerProperties);
|
||||
consumer = new KafkaConsumer<>(consumerProperties);
|
||||
admin.createTopics(ImmutableList.of(new NewTopic(Config.MULTI_PARTITION_TOPIC, Config.MULTIPLE_PARTITIONS, Config.REPLICATION_FACTOR)))
|
||||
.all()
|
||||
.get();
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
static void destroy() {
|
||||
KAFKA_CONTAINER.stop();
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenMultiplePartitions_whenPublishedToKafkaAndConsumed_thenCheckForMessageOrder() throws ExecutionException, InterruptedException {
|
||||
List<UserEvent> sentUserEventList = new ArrayList<>();
|
||||
List<UserEvent> receivedUserEventList = new ArrayList<>();
|
||||
for (long sequenceNumber = 1; sequenceNumber <= 10; sequenceNumber++) {
|
||||
UserEvent userEvent = new UserEvent(UUID.randomUUID()
|
||||
.toString());
|
||||
userEvent.setGlobalSequenceNumber(sequenceNumber);
|
||||
userEvent.setEventNanoTime(System.nanoTime());
|
||||
Future<RecordMetadata> future = producer.send(new ProducerRecord<>(Config.MULTI_PARTITION_TOPIC, sequenceNumber, userEvent));
|
||||
sentUserEventList.add(userEvent);
|
||||
RecordMetadata metadata = future.get();
|
||||
logger.info("User Event ID: " + userEvent.getUserEventId() + ", Partition : " + metadata.partition());
|
||||
}
|
||||
|
||||
consumer.subscribe(Collections.singletonList(Config.MULTI_PARTITION_TOPIC));
|
||||
ConsumerRecords<Long, UserEvent> records = consumer.poll(TIMEOUT_WAIT_FOR_MESSAGES);
|
||||
records.forEach(record -> {
|
||||
UserEvent userEvent = record.value();
|
||||
receivedUserEventList.add(userEvent);
|
||||
logger.info("User Event ID: " + userEvent.getUserEventId());
|
||||
});
|
||||
assertThat(receivedUserEventList).isNotEqualTo(sentUserEventList)
|
||||
.containsExactlyInAnyOrderElementsOf(sentUserEventList);
|
||||
}
|
||||
}
|
109
apache-kafka-2/src/test/java/com/baeldung/kafka/message/ordering/SinglePartitionLiveTest.java
Normal file
109
apache-kafka-2/src/test/java/com/baeldung/kafka/message/ordering/SinglePartitionLiveTest.java
Normal file
@ -0,0 +1,109 @@
|
||||
package com.baeldung.kafka.message.ordering;
|
||||
|
||||
import com.baeldung.kafka.message.ordering.payload.UserEvent;
|
||||
import com.baeldung.kafka.message.ordering.serialization.JacksonDeserializer;
|
||||
import com.baeldung.kafka.message.ordering.serialization.JacksonSerializer;
|
||||
|
||||
import org.apache.kafka.clients.admin.Admin;
|
||||
import org.apache.kafka.clients.admin.AdminClientConfig;
|
||||
import org.apache.kafka.clients.admin.NewTopic;
|
||||
import org.apache.kafka.clients.consumer.ConsumerConfig;
|
||||
import org.apache.kafka.clients.consumer.ConsumerRecords;
|
||||
import org.apache.kafka.clients.consumer.KafkaConsumer;
|
||||
import org.apache.kafka.clients.producer.KafkaProducer;
|
||||
import org.apache.kafka.clients.producer.ProducerConfig;
|
||||
import org.apache.kafka.clients.producer.ProducerRecord;
|
||||
import org.apache.kafka.clients.producer.RecordMetadata;
|
||||
import org.apache.kafka.common.serialization.LongDeserializer;
|
||||
import org.apache.kafka.common.serialization.LongSerializer;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.testcontainers.containers.KafkaContainer;
|
||||
import org.testcontainers.junit.jupiter.Container;
|
||||
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||
import org.testcontainers.utility.DockerImageName;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat;
|
||||
|
||||
@Testcontainers
|
||||
public class SinglePartitionLiveTest {
|
||||
|
||||
private static Admin admin;
|
||||
private static KafkaProducer<Long, UserEvent> producer;
|
||||
private static KafkaConsumer<Long, UserEvent> consumer;
|
||||
|
||||
private static final Duration TIMEOUT_WAIT_FOR_MESSAGES = Duration.ofSeconds(5);
|
||||
|
||||
private static Logger logger = LoggerFactory.getLogger(SinglePartitionLiveTest.class);
|
||||
@Container
|
||||
private static final KafkaContainer KAFKA_CONTAINER = new KafkaContainer(DockerImageName.parse("confluentinc/cp-kafka:latest"));
|
||||
|
||||
@BeforeAll
|
||||
static void setup() throws ExecutionException, InterruptedException {
|
||||
KAFKA_CONTAINER.addExposedPort(9092);
|
||||
|
||||
Properties adminProperties = new Properties();
|
||||
adminProperties.put(AdminClientConfig.BOOTSTRAP_SERVERS_CONFIG, KAFKA_CONTAINER.getBootstrapServers());
|
||||
|
||||
Properties producerProperties = new Properties();
|
||||
producerProperties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, KAFKA_CONTAINER.getBootstrapServers());
|
||||
producerProperties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, LongSerializer.class.getName());
|
||||
producerProperties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, JacksonSerializer.class.getName());
|
||||
|
||||
Properties consumerProperties = new Properties();
|
||||
consumerProperties.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, KAFKA_CONTAINER.getBootstrapServers());
|
||||
consumerProperties.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, LongDeserializer.class.getName());
|
||||
consumerProperties.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, JacksonDeserializer.class.getName());
|
||||
consumerProperties.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest");
|
||||
consumerProperties.put(Config.CONSUMER_VALUE_DESERIALIZER_SERIALIZED_CLASS, UserEvent.class);
|
||||
consumerProperties.put(ConsumerConfig.GROUP_ID_CONFIG, "test-group");
|
||||
admin = Admin.create(adminProperties);
|
||||
producer = new KafkaProducer<>(producerProperties);
|
||||
consumer = new KafkaConsumer<>(consumerProperties);
|
||||
admin.createTopics(ImmutableList.of(new NewTopic(Config.SINGLE_PARTITION_TOPIC, Config.SINGLE_PARTITION, Config.REPLICATION_FACTOR)))
|
||||
.all()
|
||||
.get();
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
static void destroy() {
|
||||
KAFKA_CONTAINER.stop();
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenASinglePartition_whenPublishedToKafkaAndConsumed_thenCheckForMessageOrder() throws ExecutionException, InterruptedException {
|
||||
List<UserEvent> sentUserEventList = new ArrayList<>();
|
||||
List<UserEvent> receivedUserEventList = new ArrayList<>();
|
||||
for (long sequenceNumber = 1; sequenceNumber <= 10; sequenceNumber++) {
|
||||
UserEvent userEvent = new UserEvent(UUID.randomUUID()
|
||||
.toString());
|
||||
userEvent.setGlobalSequenceNumber(sequenceNumber);
|
||||
userEvent.setEventNanoTime(System.nanoTime());
|
||||
ProducerRecord<Long, UserEvent> producerRecord = new ProducerRecord<>(Config.SINGLE_PARTITION_TOPIC, userEvent);
|
||||
Future<RecordMetadata> future = producer.send(producerRecord);
|
||||
sentUserEventList.add(userEvent);
|
||||
RecordMetadata metadata = future.get();
|
||||
logger.info("User Event ID: " + userEvent.getUserEventId() + ", Partition : " + metadata.partition());
|
||||
}
|
||||
|
||||
consumer.subscribe(Collections.singletonList(Config.SINGLE_PARTITION_TOPIC));
|
||||
ConsumerRecords<Long, UserEvent> records = consumer.poll(TIMEOUT_WAIT_FOR_MESSAGES);
|
||||
records.forEach(record -> {
|
||||
UserEvent userEvent = record.value();
|
||||
receivedUserEventList.add(userEvent);
|
||||
logger.info("User Event ID: " + userEvent.getUserEventId());
|
||||
});
|
||||
assertThat(receivedUserEventList).isEqualTo(sentUserEventList)
|
||||
.containsExactlyElementsOf(sentUserEventList);
|
||||
}
|
||||
}
|
11
apache-kafka-2/src/test/resources/logback.xml
Normal file
11
apache-kafka-2/src/test/resources/logback.xml
Normal file
@ -0,0 +1,11 @@
|
||||
<configuration>
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<root level="INFO">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</root>
|
||||
</configuration>
|
@ -82,26 +82,11 @@
|
||||
<artifactId>geronimo-jta_1.0.1B_spec</artifactId>
|
||||
<version>${geronimo.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.validation</groupId>
|
||||
<artifactId>validation-api</artifactId>
|
||||
<version>${validation-api.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hibernate.validator</groupId>
|
||||
<artifactId>hibernate-validator</artifactId>
|
||||
<version>${hibernate-validator.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.el</groupId>
|
||||
<artifactId>javax.el-api</artifactId>
|
||||
<version>${javax.el-api.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.glassfish.web</groupId>
|
||||
<artifactId>javax.el</artifactId>
|
||||
<version>${javax.el.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<properties>
|
||||
@ -113,10 +98,7 @@
|
||||
<derby.version>10.8.1.2</derby.version>
|
||||
<jta.version>1.1</jta.version>
|
||||
<geronimo.version>1.0</geronimo.version>
|
||||
<validation-api.version>2.0.1.Final</validation-api.version>
|
||||
<hibernate-validator.version>6.1.2.Final</hibernate-validator.version>
|
||||
<javax.el-api.version>3.0.0</javax.el-api.version>
|
||||
<javax.el.version>2.2.4</javax.el.version>
|
||||
<hibernate-validator.version>8.0.1.Final</hibernate-validator.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
@ -3,10 +3,10 @@ package com.baeldung.atomikos.spring.jpa;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.validation.ConstraintViolation;
|
||||
import javax.validation.Validation;
|
||||
import javax.validation.Validator;
|
||||
import javax.validation.ValidatorFactory;
|
||||
import jakarta.validation.ConstraintViolation;
|
||||
import jakarta.validation.Validation;
|
||||
import jakarta.validation.Validator;
|
||||
import jakarta.validation.ValidatorFactory;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
@ -3,7 +3,7 @@ package com.baeldung.atomikos.spring.jpa.order;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
import javax.validation.constraints.Max;
|
||||
import jakarta.validation.constraints.Max;
|
||||
|
||||
@Entity
|
||||
@Table(name = "ORDERS")
|
||||
|
@ -79,7 +79,7 @@
|
||||
</build>
|
||||
|
||||
<properties>
|
||||
<gson.version>2.8.0</gson.version>
|
||||
<gson.version>2.10.1</gson.version>
|
||||
<dynamodblocal.version>1.21.1</dynamodblocal.version>
|
||||
<maven-plugins-version>3.1.1</maven-plugins-version>
|
||||
</properties>
|
||||
|
@ -73,7 +73,7 @@
|
||||
</build>
|
||||
|
||||
<properties>
|
||||
<gson.version>2.8.0</gson.version>
|
||||
<gson.version>2.10.1</gson.version>
|
||||
<dynamodblocal.version>1.21.1</dynamodblocal.version>
|
||||
<commons-codec-version>1.10.L001</commons-codec-version>
|
||||
<jets3t-version>0.9.4.0006L</jets3t-version>
|
||||
|
47
core-java-modules/core-java-17/src/main/java/com/baeldung/deserializationfilters/ContextSpecificDeserializationFilterFactory.java
Normal file
47
core-java-modules/core-java-17/src/main/java/com/baeldung/deserializationfilters/ContextSpecificDeserializationFilterFactory.java
Normal file
@ -0,0 +1,47 @@
|
||||
package com.baeldung.deserializationfilters;
|
||||
|
||||
import java.io.ObjectInputFilter;
|
||||
import java.util.function.BinaryOperator;
|
||||
|
||||
import com.baeldung.deserializationfilters.service.DeserializationService;
|
||||
import com.baeldung.deserializationfilters.service.LimitedArrayService;
|
||||
import com.baeldung.deserializationfilters.service.LowDepthService;
|
||||
import com.baeldung.deserializationfilters.service.SmallObjectService;
|
||||
import com.baeldung.deserializationfilters.utils.FilterUtils;
|
||||
|
||||
public class ContextSpecificDeserializationFilterFactory implements BinaryOperator<ObjectInputFilter> {
|
||||
|
||||
@Override
|
||||
public ObjectInputFilter apply(ObjectInputFilter current, ObjectInputFilter next) {
|
||||
if (current == null) {
|
||||
Class<?> caller = findInStack(DeserializationService.class);
|
||||
|
||||
if (caller == null) {
|
||||
current = FilterUtils.fallbackFilter();
|
||||
} else if (caller.equals(SmallObjectService.class)) {
|
||||
current = FilterUtils.safeSizeFilter(190);
|
||||
} else if (caller.equals(LowDepthService.class)) {
|
||||
current = FilterUtils.safeDepthFilter(2);
|
||||
} else if (caller.equals(LimitedArrayService.class)) {
|
||||
current = FilterUtils.safeArrayFilter(3);
|
||||
}
|
||||
}
|
||||
|
||||
return ObjectInputFilter.merge(current, next);
|
||||
}
|
||||
|
||||
private static Class<?> findInStack(Class<?> superType) {
|
||||
for (StackTraceElement element : Thread.currentThread()
|
||||
.getStackTrace()) {
|
||||
try {
|
||||
Class<?> subType = Class.forName(element.getClassName());
|
||||
if (superType.isAssignableFrom(subType)) {
|
||||
return subType;
|
||||
}
|
||||
} catch (ClassNotFoundException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
7
core-java-modules/core-java-17/src/main/java/com/baeldung/deserializationfilters/pojo/ContextSpecific.java
Normal file
7
core-java-modules/core-java-17/src/main/java/com/baeldung/deserializationfilters/pojo/ContextSpecific.java
Normal file
@ -0,0 +1,7 @@
|
||||
package com.baeldung.deserializationfilters.pojo;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public interface ContextSpecific extends Serializable {
|
||||
|
||||
}
|
19
core-java-modules/core-java-17/src/main/java/com/baeldung/deserializationfilters/pojo/NestedSample.java
Normal file
19
core-java-modules/core-java-17/src/main/java/com/baeldung/deserializationfilters/pojo/NestedSample.java
Normal file
@ -0,0 +1,19 @@
|
||||
package com.baeldung.deserializationfilters.pojo;
|
||||
|
||||
public class NestedSample implements ContextSpecific {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private Sample optional;
|
||||
|
||||
public NestedSample(Sample optional) {
|
||||
this.optional = optional;
|
||||
}
|
||||
|
||||
public Sample getOptional() {
|
||||
return optional;
|
||||
}
|
||||
|
||||
public void setOptional(Sample optional) {
|
||||
this.optional = optional;
|
||||
}
|
||||
}
|
61
core-java-modules/core-java-17/src/main/java/com/baeldung/deserializationfilters/pojo/Sample.java
Normal file
61
core-java-modules/core-java-17/src/main/java/com/baeldung/deserializationfilters/pojo/Sample.java
Normal file
@ -0,0 +1,61 @@
|
||||
package com.baeldung.deserializationfilters.pojo;
|
||||
|
||||
public class Sample implements ContextSpecific, Comparable<Sample> {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private int[] array;
|
||||
private String name;
|
||||
private NestedSample nested;
|
||||
|
||||
public Sample(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Sample(int[] array) {
|
||||
this.array = array;
|
||||
}
|
||||
|
||||
public Sample(NestedSample nested) {
|
||||
this.nested = nested;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int[] getArray() {
|
||||
return array;
|
||||
}
|
||||
|
||||
public void setArray(int[] array) {
|
||||
this.array = array;
|
||||
}
|
||||
|
||||
public NestedSample getNested() {
|
||||
return nested;
|
||||
}
|
||||
|
||||
public void setNested(NestedSample nested) {
|
||||
this.nested = nested;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Sample o) {
|
||||
if (name == null)
|
||||
return -1;
|
||||
|
||||
if (o == null || o.getName() == null)
|
||||
return 1;
|
||||
|
||||
return getName().compareTo(o.getName());
|
||||
}
|
||||
}
|
25
core-java-modules/core-java-17/src/main/java/com/baeldung/deserializationfilters/pojo/SampleExploit.java
Normal file
25
core-java-modules/core-java-17/src/main/java/com/baeldung/deserializationfilters/pojo/SampleExploit.java
Normal file
@ -0,0 +1,25 @@
|
||||
package com.baeldung.deserializationfilters.pojo;
|
||||
|
||||
public class SampleExploit extends Sample {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public SampleExploit() {
|
||||
super("exploit");
|
||||
}
|
||||
|
||||
public static void maliciousCode() {
|
||||
System.out.println("exploit executed");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
maliciousCode();
|
||||
return "exploit";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Sample o) {
|
||||
maliciousCode();
|
||||
return super.compareTo(o);
|
||||
}
|
||||
}
|
11
core-java-modules/core-java-17/src/main/java/com/baeldung/deserializationfilters/service/DeserializationService.java
Normal file
11
core-java-modules/core-java-17/src/main/java/com/baeldung/deserializationfilters/service/DeserializationService.java
Normal file
@ -0,0 +1,11 @@
|
||||
package com.baeldung.deserializationfilters.service;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.Set;
|
||||
|
||||
import com.baeldung.deserializationfilters.pojo.ContextSpecific;
|
||||
|
||||
public interface DeserializationService {
|
||||
|
||||
Set<ContextSpecific> process(InputStream... inputStreams);
|
||||
}
|
15
core-java-modules/core-java-17/src/main/java/com/baeldung/deserializationfilters/service/LimitedArrayService.java
Normal file
15
core-java-modules/core-java-17/src/main/java/com/baeldung/deserializationfilters/service/LimitedArrayService.java
Normal file
@ -0,0 +1,15 @@
|
||||
package com.baeldung.deserializationfilters.service;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.Set;
|
||||
|
||||
import com.baeldung.deserializationfilters.pojo.ContextSpecific;
|
||||
import com.baeldung.deserializationfilters.utils.DeserializationUtils;
|
||||
|
||||
public class LimitedArrayService implements DeserializationService {
|
||||
|
||||
@Override
|
||||
public Set<ContextSpecific> process(InputStream... inputStreams) {
|
||||
return DeserializationUtils.deserializeIntoSet(inputStreams);
|
||||
}
|
||||
}
|
20
core-java-modules/core-java-17/src/main/java/com/baeldung/deserializationfilters/service/LowDepthService.java
Normal file
20
core-java-modules/core-java-17/src/main/java/com/baeldung/deserializationfilters/service/LowDepthService.java
Normal file
@ -0,0 +1,20 @@
|
||||
package com.baeldung.deserializationfilters.service;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.ObjectInputFilter;
|
||||
import java.util.Set;
|
||||
|
||||
import com.baeldung.deserializationfilters.pojo.ContextSpecific;
|
||||
import com.baeldung.deserializationfilters.utils.DeserializationUtils;
|
||||
|
||||
public class LowDepthService implements DeserializationService {
|
||||
|
||||
public Set<ContextSpecific> process(ObjectInputFilter filter, InputStream... inputStreams) {
|
||||
return DeserializationUtils.deserializeIntoSet(filter, inputStreams);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<ContextSpecific> process(InputStream... inputStreams) {
|
||||
return process(null, inputStreams);
|
||||
}
|
||||
}
|
15
core-java-modules/core-java-17/src/main/java/com/baeldung/deserializationfilters/service/SmallObjectService.java
Normal file
15
core-java-modules/core-java-17/src/main/java/com/baeldung/deserializationfilters/service/SmallObjectService.java
Normal file
@ -0,0 +1,15 @@
|
||||
package com.baeldung.deserializationfilters.service;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.Set;
|
||||
|
||||
import com.baeldung.deserializationfilters.pojo.ContextSpecific;
|
||||
import com.baeldung.deserializationfilters.utils.DeserializationUtils;
|
||||
|
||||
public class SmallObjectService implements DeserializationService {
|
||||
|
||||
@Override
|
||||
public Set<ContextSpecific> process(InputStream... inputStreams) {
|
||||
return DeserializationUtils.deserializeIntoSet(inputStreams);
|
||||
}
|
||||
}
|
50
core-java-modules/core-java-17/src/main/java/com/baeldung/deserializationfilters/utils/DeserializationUtils.java
Normal file
50
core-java-modules/core-java-17/src/main/java/com/baeldung/deserializationfilters/utils/DeserializationUtils.java
Normal file
@ -0,0 +1,50 @@
|
||||
package com.baeldung.deserializationfilters.utils;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.InvalidClassException;
|
||||
import java.io.ObjectInputFilter;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import com.baeldung.deserializationfilters.pojo.ContextSpecific;
|
||||
|
||||
public class DeserializationUtils {
|
||||
private DeserializationUtils() {
|
||||
}
|
||||
|
||||
public static Object deserialize(InputStream inStream) {
|
||||
return deserialize(inStream, null);
|
||||
}
|
||||
|
||||
public static Object deserialize(InputStream inStream, ObjectInputFilter filter) {
|
||||
try (ObjectInputStream in = new ObjectInputStream(inStream)) {
|
||||
if (filter != null) {
|
||||
in.setObjectInputFilter(filter);
|
||||
}
|
||||
return in.readObject();
|
||||
} catch (InvalidClassException e) {
|
||||
return null;
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static Set<ContextSpecific> deserializeIntoSet(InputStream... inputStreams) {
|
||||
return deserializeIntoSet(null, inputStreams);
|
||||
}
|
||||
|
||||
public static Set<ContextSpecific> deserializeIntoSet(ObjectInputFilter filter, InputStream... inputStreams) {
|
||||
Set<ContextSpecific> set = new TreeSet<>();
|
||||
|
||||
for (InputStream inputStream : inputStreams) {
|
||||
Object object = deserialize(inputStream, filter);
|
||||
if (object != null) {
|
||||
set.add((ContextSpecific) object);
|
||||
}
|
||||
}
|
||||
|
||||
return set;
|
||||
}
|
||||
}
|
32
core-java-modules/core-java-17/src/main/java/com/baeldung/deserializationfilters/utils/FilterUtils.java
Normal file
32
core-java-modules/core-java-17/src/main/java/com/baeldung/deserializationfilters/utils/FilterUtils.java
Normal file
@ -0,0 +1,32 @@
|
||||
package com.baeldung.deserializationfilters.utils;
|
||||
|
||||
import java.io.ObjectInputFilter;
|
||||
|
||||
public class FilterUtils {
|
||||
|
||||
private static final String DEFAULT_PACKAGE_PATTERN = "java.base/*;!*";
|
||||
private static final String POJO_PACKAGE = "com.baeldung.deserializationfilters.pojo";
|
||||
|
||||
private FilterUtils() {
|
||||
}
|
||||
|
||||
private static ObjectInputFilter baseFilter(String parameter, int max) {
|
||||
return ObjectInputFilter.Config.createFilter(String.format("%s=%d;%s.**;%s", parameter, max, POJO_PACKAGE, DEFAULT_PACKAGE_PATTERN));
|
||||
}
|
||||
|
||||
public static ObjectInputFilter fallbackFilter() {
|
||||
return ObjectInputFilter.Config.createFilter(String.format("%s", DEFAULT_PACKAGE_PATTERN));
|
||||
}
|
||||
|
||||
public static ObjectInputFilter safeSizeFilter(int max) {
|
||||
return baseFilter("maxbytes", max);
|
||||
}
|
||||
|
||||
public static ObjectInputFilter safeArrayFilter(int max) {
|
||||
return baseFilter("maxarray", max);
|
||||
}
|
||||
|
||||
public static ObjectInputFilter safeDepthFilter(int max) {
|
||||
return baseFilter("maxdepth", max);
|
||||
}
|
||||
}
|
17
core-java-modules/core-java-17/src/main/java/com/baeldung/deserializationfilters/utils/SerializationUtils.java
Normal file
17
core-java-modules/core-java-17/src/main/java/com/baeldung/deserializationfilters/utils/SerializationUtils.java
Normal file
@ -0,0 +1,17 @@
|
||||
package com.baeldung.deserializationfilters.utils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
public class SerializationUtils {
|
||||
|
||||
private SerializationUtils() {
|
||||
}
|
||||
|
||||
public static void serialize(Object object, OutputStream outStream) throws IOException {
|
||||
try (ObjectOutputStream objStream = new ObjectOutputStream(outStream)) {
|
||||
objStream.writeObject(object);
|
||||
}
|
||||
}
|
||||
}
|
119
core-java-modules/core-java-17/src/test/java/com/baeldung/deserializationfilters/ContextSpecificDeserializationFilterIntegrationTest.java
Normal file
119
core-java-modules/core-java-17/src/test/java/com/baeldung/deserializationfilters/ContextSpecificDeserializationFilterIntegrationTest.java
Normal file
@ -0,0 +1,119 @@
|
||||
package com.baeldung.deserializationfilters;
|
||||
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputFilter;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import com.baeldung.deserializationfilters.pojo.ContextSpecific;
|
||||
import com.baeldung.deserializationfilters.pojo.NestedSample;
|
||||
import com.baeldung.deserializationfilters.pojo.Sample;
|
||||
import com.baeldung.deserializationfilters.pojo.SampleExploit;
|
||||
import com.baeldung.deserializationfilters.service.LimitedArrayService;
|
||||
import com.baeldung.deserializationfilters.service.LowDepthService;
|
||||
import com.baeldung.deserializationfilters.service.SmallObjectService;
|
||||
import com.baeldung.deserializationfilters.utils.DeserializationUtils;
|
||||
import com.baeldung.deserializationfilters.utils.FilterUtils;
|
||||
import com.baeldung.deserializationfilters.utils.SerializationUtils;
|
||||
|
||||
public class ContextSpecificDeserializationFilterIntegrationTest {
|
||||
|
||||
private static ByteArrayOutputStream serialSampleA = new ByteArrayOutputStream();
|
||||
private static ByteArrayOutputStream serialBigSampleA = new ByteArrayOutputStream();
|
||||
|
||||
private static ByteArrayOutputStream serialSampleB = new ByteArrayOutputStream();
|
||||
private static ByteArrayOutputStream serialBigSampleB = new ByteArrayOutputStream();
|
||||
|
||||
private static ByteArrayOutputStream serialSampleC = new ByteArrayOutputStream();
|
||||
private static ByteArrayOutputStream serialBigSampleC = new ByteArrayOutputStream();
|
||||
|
||||
private static ByteArrayInputStream bytes(ByteArrayOutputStream stream) {
|
||||
return new ByteArrayInputStream(stream.toByteArray());
|
||||
}
|
||||
|
||||
@BeforeAll
|
||||
static void setup() throws IOException {
|
||||
ObjectInputFilter.Config.setSerialFilterFactory(new ContextSpecificDeserializationFilterFactory());
|
||||
|
||||
SerializationUtils.serialize(new Sample("simple"), serialSampleA);
|
||||
SerializationUtils.serialize(new SampleExploit(), serialBigSampleA);
|
||||
|
||||
SerializationUtils.serialize(new Sample(new int[] { 1, 2, 3 }), serialSampleB);
|
||||
SerializationUtils.serialize(new Sample(new int[] { 1, 2, 3, 4, 5, 6 }), serialBigSampleB);
|
||||
|
||||
SerializationUtils.serialize(new Sample(new NestedSample(null)), serialSampleC);
|
||||
SerializationUtils.serialize(new Sample(new NestedSample(new Sample("deep"))), serialBigSampleC);
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenSmallObjectContext_thenCorrectFilterApplied() {
|
||||
Set<ContextSpecific> result = new SmallObjectService().process( //
|
||||
bytes(serialSampleA), //
|
||||
bytes(serialBigSampleA));
|
||||
|
||||
assertEquals(1, result.size());
|
||||
assertEquals("simple", ((Sample) result.iterator()
|
||||
.next()).getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenLimitedArrayContext_thenCorrectFilterApplied() {
|
||||
Set<ContextSpecific> result = new LimitedArrayService().process( //
|
||||
bytes(serialSampleB), //
|
||||
bytes(serialBigSampleB));
|
||||
|
||||
assertEquals(1, result.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenLowDepthContext_thenCorrectFilterApplied() {
|
||||
Set<ContextSpecific> result = new LowDepthService().process( //
|
||||
bytes(serialSampleC), //
|
||||
bytes(serialBigSampleC));
|
||||
|
||||
assertEquals(1, result.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenExtraFilter_whenCombinedContext_thenMergedFiltersApplied() {
|
||||
Set<ContextSpecific> result = new LowDepthService().process( //
|
||||
FilterUtils.safeSizeFilter(190), //
|
||||
bytes(serialSampleA), //
|
||||
bytes(serialBigSampleA), //
|
||||
bytes(serialSampleC), //
|
||||
bytes(serialBigSampleC));
|
||||
|
||||
assertEquals(1, result.size());
|
||||
assertEquals("simple", ((Sample) result.iterator()
|
||||
.next()).getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenFallbackContext_whenUsingBaseClasses_thenRestrictiveFilterApplied() throws IOException {
|
||||
String a = new String("a");
|
||||
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
|
||||
SerializationUtils.serialize(a, outStream);
|
||||
|
||||
String deserializedA = (String) DeserializationUtils.deserialize(bytes(outStream));
|
||||
|
||||
assertEquals(a, deserializedA);
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenFallbackContext_whenUsingAppClasses_thenRejected() throws IOException {
|
||||
Sample a = new Sample("a");
|
||||
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
|
||||
SerializationUtils.serialize(a, outStream);
|
||||
|
||||
Sample deserializedA = (Sample) DeserializationUtils.deserialize(bytes(outStream));
|
||||
|
||||
assertNull(deserializedA);
|
||||
}
|
||||
}
|
@ -6,4 +6,5 @@
|
||||
- [How Many Days Are There in a Particular Month of a Given Year?](https://www.baeldung.com/days-particular-month-given-year)
|
||||
- [Difference Between Instant and LocalDateTime](https://www.baeldung.com/java-instant-vs-localdatetime)
|
||||
- [Add Minutes to a Time String in Java](https://www.baeldung.com/java-string-time-add-mins)
|
||||
- [Round the Date in Java](https://www.baeldung.com/java-round-the-date)
|
||||
- [[<-- Prev]](/core-java-modules/core-java-datetime-java8-1)
|
||||
|
@ -55,7 +55,7 @@
|
||||
<properties>
|
||||
<maven.compiler.source>1.8</maven.compiler.source>
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
<joda-time.version>2.10</joda-time.version>
|
||||
<joda-time.version>2.12.5</joda-time.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
18
core-java-modules/core-java-8-datetime-2/src/main/java/com/baeldung/maxdate/DateComparison.java
Normal file
18
core-java-modules/core-java-8-datetime-2/src/main/java/com/baeldung/maxdate/DateComparison.java
Normal file
@ -0,0 +1,18 @@
|
||||
package com.baeldung.maxdate;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
public class DateComparison {
|
||||
public int compareTodayWithMaxDate() {
|
||||
Date today = new Date();
|
||||
Date maxDate = new Date(Long.MAX_VALUE);
|
||||
|
||||
int comparisonResult = today.compareTo(maxDate);
|
||||
return comparisonResult;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
DateComparison comparator = new DateComparison();
|
||||
System.out.println(comparator.compareTodayWithMaxDate());
|
||||
}
|
||||
}
|
18
core-java-modules/core-java-8-datetime-2/src/main/java/com/baeldung/maxdate/MaxDateDisplay.java
Normal file
18
core-java-modules/core-java-8-datetime-2/src/main/java/com/baeldung/maxdate/MaxDateDisplay.java
Normal file
@ -0,0 +1,18 @@
|
||||
package com.baeldung.maxdate;
|
||||
|
||||
import java.util.Date;
|
||||
import java.text.SimpleDateFormat;
|
||||
|
||||
public class MaxDateDisplay {
|
||||
public String getMaxDateValue() {
|
||||
Date maxDate = new Date(Long.MAX_VALUE);
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
|
||||
return "The maximum date value in Java is: " + sdf.format(maxDate);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
MaxDateDisplay display = new MaxDateDisplay();
|
||||
System.out.println(display.getMaxDateValue());
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ import java.util.List;
|
||||
|
||||
public class SimpleParseDate {
|
||||
|
||||
public Date parseDate(String dateString, List<String> formatStrings) {
|
||||
public static Date parseDate(String dateString, List<String> formatStrings) {
|
||||
for (String formatString : formatStrings) {
|
||||
try {
|
||||
return new SimpleDateFormat(formatString).parse(dateString);
|
||||
|
113
core-java-modules/core-java-8-datetime-2/src/main/java/com/baeldung/rounddate/RoundDate.java
Normal file
113
core-java-modules/core-java-8-datetime-2/src/main/java/com/baeldung/rounddate/RoundDate.java
Normal file
@ -0,0 +1,113 @@
|
||||
package com.baeldung.rounddate;
|
||||
|
||||
import java.time.DayOfWeek;
|
||||
import java.time.temporal.ChronoField;
|
||||
import java.time.temporal.TemporalAdjusters;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZonedDateTime;
|
||||
|
||||
public class RoundDate {
|
||||
public static Date getDate(int year, int month, int day, int hour, int minute) {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.set(Calendar.YEAR, year);
|
||||
calendar.set(Calendar.MONTH, month);
|
||||
calendar.set(Calendar.DAY_OF_MONTH, day);
|
||||
calendar.set(Calendar.HOUR_OF_DAY, hour);
|
||||
calendar.set(Calendar.MINUTE, minute);
|
||||
calendar.set(Calendar.SECOND, 0);
|
||||
calendar.set(Calendar.MILLISECOND, 0);
|
||||
|
||||
return calendar.getTime();
|
||||
}
|
||||
|
||||
public static Date roundToDay(Date date) {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.setTime(date);
|
||||
calendar.set(Calendar.HOUR_OF_DAY, 0);
|
||||
calendar.set(Calendar.MINUTE, 0);
|
||||
calendar.set(Calendar.SECOND, 0);
|
||||
calendar.set(Calendar.MILLISECOND, 0);
|
||||
return calendar.getTime();
|
||||
}
|
||||
|
||||
public static Date roundToNearestUnit(Date date, int unit) {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.setTime(date);
|
||||
|
||||
switch (unit) {
|
||||
case Calendar.HOUR:
|
||||
int minute = calendar.get(Calendar.MINUTE);
|
||||
if (minute >= 0 && minute < 15) {
|
||||
calendar.set(Calendar.MINUTE, 0);
|
||||
} else if (minute >= 15 && minute < 45) {
|
||||
calendar.set(Calendar.MINUTE, 30);
|
||||
} else {
|
||||
calendar.set(Calendar.MINUTE, 0);
|
||||
calendar.add(Calendar.HOUR_OF_DAY, 1);
|
||||
}
|
||||
calendar.set(Calendar.SECOND, 0);
|
||||
calendar.set(Calendar.MILLISECOND, 0);
|
||||
break;
|
||||
|
||||
case Calendar.DAY_OF_MONTH:
|
||||
int hour = calendar.get(Calendar.HOUR_OF_DAY);
|
||||
if (hour >= 12) {
|
||||
calendar.add(Calendar.DAY_OF_MONTH, 1);
|
||||
}
|
||||
calendar.set(Calendar.HOUR_OF_DAY, 0);
|
||||
calendar.set(Calendar.MINUTE, 0);
|
||||
calendar.set(Calendar.SECOND, 0);
|
||||
calendar.set(Calendar.MILLISECOND, 0);
|
||||
break;
|
||||
|
||||
case Calendar.MONTH:
|
||||
int day = calendar.get(Calendar.DAY_OF_MONTH);
|
||||
if (day >= 15) {
|
||||
calendar.add(Calendar.MONTH, 1);
|
||||
}
|
||||
calendar.set(Calendar.DAY_OF_MONTH, 1);
|
||||
calendar.set(Calendar.HOUR_OF_DAY, 0);
|
||||
calendar.set(Calendar.MINUTE, 0);
|
||||
calendar.set(Calendar.SECOND, 0);
|
||||
calendar.set(Calendar.MILLISECOND, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
return calendar.getTime();
|
||||
}
|
||||
|
||||
public static LocalDateTime roundToStartOfMonthUsingLocalDateTime(LocalDateTime dateTime) {
|
||||
return dateTime.withDayOfMonth(1).withHour(0).withMinute(0).withSecond(0).withNano(0);
|
||||
}
|
||||
|
||||
public static LocalDateTime roundToEndOfWeekUsingLocalDateTime(LocalDateTime dateTime) {
|
||||
return dateTime.with(TemporalAdjusters.next(DayOfWeek.SATURDAY))
|
||||
.withHour(23)
|
||||
.withMinute(59)
|
||||
.withSecond(59)
|
||||
.withNano(999);
|
||||
}
|
||||
|
||||
public static ZonedDateTime roundToStartOfMonthUsingZonedDateTime(ZonedDateTime dateTime) {
|
||||
return dateTime.withDayOfMonth(1)
|
||||
.withHour(0)
|
||||
.withMinute(0)
|
||||
.withSecond(0)
|
||||
.with(ChronoField.MILLI_OF_SECOND, 0)
|
||||
.with(ChronoField.MICRO_OF_SECOND, 0)
|
||||
.with(ChronoField.NANO_OF_SECOND, 0);
|
||||
}
|
||||
|
||||
public static ZonedDateTime roundToEndOfWeekUsingZonedDateTime(ZonedDateTime dateTime) {
|
||||
return dateTime.with(TemporalAdjusters.next(DayOfWeek.SATURDAY))
|
||||
.withHour(23)
|
||||
.withMinute(59)
|
||||
.withSecond(59)
|
||||
.with(ChronoField.MILLI_OF_SECOND, 999)
|
||||
.with(ChronoField.MICRO_OF_SECOND, 999)
|
||||
.with(ChronoField.NANO_OF_SECOND, 999);
|
||||
}
|
||||
|
||||
}
|
16
core-java-modules/core-java-8-datetime-2/src/test/java/com/baeldung/maxdate/DateComparisonUnitTest.java
Normal file
16
core-java-modules/core-java-8-datetime-2/src/test/java/com/baeldung/maxdate/DateComparisonUnitTest.java
Normal file
@ -0,0 +1,16 @@
|
||||
package com.baeldung.maxdate;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class DateComparisonUnitTest {
|
||||
|
||||
@Test
|
||||
void whenCompareTodayWithMaxDate_thenCorrectResult() {
|
||||
DateComparison comparator = new DateComparison();
|
||||
int result = comparator.compareTodayWithMaxDate();
|
||||
|
||||
assertTrue(result < 0);
|
||||
}
|
||||
}
|
18
core-java-modules/core-java-8-datetime-2/src/test/java/com/baeldung/maxdate/MaxDateDisplayUnitTest.java
Normal file
18
core-java-modules/core-java-8-datetime-2/src/test/java/com/baeldung/maxdate/MaxDateDisplayUnitTest.java
Normal file
@ -0,0 +1,18 @@
|
||||
package com.baeldung.maxdate;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class MaxDateDisplayUnitTest {
|
||||
|
||||
@Test
|
||||
void whenGetMaxDate_thenCorrectResult() {
|
||||
MaxDateDisplay display = new MaxDateDisplay();
|
||||
String result = display.getMaxDateValue();
|
||||
assertEquals(
|
||||
"The maximum date value in Java is: 292278994-08-17 07:12:55.807",
|
||||
result
|
||||
);
|
||||
}
|
||||
}
|
@ -1,43 +1,41 @@
|
||||
package com.baeldung.parsingDates;
|
||||
|
||||
import com.baeldung.parsingDates.SimpleDateTimeFormat;
|
||||
import com.baeldung.parsingDates.SimpleDateTimeFormater;
|
||||
import com.baeldung.parsingDates.SimpleDateUtils;
|
||||
import com.baeldung.parsingDates.SimpleParseDate;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
import java.time.format.DateTimeParseException;
|
||||
import java.util.Arrays;
|
||||
import org.junit.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.joda.time.LocalDate;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class SimpleParseDateUnitTest {
|
||||
class SimpleParseDateUnitTest {
|
||||
|
||||
@Test
|
||||
public void whenInvalidInput_thenGettingUnexpectedResult() {
|
||||
SimpleParseDate simpleParseDate = new SimpleParseDate();
|
||||
void whenInvalidInput_thenGettingUnexpectedResult() {
|
||||
String date = "2022-40-40";
|
||||
assertEquals("Sat May 10 00:00:00 UTC 2025", simpleParseDate.parseDate(date, Arrays.asList("MM/dd/yyyy", "dd.MM.yyyy", "yyyy-MM-dd")).toString());
|
||||
assertEquals("Sat May 10 00:00:00 UTC 2025", SimpleParseDate.parseDate(date, Arrays.asList("MM/dd/yyyy", "dd.MM.yyyy", "yyyy-MM-dd"))
|
||||
.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenInvalidDate_thenAssertThrows() {
|
||||
SimpleDateTimeFormater simpleDateTimeFormater = new SimpleDateTimeFormater();
|
||||
assertEquals(java.time.LocalDate.parse("2022-12-04"), simpleDateTimeFormater.parseDate("2022-12-04"));
|
||||
assertThrows(DateTimeParseException.class, () -> simpleDateTimeFormater.parseDate("2022-13-04"));
|
||||
void whenInvalidDate_thenAssertThrows() {
|
||||
assertEquals(java.time.LocalDate.parse("2022-12-04"), SimpleDateTimeFormater.parseDate("2022-12-04"));
|
||||
assertThrows(DateTimeParseException.class, () -> SimpleDateTimeFormater.parseDate("2022-13-04"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenDateIsCorrect_thenParseCorrect() {
|
||||
SimpleDateUtils simpleDateUtils = new SimpleDateUtils();
|
||||
assertNull(simpleDateUtils.parseDate("53/10/2014"));
|
||||
assertEquals("Wed Sep 10 00:00:00 UTC 2014", simpleDateUtils.parseDate("10/09/2014").toString());
|
||||
void whenDateIsCorrect_thenParseCorrect() {
|
||||
assertNull(SimpleDateUtils.parseDate("53/10/2014"));
|
||||
assertEquals("Wed Sep 10 00:00:00 UTC 2014", SimpleDateUtils.parseDate("10/09/2014")
|
||||
.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenDateIsCorrect_thenResultCorrect() {
|
||||
SimpleDateTimeFormat simpleDateTimeFormat = new SimpleDateTimeFormat();
|
||||
assertNull(simpleDateTimeFormat.parseDate("53/10/2014"));
|
||||
assertEquals(LocalDate.parse("2014-10-10"), simpleDateTimeFormat.parseDate("2014-10-10"));
|
||||
void whenDateIsCorrect_thenResultCorrect() {
|
||||
assertNull(SimpleDateTimeFormat.parseDate("53/10/2014"));
|
||||
assertEquals(LocalDate.parse("2014-10-10"), SimpleDateTimeFormat.parseDate("2014-10-10"));
|
||||
}
|
||||
|
||||
}
|
||||
|
63
core-java-modules/core-java-8-datetime-2/src/test/java/com/baeldung/rounddate/DateRoundingUnitTest.java
Normal file
63
core-java-modules/core-java-8-datetime-2/src/test/java/com/baeldung/rounddate/DateRoundingUnitTest.java
Normal file
@ -0,0 +1,63 @@
|
||||
package com.baeldung.rounddate;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public class DateRoundingUnitTest {
|
||||
|
||||
@Test
|
||||
public void givenDate_whenRoundToDay_thenBeginningOfDay() {
|
||||
Date date = RoundDate.getDate(2023, Calendar.JANUARY, 27, 14, 30);
|
||||
Date result = RoundDate.roundToDay(date);
|
||||
assertEquals(RoundDate.getDate(2023, Calendar.JANUARY, 27, 0, 0), result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenDate_whenRoundToNearestUnit_thenNearestUnit() {
|
||||
Date date = RoundDate.getDate(2023, Calendar.JANUARY, 27, 14, 12);
|
||||
Date result = RoundDate.roundToNearestUnit(date, Calendar.DAY_OF_MONTH);
|
||||
Date expected = RoundDate.getDate(2023, Calendar.JANUARY, 28, 0, 0);
|
||||
assertEquals(expected, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenLocalDateTime_whenRoundToStartOfMonth_thenStartOfMonth() {
|
||||
LocalDateTime dateTime = LocalDateTime.of(2023, 1, 27, 14, 12);
|
||||
LocalDateTime result = RoundDate.roundToStartOfMonthUsingLocalDateTime(dateTime);
|
||||
LocalDateTime expected = LocalDateTime.of(2023, 1, 1, 0, 0, 0);
|
||||
assertEquals(expected, result);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void givenZonedDateTime_whenRoundToStartOfMonth_thenStartOfMonth() {
|
||||
ZonedDateTime dateTime = ZonedDateTime.of(2023, 1, 27, 14, 12, 0, 0, ZoneId.systemDefault());
|
||||
ZonedDateTime result = RoundDate.roundToStartOfMonthUsingZonedDateTime(dateTime);
|
||||
ZonedDateTime expected = ZonedDateTime.of(2023, 1, 1, 0, 0, 0, 0, ZoneId.systemDefault());
|
||||
assertEquals(expected, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenLocalDateTime_whenRoundToEndOfWeek_thenEndOfWeek() {
|
||||
LocalDateTime dateTime = LocalDateTime.of(2023, 1, 27, 14, 12);
|
||||
LocalDateTime result = RoundDate.roundToEndOfWeekUsingLocalDateTime(dateTime);
|
||||
LocalDateTime expected = LocalDateTime.of(2023, 1, 28, 23, 59, 59, 999);
|
||||
assertEquals(expected, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenZonedDateTime_whenRoundToEndOfWeek_thenEndOfWeek() {
|
||||
ZonedDateTime dateTime = ZonedDateTime.of(2023, 1, 27, 14, 12, 0, 0, ZoneId.systemDefault());
|
||||
ZonedDateTime result = RoundDate.roundToEndOfWeekUsingZonedDateTime(dateTime);
|
||||
ZonedDateTime expected = ZonedDateTime.of(2023, 1, 28, 23, 59, 59, 999, ZoneId.systemDefault());
|
||||
assertEquals(expected, result);
|
||||
}
|
||||
|
||||
}
|
@ -56,7 +56,7 @@
|
||||
<properties>
|
||||
<maven.compiler.source>1.8</maven.compiler.source>
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
<joda-time.version>2.10</joda-time.version>
|
||||
<joda-time.version>2.12.5</joda-time.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
62
core-java-modules/core-java-8/src/main/java/com/baeldung/streamreduce/application/Application.java
62
core-java-modules/core-java-8/src/main/java/com/baeldung/streamreduce/application/Application.java
@ -1,62 +0,0 @@
|
||||
package com.baeldung.streamreduce.application;
|
||||
|
||||
import com.baeldung.streamreduce.entities.User;
|
||||
import com.baeldung.streamreduce.utilities.NumberUtils;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class Application {
|
||||
|
||||
public static void main(String[] args) {
|
||||
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
|
||||
int result1 = numbers.stream().reduce(0, (a, b) -> a + b);
|
||||
System.out.println(result1);
|
||||
|
||||
int result2 = numbers.stream().reduce(0, Integer::sum);
|
||||
System.out.println(result2);
|
||||
|
||||
List<String> letters = Arrays.asList("a", "b", "c", "d", "e");
|
||||
String result3 = letters.stream().reduce("", (a, b) -> a + b);
|
||||
System.out.println(result3);
|
||||
|
||||
String result4 = letters.stream().reduce("", String::concat);
|
||||
System.out.println(result4);
|
||||
|
||||
String result5 = letters.stream().reduce("", (a, b) -> a.toUpperCase() + b.toUpperCase());
|
||||
System.out.println(result5);
|
||||
|
||||
List<User> users = Arrays.asList(new User("John", 30), new User("Julie", 35));
|
||||
int result6 = users.stream().reduce(0, (partialAgeResult, user) -> partialAgeResult + user.getAge(), Integer::sum);
|
||||
System.out.println(result6);
|
||||
|
||||
String result7 = letters.parallelStream().reduce("", String::concat);
|
||||
System.out.println(result7);
|
||||
|
||||
int result8 = users.parallelStream().reduce(0, (partialAgeResult, user) -> partialAgeResult + user.getAge(), Integer::sum);
|
||||
System.out.println(result8);
|
||||
|
||||
List<User> userList = new ArrayList<>();
|
||||
for (int i = 0; i <= 1000000; i++) {
|
||||
userList.add(new User("John" + i, i));
|
||||
}
|
||||
|
||||
long t1 = System.currentTimeMillis();
|
||||
int result9 = userList.stream().reduce(0, (partialAgeResult, user) -> partialAgeResult + user.getAge(), Integer::sum);
|
||||
long t2 = System.currentTimeMillis();
|
||||
System.out.println(result9);
|
||||
System.out.println("Sequential stream time: " + (t2 - t1) + "ms");
|
||||
|
||||
long t3 = System.currentTimeMillis();
|
||||
int result10 = userList.parallelStream().reduce(0, (partialAgeResult, user) -> partialAgeResult + user.getAge(), Integer::sum);
|
||||
long t4 = System.currentTimeMillis();
|
||||
System.out.println(result10);
|
||||
System.out.println("Parallel stream time: " + (t4 - t3) + "ms");
|
||||
|
||||
int result11 = NumberUtils.divideListElements(numbers, 1);
|
||||
System.out.println(result11);
|
||||
|
||||
int result12 = NumberUtils.divideListElementsWithExtractedTryCatchBlock(numbers, 0);
|
||||
System.out.println(result12);
|
||||
}
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
package com.baeldung.streamreduce.entities;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class Rating {
|
||||
|
||||
double points;
|
||||
List<Review> reviews = new ArrayList<>();
|
||||
|
||||
public Rating() {}
|
||||
|
||||
public void add(Review review) {
|
||||
reviews.add(review);
|
||||
computeRating();
|
||||
}
|
||||
|
||||
private double computeRating() {
|
||||
double totalPoints = reviews.stream().map(Review::getPoints).reduce(0, Integer::sum);
|
||||
this.points = totalPoints / reviews.size();
|
||||
return this.points;
|
||||
}
|
||||
|
||||
public static Rating average(Rating r1, Rating r2) {
|
||||
Rating combined = new Rating();
|
||||
combined.reviews = new ArrayList<>(r1.reviews);
|
||||
combined.reviews.addAll(r2.reviews);
|
||||
combined.computeRating();
|
||||
return combined;
|
||||
}
|
||||
|
||||
public double getPoints() {
|
||||
return points;
|
||||
}
|
||||
|
||||
public List<Review> getReviews() {
|
||||
return reviews;
|
||||
}
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
package com.baeldung.streamreduce.entities;
|
||||
|
||||
public class Review {
|
||||
|
||||
int points;
|
||||
String review;
|
||||
|
||||
public Review(int points, String review) {
|
||||
this.points = points;
|
||||
this.review = review;
|
||||
}
|
||||
|
||||
public int getPoints() {
|
||||
return points;
|
||||
}
|
||||
|
||||
public void setPoints(int points) {
|
||||
this.points = points;
|
||||
}
|
||||
|
||||
public String getReview() {
|
||||
return review;
|
||||
}
|
||||
|
||||
public void setReview(String review) {
|
||||
this.review = review;
|
||||
}
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
package com.baeldung.streamreduce.entities;
|
||||
|
||||
public class User {
|
||||
|
||||
private final String name;
|
||||
private final int age;
|
||||
private final Rating rating = new Rating();
|
||||
|
||||
public User(String name, int age) {
|
||||
this.name = name;
|
||||
this.age = age;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public int getAge() {
|
||||
return age;
|
||||
}
|
||||
|
||||
public Rating getRating() {
|
||||
return rating;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "User{" + "name=" + name + ", age=" + age + '}';
|
||||
}
|
||||
}
|
@ -1,52 +0,0 @@
|
||||
package com.baeldung.streamreduce.utilities;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public abstract class NumberUtils {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(NumberUtils.class.getName());
|
||||
|
||||
public static int divideListElements(List<Integer> values, Integer divider) {
|
||||
return values.stream()
|
||||
.reduce(0, (a, b) -> {
|
||||
try {
|
||||
return a / divider + b / divider;
|
||||
} catch (ArithmeticException e) {
|
||||
LOGGER.log(Level.INFO, "Arithmetic Exception: Division by Zero");
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
}
|
||||
|
||||
public static int divideListElementsWithExtractedTryCatchBlock(List<Integer> values, int divider) {
|
||||
return values.stream().reduce(0, (a, b) -> divide(a, divider) + divide(b, divider));
|
||||
}
|
||||
|
||||
public static int divideListElementsWithApplyFunctionMethod(List<Integer> values, int divider) {
|
||||
BiFunction<Integer, Integer, Integer> division = (a, b) -> a / b;
|
||||
return values.stream().reduce(0, (a, b) -> applyFunction(division, a, divider) + applyFunction(division, b, divider));
|
||||
}
|
||||
|
||||
private static int divide(int value, int factor) {
|
||||
int result = 0;
|
||||
try {
|
||||
result = value / factor;
|
||||
} catch (ArithmeticException e) {
|
||||
LOGGER.log(Level.INFO, "Arithmetic Exception: Division by Zero");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static int applyFunction(BiFunction<Integer, Integer, Integer> function, int a, int b) {
|
||||
try {
|
||||
return function.apply(a, b);
|
||||
}
|
||||
catch(Exception e) {
|
||||
LOGGER.log(Level.INFO, "Exception occurred!");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
@ -8,4 +8,5 @@
|
||||
- [Difference Between Arrays.sort() and Collections.sort()](https://www.baeldung.com/java-arrays-collections-sort-methods)
|
||||
- [Skipping the First Iteration in Java](https://www.baeldung.com/java-skip-first-iteration)
|
||||
- [Remove Elements From a Queue Using Loop](https://www.baeldung.com/java-remove-elements-queue)
|
||||
- [Intro to Vector Class in Java](https://www.baeldung.com/java-vector-guide)
|
||||
- More articles: [[<-- prev]](/core-java-modules/core-java-collections-4)
|
||||
|
60
core-java-modules/core-java-collections-5/src/main/java/com/baeldung/collectionssortcomplexity/CollectionsSortTimeComplexityJMH.java
Normal file
60
core-java-modules/core-java-collections-5/src/main/java/com/baeldung/collectionssortcomplexity/CollectionsSortTimeComplexityJMH.java
Normal file
@ -0,0 +1,60 @@
|
||||
package com.baeldung.collectionssortcomplexity;
|
||||
|
||||
import org.openjdk.jmh.annotations.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@BenchmarkMode(Mode.AverageTime)
|
||||
@OutputTimeUnit(TimeUnit.MILLISECONDS)
|
||||
@Fork(value = 1, warmups = 1)
|
||||
@Warmup(iterations = 5, time = 1)
|
||||
@Measurement(iterations = 5, time = 1)
|
||||
public class CollectionsSortTimeComplexityJMH {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
org.openjdk.jmh.Main.main(args);
|
||||
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void measureCollectionsSortBestCase(BestCaseBenchmarkState state) {
|
||||
List<Integer> sortedList = new ArrayList<>(state.sortedList);
|
||||
Collections.sort(sortedList);
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void measureCollectionsSortAverageWorstCase(AverageWorstCaseBenchmarkState state) {
|
||||
List<Integer> unsortedList = new ArrayList<>(state.unsortedList);
|
||||
Collections.sort(unsortedList);
|
||||
}
|
||||
|
||||
@State(Scope.Benchmark)
|
||||
public static class BestCaseBenchmarkState {
|
||||
List<Integer> sortedList;
|
||||
|
||||
@Setup(Level.Trial)
|
||||
public void setUp() {
|
||||
sortedList = new ArrayList<>();
|
||||
for (int i = 1; i <= 1000000; i++) {
|
||||
sortedList.add(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@State(Scope.Benchmark)
|
||||
public static class AverageWorstCaseBenchmarkState {
|
||||
List<Integer> unsortedList;
|
||||
|
||||
@Setup(Level.Trial)
|
||||
public void setUp() {
|
||||
unsortedList = new ArrayList<>();
|
||||
for (int i = 1000000; i > 0; i--) {
|
||||
unsortedList.add(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
33
core-java-modules/core-java-collections-5/src/main/java/com/baeldung/collectionssortcomplexity/CollectionsSortTimeComplexityMain.java
Normal file
33
core-java-modules/core-java-collections-5/src/main/java/com/baeldung/collectionssortcomplexity/CollectionsSortTimeComplexityMain.java
Normal file
@ -0,0 +1,33 @@
|
||||
package com.baeldung.collectionssortcomplexity;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class CollectionsSortTimeComplexityMain {
|
||||
// O(n log n) Time Complexity Example
|
||||
public static void worstAndAverageCasesTimeComplexity() {
|
||||
Integer[] sortedArray = {20, 21, 22, 23, 24, 25, 26, 17, 28, 29, 30, 31, 18, 19, 32, 33, 34, 27, 35};
|
||||
List<Integer> list = Arrays.asList(sortedArray);
|
||||
Collections.shuffle(list);
|
||||
long startTime = System.nanoTime();
|
||||
Collections.sort(list);
|
||||
long endTime = System.nanoTime();
|
||||
System.out.println("Execution Time for O(n log n): " + (endTime - startTime) + " nanoseconds");
|
||||
}
|
||||
|
||||
// O(n) Time Complexity Example
|
||||
public static void bestCaseTimeComplexity() {
|
||||
Integer[] sortedArray = {19, 22, 19, 22, 24, 25, 17, 11, 22, 23, 28, 23, 0, 1, 12, 9, 13, 27, 15};
|
||||
List<Integer> list = Arrays.asList(sortedArray);
|
||||
long startTime = System.nanoTime();
|
||||
Collections.sort(list);
|
||||
long endTime = System.nanoTime();
|
||||
System.out.println("Execution Time for O(n): " + (endTime - startTime) + " nanoseconds");
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
worstAndAverageCasesTimeComplexity();
|
||||
bestCaseTimeComplexity();
|
||||
}
|
||||
}
|
87
core-java-modules/core-java-collections-5/src/test/java/com/baeldung/vectors/VectorOperationsUnitTest.java
Normal file
87
core-java-modules/core-java-collections-5/src/test/java/com/baeldung/vectors/VectorOperationsUnitTest.java
Normal file
@ -0,0 +1,87 @@
|
||||
package com.baeldung.vectors;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Vector;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class VectorOperationsUnitTest {
|
||||
|
||||
private static Vector<String> getVector() {
|
||||
Vector<String> vector = new Vector<String>();
|
||||
vector.add("Today");
|
||||
vector.add("is");
|
||||
vector.add("a");
|
||||
vector.add("great");
|
||||
vector.add("day!");
|
||||
|
||||
return vector;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenAVector_whenAddElementsUsingAddMethod_thenElementsGetAddedAtEnd() {
|
||||
Vector<String> vector = getVector();
|
||||
vector.add("Hello");
|
||||
assertEquals(6, vector.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenAVector_whenUpdateElementAtIndex_thenElementAtIndexGetsUpdated() {
|
||||
Vector<String> vector = getVector();
|
||||
assertEquals(5, vector.size());
|
||||
assertEquals("great", vector.get(3));
|
||||
vector.set(3, "good");
|
||||
assertEquals("good", vector.get(3));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenAVector_whenRemoveAnElement_thenElementGetsRemovedFromTheVector() {
|
||||
Vector<String> vector = getVector();
|
||||
assertEquals(5, vector.size());
|
||||
|
||||
// remove a specific element
|
||||
vector.remove("a");
|
||||
assertEquals(4, vector.size());
|
||||
|
||||
// remove at specific index
|
||||
vector.remove(2);
|
||||
assertEquals("day!", vector.get(2));
|
||||
assertEquals(3, vector.size());
|
||||
|
||||
assertEquals(false, vector.remove("SomethingThatDoesn'tExist"));
|
||||
}
|
||||
|
||||
@Test(expected = ArrayIndexOutOfBoundsException.class)
|
||||
public void givenAVector_whenIndexIsBeyondRange_thenRemoveMethodThrowsArrayIndexOutOfBoundsException() {
|
||||
Vector<String> vector = getVector();
|
||||
assertEquals(5, vector.size());
|
||||
vector.remove(10);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenAVector_whenGetElementWithinARange_thenGetMethodGetsAnElementFromTheVector() {
|
||||
Vector<String> vector = getVector();
|
||||
String fourthElement = vector.get(3);
|
||||
assertEquals("great", fourthElement);
|
||||
}
|
||||
|
||||
@Test(expected = ArrayIndexOutOfBoundsException.class)
|
||||
public void givenAVector_whenGetElementBeyondARange_thenGetMethodThrowsArrayIndexOutOfBoundsException() {
|
||||
Vector<String> vector = getVector();
|
||||
assertEquals(5, vector.size());
|
||||
vector.get(10);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenAVector_whenAddElementFromACollection_thenAllElementsGetAdeddToTheVector() {
|
||||
Vector<String> vector = getVector();
|
||||
assertEquals(5, vector.size());
|
||||
ArrayList<String> words = new ArrayList<>(Arrays.asList("Baeldung", "is", "cool!"));
|
||||
vector.addAll(words);
|
||||
assertEquals(8, vector.size());
|
||||
assertEquals("cool!", vector.get(7));
|
||||
}
|
||||
}
|
51
core-java-modules/core-java-collections-5/toarraymethod/ConvertingHashSetToArrayUnitTest.java
Normal file
51
core-java-modules/core-java-collections-5/toarraymethod/ConvertingHashSetToArrayUnitTest.java
Normal file
@ -0,0 +1,51 @@
|
||||
package com.baeldung.toarraymethod;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.HashSet;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class ConvertingHashSetToArrayUnitTest {
|
||||
|
||||
@Test
|
||||
public void givenStringHashSet_whenConvertedToArray_thenArrayContainsStringElements() {
|
||||
HashSet<String> stringSet = new HashSet<>();
|
||||
stringSet.add("Apple");
|
||||
stringSet.add("Banana");
|
||||
stringSet.add("Cherry");
|
||||
|
||||
// Convert the HashSet of Strings to an array of Strings
|
||||
String[] stringArray = stringSet.toArray(new String[0]);
|
||||
|
||||
// Test that the array is of the correct length
|
||||
assertEquals(3, stringArray.length);
|
||||
|
||||
for (String str : stringArray) {
|
||||
assertTrue(stringSet.contains(str));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenIntegerHashSet_whenConvertedToArray_thenArrayContainsIntegerElements() {
|
||||
HashSet<Integer> integerSet = new HashSet<>();
|
||||
integerSet.add(5);
|
||||
integerSet.add(10);
|
||||
integerSet.add(15);
|
||||
|
||||
// Convert the HashSet of Integers to an array of Integers
|
||||
Integer[] integerArray = integerSet.toArray(new Integer[0]);
|
||||
|
||||
// Test that the array is of the correct length
|
||||
assertEquals(3, integerArray.length);
|
||||
|
||||
for (Integer num : integerArray) {
|
||||
assertTrue(integerSet.contains(num));
|
||||
}
|
||||
|
||||
assertTrue(integerSet.contains(5));
|
||||
assertTrue(integerSet.contains(10));
|
||||
assertTrue(integerSet.contains(15));
|
||||
}
|
||||
}
|
@ -44,6 +44,6 @@
|
||||
<properties>
|
||||
<vavr.version>0.10.3</vavr.version>
|
||||
<java.version>11</java.version>
|
||||
<modelmapper.version>3.1.1</modelmapper.version>
|
||||
<modelmapper.version>3.2.0</modelmapper.version>
|
||||
</properties>
|
||||
</project>
|
@ -1,8 +1,9 @@
|
||||
package com.baeldung.modelmapper;
|
||||
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.modelmapper.ModelMapper;
|
||||
import org.modelmapper.TypeMap;
|
||||
import org.modelmapper.TypeToken;
|
||||
@ -10,11 +11,10 @@ import org.modelmapper.TypeToken;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.hasItems;
|
||||
import static org.hamcrest.Matchers.hasProperty;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
|
||||
/**
|
||||
* This class has test methods of mapping Integer to Character list,
|
||||
@ -22,12 +22,12 @@ import static org.junit.Assert.assertThat;
|
||||
*
|
||||
* @author Sasa Milenkovic
|
||||
*/
|
||||
public class UsersListMappingUnitTest {
|
||||
class UsersListMappingUnitTest {
|
||||
|
||||
private ModelMapper modelMapper;
|
||||
private List<User> users;
|
||||
|
||||
@Before
|
||||
@BeforeEach
|
||||
public void init() {
|
||||
|
||||
modelMapper = new ModelMapper();
|
||||
@ -35,18 +35,16 @@ public class UsersListMappingUnitTest {
|
||||
TypeMap<UserList, UserListDTO> typeMap = modelMapper.createTypeMap(UserList.class, UserListDTO.class);
|
||||
|
||||
typeMap.addMappings(mapper -> mapper.using(new UsersListConverter())
|
||||
.map(UserList::getUsers, UserListDTO::setUsernames));
|
||||
.map(UserList::getUsers, UserListDTO::setUsernames));
|
||||
|
||||
users = new ArrayList();
|
||||
users = new ArrayList<>();
|
||||
users.add(new User("b100", "user1", "user1@baeldung.com", "111-222", "USER"));
|
||||
users.add(new User("b101", "user2", "user2@baeldung.com", "111-333", "USER"));
|
||||
users.add(new User("b102", "user3", "user3@baeldung.com", "111-444", "ADMIN"));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenInteger_thenMapToCharacter() {
|
||||
|
||||
void whenInteger_thenMapToCharacter() {
|
||||
List<Integer> integers = new ArrayList<Integer>();
|
||||
|
||||
integers.add(1);
|
||||
@ -57,36 +55,27 @@ public class UsersListMappingUnitTest {
|
||||
}.getType());
|
||||
|
||||
assertThat(characters, hasItems('1', '2', '3'));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenUsersList_whenUseGenericType_thenMapToUserDTO() {
|
||||
|
||||
void givenUsersList_whenUseGenericType_thenMapToUserDTO() {
|
||||
// Mapping lists using custom (generic) type mapping
|
||||
|
||||
List<UserDTO> userDtoList = MapperUtil.mapList(users, UserDTO.class);
|
||||
|
||||
assertThat(userDtoList, Matchers.<UserDTO>hasItem(
|
||||
Matchers.both(hasProperty("userId", equalTo("b100")))
|
||||
.and(hasProperty("email", equalTo("user1@baeldung.com")))
|
||||
.and(hasProperty("username", equalTo("user1")))));
|
||||
|
||||
|
||||
assertThat(userDtoList, Matchers.<UserDTO> hasItem(Matchers.both(hasProperty("userId", equalTo("b100")))
|
||||
.and(hasProperty("email", equalTo("user1@baeldung.com")))
|
||||
.and(hasProperty("username", equalTo("user1")))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenUsersList_whenUseConverter_thenMapToUsernames() {
|
||||
|
||||
void givenUsersList_whenUseConverter_thenMapToUsernames() {
|
||||
// Mapping lists using property mapping and converter
|
||||
|
||||
UserList userList = new UserList();
|
||||
userList.setUsers(users);
|
||||
UserListDTO dtos = new UserListDTO();
|
||||
modelMapper.map(userList, dtos);
|
||||
|
||||
assertThat(dtos.getUsernames(), hasItems("user1", "user2", "user3"));
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,3 +1,7 @@
|
||||
## Relevant Articles
|
||||
## Relevant Articles:
|
||||
- [Difference Between putIfAbsent() and computeIfAbsent() in Java’s Map](https://www.baeldung.com/java-map-putifabsent-computeifabsent)
|
||||
- [How to Write and Read a File with a Java HashMap](https://www.baeldung.com/how-to-write-and-read-a-file-with-a-java-hashmap/)
|
||||
- [How to Write Hashmap to CSV File](https://www.baeldung.com/java-write-hashmap-csv)
|
||||
- [How to Get First or Last Entry From a LinkedHashMap in Java](https://www.baeldung.com/java-linkedhashmap-first-last-key-value-pair)
|
||||
- [How to Write and Read a File with a Java HashMap](https://www.baeldung.com/java-hashmap-write-read-file)
|
||||
- More articles: [[<-- prev]](/core-java-modules/core-java-collections-maps-6)
|
@ -1,11 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>core-java-collections-maps-7</artifactId>
|
||||
<name>core-java-collections-maps-7</name>
|
||||
<packaging>jar</packaging>
|
||||
<properties>
|
||||
<gson.version>2.10.1</gson.version>
|
||||
<csv.version>1.5</csv.version>
|
||||
</properties>
|
||||
|
||||
<parent>
|
||||
<artifactId>core-java-modules</artifactId>
|
||||
@ -13,71 +17,35 @@
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
<spring.version>5.2.5.RELEASE</spring.version>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>2.12.4</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openjdk.jmh</groupId>
|
||||
<artifactId>jmh-core</artifactId>
|
||||
<version>1.36</version>
|
||||
<version>${jackson.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<version>2.8.9</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.json</groupId>
|
||||
<artifactId>json</artifactId>
|
||||
<version>20230227</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.13.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter</artifactId>
|
||||
<version>5.8.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter</artifactId>
|
||||
<version>5.8.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.13.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter</artifactId>
|
||||
<version>5.8.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.13.1</version>
|
||||
<scope>test</scope>
|
||||
<version>${gson.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-csv</artifactId>
|
||||
<version>1.5</version>
|
||||
<version>${csv.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<argLine>
|
||||
--add-opens java.base/java.util=ALL-UNNAMED
|
||||
</argLine>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
|
51
core-java-modules/core-java-collections-maps-7/src/main/java/com/baeldung/map/readandwritefile/Student.java
Normal file
51
core-java-modules/core-java-collections-maps-7/src/main/java/com/baeldung/map/readandwritefile/Student.java
Normal file
@ -0,0 +1,51 @@
|
||||
package com.baeldung.map.readandwritefile;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Objects;
|
||||
|
||||
public class Student implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private String firstName;
|
||||
private String lastName;
|
||||
|
||||
/** Default constructor for JSON serialization */
|
||||
public Student() {
|
||||
|
||||
}
|
||||
|
||||
public Student(String firstName, String lastName) {
|
||||
this.firstName = firstName;
|
||||
this.lastName = lastName;
|
||||
}
|
||||
|
||||
public void setFirstName(String firstName) {
|
||||
this.firstName = firstName;
|
||||
}
|
||||
|
||||
public void setLastName(String lastName) {
|
||||
this.lastName = lastName;
|
||||
}
|
||||
|
||||
public String getFirstName() {
|
||||
return firstName;
|
||||
}
|
||||
|
||||
public String getLastName() {
|
||||
return lastName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o)
|
||||
return true;
|
||||
if (o == null || getClass() != o.getClass())
|
||||
return false;
|
||||
Student student = (Student) o;
|
||||
return Objects.equals(firstName, student.firstName) && Objects.equals(lastName, student.lastName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return super.hashCode();
|
||||
}
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
package com.baeldung.map.linkedhashmapfirstandlastentry;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
public class GetFirstAndLastEntryFromLinkedHashMapUnitTest {
|
||||
private static final LinkedHashMap<String, String> THE_MAP = new LinkedHashMap<>();
|
||||
|
||||
static {
|
||||
THE_MAP.put("key one", "a1 b1 c1");
|
||||
THE_MAP.put("key two", "a2 b2 c2");
|
||||
THE_MAP.put("key three", "a3 b3 c3");
|
||||
THE_MAP.put("key four", "a4 b4 c4");
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenIteratingEntrySet_thenGetExpectedResult() {
|
||||
Entry<String, String> firstEntry = THE_MAP.entrySet().iterator().next();
|
||||
assertEquals("key one", firstEntry.getKey());
|
||||
assertEquals("a1 b1 c1", firstEntry.getValue());
|
||||
|
||||
Entry<String, String> lastEntry = null;
|
||||
Iterator<Entry<String, String>> it = THE_MAP.entrySet().iterator();
|
||||
while (it.hasNext()) {
|
||||
lastEntry = it.next();
|
||||
}
|
||||
|
||||
assertNotNull(lastEntry);
|
||||
assertEquals("key four", lastEntry.getKey());
|
||||
assertEquals("a4 b4 c4", lastEntry.getValue());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenConvertingEntriesToArray_thenGetExpectedResult() {
|
||||
|
||||
Entry<String, String>[] theArray = new Entry[THE_MAP.size()];
|
||||
THE_MAP.entrySet().toArray(theArray);
|
||||
|
||||
Entry<String, String> firstEntry = theArray[0];
|
||||
assertEquals("key one", firstEntry.getKey());
|
||||
assertEquals("a1 b1 c1", firstEntry.getValue());
|
||||
|
||||
Entry<String, String> lastEntry = theArray[THE_MAP.size() - 1];
|
||||
assertEquals("key four", lastEntry.getKey());
|
||||
assertEquals("a4 b4 c4", lastEntry.getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenUsingStreamAPI_thenGetExpectedResult() {
|
||||
Entry<String, String> firstEntry = THE_MAP.entrySet().stream().findFirst().get();
|
||||
assertEquals("key one", firstEntry.getKey());
|
||||
assertEquals("a1 b1 c1", firstEntry.getValue());
|
||||
|
||||
Entry<String, String> lastEntry = THE_MAP.entrySet().stream().skip(THE_MAP.size() - 1).findFirst().get();
|
||||
|
||||
assertNotNull(lastEntry);
|
||||
assertEquals("key four", lastEntry.getKey());
|
||||
assertEquals("a4 b4 c4", lastEntry.getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenUsingReflection_thenGetExpectedResult() throws NoSuchFieldException, IllegalAccessException {
|
||||
Field head = THE_MAP.getClass().getDeclaredField("head");
|
||||
head.setAccessible(true);
|
||||
Entry<String, String> firstEntry = (Entry<String, String>) head.get(THE_MAP);
|
||||
assertEquals("key one", firstEntry.getKey());
|
||||
assertEquals("a1 b1 c1", firstEntry.getValue());
|
||||
|
||||
Field tail = THE_MAP.getClass().getDeclaredField("tail");
|
||||
tail.setAccessible(true);
|
||||
Entry<String, String> lastEntry = (Entry<String, String>) tail.get(THE_MAP);
|
||||
assertEquals("key four", lastEntry.getKey());
|
||||
assertEquals("a4 b4 c4", lastEntry.getValue());
|
||||
}
|
||||
|
||||
|
||||
}
|
135
core-java-modules/core-java-collections-maps-7/src/test/java/com/baeldung/map/readandwritefile/ReadAndWriteFileWithHashMapUnitTest.java
Normal file
135
core-java-modules/core-java-collections-maps-7/src/test/java/com/baeldung/map/readandwritefile/ReadAndWriteFileWithHashMapUnitTest.java
Normal file
@ -0,0 +1,135 @@
|
||||
package com.baeldung.map.readandwritefile;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.lang.reflect.Type;
|
||||
import java.nio.file.Files;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.junit.Before;
|
||||
|
||||
public class ReadAndWriteFileWithHashMapUnitTest {
|
||||
|
||||
private static final Map<Integer, Student> STUDENT_DATA = new HashMap<>();
|
||||
|
||||
static {
|
||||
STUDENT_DATA.put(1234, new Student("Henry", "Winter"));
|
||||
STUDENT_DATA.put(5678, new Student("Richard", "Papen"));
|
||||
}
|
||||
|
||||
private File file;
|
||||
|
||||
@Before
|
||||
public void createFile() throws IOException {
|
||||
file = File.createTempFile("student", ".data");
|
||||
}
|
||||
|
||||
@After
|
||||
public void deleteFile() {
|
||||
file.delete();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenHashMap_whenWrittenAsPropertiesFile_thenReloadedMapIsIdentical() throws IOException {
|
||||
// Given a map containing student data
|
||||
Map<String, String> studentData = new HashMap<>();
|
||||
studentData.put("student.firstName", "Henry");
|
||||
studentData.put("student.lastName", "Winter");
|
||||
|
||||
// When converting to a Properties object and writing to a file
|
||||
Properties props = new Properties();
|
||||
props.putAll(studentData);
|
||||
try (OutputStream output = Files.newOutputStream(file.toPath())) {
|
||||
props.store(output, null);
|
||||
}
|
||||
|
||||
// Then the map resulting from loading the Properties file is identical
|
||||
Properties propsFromFile = new Properties();
|
||||
try (InputStream input = Files.newInputStream(file.toPath())) {
|
||||
propsFromFile.load(input);
|
||||
}
|
||||
|
||||
Map<String, String> studentDataFromProps = propsFromFile.stringPropertyNames()
|
||||
.stream()
|
||||
.collect(Collectors.toMap(key -> key, props::getProperty));
|
||||
assertThat(studentDataFromProps).isEqualTo(studentData);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenHashMap_whenSerializedToFile_thenDeserializedMapIsIdentical() throws IOException, ClassNotFoundException {
|
||||
// Given a map containing student data (STUDENT_DATA)
|
||||
|
||||
// When serializing the map to a file
|
||||
try (FileOutputStream fileOutput = new FileOutputStream(file); ObjectOutputStream objectStream = new ObjectOutputStream(fileOutput)) {
|
||||
objectStream.writeObject(STUDENT_DATA);
|
||||
}
|
||||
|
||||
// Then read the file back into a map and check the contents
|
||||
Map<Integer, Student> studentsFromFile;
|
||||
try (FileInputStream fileReader = new FileInputStream(file); ObjectInputStream objectStream = new ObjectInputStream(fileReader)) {
|
||||
studentsFromFile = (HashMap<Integer, Student>) objectStream.readObject();
|
||||
}
|
||||
assertThat(studentsFromFile).isEqualTo(STUDENT_DATA);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenHashMap_whenSerializedToFileWithJackson_thenDeserializedMapIsIdentical() throws IOException {
|
||||
// Given a map containing student data (STUDENT_DATA)
|
||||
|
||||
// When converting to JSON with Jackson and writing to a file
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
try (FileOutputStream fileOutput = new FileOutputStream(file)) {
|
||||
mapper.writeValue(fileOutput, STUDENT_DATA);
|
||||
}
|
||||
|
||||
// Then deserialize the file back into a map and check that it's identical
|
||||
Map<Integer, Student> mapFromFile;
|
||||
try (FileInputStream fileInput = new FileInputStream(file)) {
|
||||
// Create a TypeReference so we can deserialize the parameterized type
|
||||
TypeReference<HashMap<Integer, Student>> mapType = new TypeReference<HashMap<Integer, Student>>() {
|
||||
};
|
||||
mapFromFile = mapper.readValue(fileInput, mapType);
|
||||
}
|
||||
assertThat(mapFromFile).isEqualTo(STUDENT_DATA);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenHashMap_whenSerializedToFileWithGson_thenDeserializedMapIsIdentical() throws IOException {
|
||||
// Given a map containing student data (STUDENT_DATA)
|
||||
|
||||
// When converting to JSON using Gson and writing to a file
|
||||
Gson gson = new Gson();
|
||||
try (FileWriter writer = new FileWriter(file)) {
|
||||
gson.toJson(STUDENT_DATA, writer);
|
||||
}
|
||||
|
||||
// Then deserialize the file back into a map and check that it's identical
|
||||
Map<Integer, Student> studentsFromFile;
|
||||
try (FileReader reader = new FileReader(file)) {
|
||||
Type mapType = new TypeToken<HashMap<Integer, Student>>() {
|
||||
}.getType();
|
||||
studentsFromFile = gson.fromJson(reader, mapType);
|
||||
}
|
||||
assertThat(studentsFromFile).isEqualTo(STUDENT_DATA);
|
||||
}
|
||||
}
|
@ -0,0 +1,126 @@
|
||||
package com.baeldung.exceptions_completablefuture;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.assertj.core.api.Assertions;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
public class CompletableFutureExceptionsHandlingUnitTest {
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("parametersSource_handle")
|
||||
void whenCompletableFutureIsScheduled_thenHandleStageIsAlwaysInvoked(int radius, long expected)
|
||||
throws ExecutionException, InterruptedException {
|
||||
long actual = CompletableFuture
|
||||
.supplyAsync(() -> {
|
||||
if (radius <= 0) {
|
||||
throw new IllegalArgumentException("Supplied with non-positive radius '%d'");
|
||||
}
|
||||
return Math.round(Math.pow(radius, 2) * Math.PI);
|
||||
})
|
||||
.handle((result, ex) -> {
|
||||
if (ex == null) {
|
||||
return result;
|
||||
} else {
|
||||
return -1L;
|
||||
}
|
||||
})
|
||||
.get();
|
||||
|
||||
Assertions.assertThat(actual).isEqualTo(expected);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("parametersSource_exceptionally")
|
||||
void whenCompletableFutureIsScheduled_thenExceptionallyExecutedOnlyOnFailure(int a, int b, int c, long expected)
|
||||
throws ExecutionException, InterruptedException {
|
||||
long actual = CompletableFuture
|
||||
.supplyAsync(() -> {
|
||||
if (a <= 0 || b <= 0 || c <= 0) {
|
||||
throw new IllegalArgumentException(String.format("Supplied with incorrect edge length [%s]", List.of(a, b, c)));
|
||||
}
|
||||
return a * b * c;
|
||||
})
|
||||
.exceptionally((ex) -> -1)
|
||||
.get();
|
||||
|
||||
Assertions.assertThat(actual).isEqualTo(expected);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("parametersSource_exceptionally")
|
||||
void givenCompletableFutureIsScheduled_whenHandleIsAlreadyPresent_thenExceptionallyIsNotExecuted(int a, int b, int c, long expected)
|
||||
throws ExecutionException, InterruptedException {
|
||||
long actual = CompletableFuture
|
||||
.supplyAsync(() -> {
|
||||
if (a <= 0 || b <= 0 || c <= 0) {
|
||||
throw new IllegalArgumentException(String.format("Supplied with incorrect edge length [%s]", List.of(a, b, c)));
|
||||
}
|
||||
return a * b * c;
|
||||
})
|
||||
.handle((result, throwable) -> {
|
||||
if (throwable != null) {
|
||||
return -1;
|
||||
}
|
||||
return result;
|
||||
})
|
||||
.exceptionally((ex) -> {
|
||||
System.exit(1);
|
||||
return 0;
|
||||
})
|
||||
.get();
|
||||
|
||||
Assertions.assertThat(actual).isEqualTo(expected);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("parametersSource_whenComplete")
|
||||
void whenCompletableFutureIsScheduled_thenWhenCompletedExecutedAlways(Double a, long expected, Class<Exception> ifAny) {
|
||||
try {
|
||||
CountDownLatch countDownLatch = new CountDownLatch(1);
|
||||
|
||||
long actual = CompletableFuture
|
||||
.supplyAsync(() -> {
|
||||
if (a.isNaN()) {
|
||||
throw new IllegalArgumentException("Supplied value is NaN");
|
||||
}
|
||||
return Math.round(Math.pow(a, 2));
|
||||
})
|
||||
.whenComplete((result, exception) -> countDownLatch.countDown())
|
||||
.get();
|
||||
|
||||
Assertions.assertThat(countDownLatch.await(20L, java.util.concurrent.TimeUnit.SECONDS));
|
||||
Assertions.assertThat(actual).isEqualTo(expected);
|
||||
} catch (Exception e) {
|
||||
Assertions.assertThat(e.getClass()).isSameAs(ExecutionException.class);
|
||||
Assertions.assertThat(e.getCause().getClass()).isSameAs(ifAny);
|
||||
}
|
||||
}
|
||||
|
||||
static Stream<Arguments> parametersSource_handle() {
|
||||
return Stream.of(
|
||||
Arguments.of(1, 3),
|
||||
Arguments.of(-1, -1)
|
||||
);
|
||||
}
|
||||
|
||||
static Stream<Arguments> parametersSource_exceptionally() {
|
||||
return Stream.of(
|
||||
Arguments.of(1, 5, 5, 25),
|
||||
Arguments.of(-1, 10, 15, -1)
|
||||
);
|
||||
}
|
||||
|
||||
static Stream<Arguments> parametersSource_whenComplete() {
|
||||
return Stream.of(
|
||||
Arguments.of(2d, 4, null),
|
||||
Arguments.of(Double.NaN, 1, IllegalArgumentException.class)
|
||||
);
|
||||
}
|
||||
}
|
@ -11,4 +11,5 @@ This module contains articles about basic Java concurrency.
|
||||
- [CompletableFuture and ThreadPool in Java](https://www.baeldung.com/java-completablefuture-threadpool)
|
||||
- [CompletableFuture allOf().join() vs. CompletableFuture.join()](https://www.baeldung.com/java-completablefuture-allof-join)
|
||||
- [Retry Logic with CompletableFuture](https://www.baeldung.com/java-completablefuture-retry-logic)
|
||||
- [Convert From List of CompletableFuture to CompletableFuture List](https://www.baeldung.com/java-completablefuture-list-convert)
|
||||
- [[<-- Prev]](../core-java-concurrency-basic-2)
|
||||
|
30
core-java-modules/core-java-concurrency-basic-3/src/main/java/com/baeldung/concurrent/synchronizestatic/atomicinteger/Employee.java
Normal file
30
core-java-modules/core-java-concurrency-basic-3/src/main/java/com/baeldung/concurrent/synchronizestatic/atomicinteger/Employee.java
Normal file
@ -0,0 +1,30 @@
|
||||
package com.baeldung.concurrent.synchronizestatic.atomicinteger;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* Synchronizing static variable with AtomicInteger.
|
||||
*/
|
||||
public class Employee {
|
||||
|
||||
private static final AtomicInteger count = new AtomicInteger(0);
|
||||
|
||||
int id;
|
||||
String name;
|
||||
String title;
|
||||
|
||||
public Employee(int id, String name, String title) {
|
||||
incrementCount();
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
private static void incrementCount() {
|
||||
count.incrementAndGet();
|
||||
}
|
||||
|
||||
public static int getCount() {
|
||||
return count.get();
|
||||
}
|
||||
}
|
27
core-java-modules/core-java-concurrency-basic-3/src/main/java/com/baeldung/concurrent/synchronizestatic/none/Employee.java
Normal file
27
core-java-modules/core-java-concurrency-basic-3/src/main/java/com/baeldung/concurrent/synchronizestatic/none/Employee.java
Normal file
@ -0,0 +1,27 @@
|
||||
package com.baeldung.concurrent.synchronizestatic.none;
|
||||
|
||||
/**
|
||||
* No synchronization.
|
||||
*/
|
||||
public class Employee {
|
||||
|
||||
static int count;
|
||||
int id;
|
||||
String name;
|
||||
String title;
|
||||
|
||||
public Employee(int id, String name, String title) {
|
||||
incrementCount();
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
private static void incrementCount() {
|
||||
System.out.println("Count = " + ++count);
|
||||
}
|
||||
|
||||
public static Integer getCount() {
|
||||
return count;
|
||||
}
|
||||
}
|
43
core-java-modules/core-java-concurrency-basic-3/src/main/java/com/baeldung/concurrent/synchronizestatic/reentrantlock/Employee.java
Normal file
43
core-java-modules/core-java-concurrency-basic-3/src/main/java/com/baeldung/concurrent/synchronizestatic/reentrantlock/Employee.java
Normal file
@ -0,0 +1,43 @@
|
||||
package com.baeldung.concurrent.synchronizestatic.reentrantlock;
|
||||
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
/**
|
||||
* Synchronizing static variable with a Reenatrant Lock.
|
||||
*/
|
||||
public class Employee {
|
||||
|
||||
private static final ReentrantLock lock = new ReentrantLock();
|
||||
|
||||
static int count;
|
||||
int id;
|
||||
String name;
|
||||
String title;
|
||||
|
||||
public Employee(int id, String name, String title) {
|
||||
incrementCount();
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
private static void incrementCount() {
|
||||
lock.lock();
|
||||
try {
|
||||
System.out.println("Count = " + ++count);
|
||||
}
|
||||
finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public static int getCount() {
|
||||
lock.lock();
|
||||
try {
|
||||
return count;
|
||||
}
|
||||
finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
33
core-java-modules/core-java-concurrency-basic-3/src/main/java/com/baeldung/concurrent/synchronizestatic/synchronizedblock/Employee.java
Normal file
33
core-java-modules/core-java-concurrency-basic-3/src/main/java/com/baeldung/concurrent/synchronizestatic/synchronizedblock/Employee.java
Normal file
@ -0,0 +1,33 @@
|
||||
package com.baeldung.concurrent.synchronizestatic.synchronizedblock;
|
||||
|
||||
/**
|
||||
* Synchronizing static variable with a synchronized block.
|
||||
*/
|
||||
public class Employee {
|
||||
|
||||
private static final Object lock = new Object();
|
||||
|
||||
static int count;
|
||||
int id;
|
||||
String name;
|
||||
String title;
|
||||
|
||||
public Employee(int id, String name, String title) {
|
||||
incrementCount();
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
private static void incrementCount() {
|
||||
synchronized(lock) {
|
||||
System.out.println("Count = " + ++count);
|
||||
}
|
||||
}
|
||||
|
||||
public static int getCount() {
|
||||
synchronized(lock) {
|
||||
return count;
|
||||
}
|
||||
}
|
||||
}
|
31
core-java-modules/core-java-concurrency-basic-3/src/main/java/com/baeldung/concurrent/synchronizestatic/synchronizedclass/Employee.java
Normal file
31
core-java-modules/core-java-concurrency-basic-3/src/main/java/com/baeldung/concurrent/synchronizestatic/synchronizedclass/Employee.java
Normal file
@ -0,0 +1,31 @@
|
||||
package com.baeldung.concurrent.synchronizestatic.synchronizedclass;
|
||||
|
||||
/**
|
||||
* Synchronizing static variable with a synchronized block.
|
||||
*/
|
||||
public class Employee
|
||||
{
|
||||
static int count;
|
||||
int id;
|
||||
String name;
|
||||
String title;
|
||||
|
||||
public Employee(int id, String name, String title) {
|
||||
incrementCount();
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
private static void incrementCount() {
|
||||
synchronized(Employee.class) {
|
||||
System.out.println("Count = " + ++count);
|
||||
}
|
||||
}
|
||||
|
||||
public static int getCount() {
|
||||
synchronized(Employee.class) {
|
||||
return count;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
package com.baeldung.concurrent.synchronizestatic.synchronizedmethod;
|
||||
|
||||
/**
|
||||
* Synchronizing static variable with a synchronized method.
|
||||
*/
|
||||
public class Employee {
|
||||
static int count;
|
||||
int id;
|
||||
String name;
|
||||
String title;
|
||||
|
||||
public Employee(int id, String name, String title)
|
||||
{
|
||||
incrementCount();
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
private static synchronized void incrementCount() {
|
||||
System.out.println("Count = " + ++count);
|
||||
}
|
||||
|
||||
public static synchronized int getCount() {
|
||||
return count;
|
||||
}
|
||||
}
|
@ -0,0 +1,90 @@
|
||||
package com.baeldung.concurrent.synchronizestatic;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
/**
|
||||
* The tests in this class show the output of creating multiple
|
||||
* types of Employee classes in the <code>synchronizedstatic</code>
|
||||
* package. When not synchronized the out will not be sequential;
|
||||
* when it is synchronized the output will be in sequential.
|
||||
*/
|
||||
public class SychronizeStaticDataUnitTest {
|
||||
private final Executor pool = Executors.newFixedThreadPool(4);
|
||||
|
||||
private final int numberToTest = 100;
|
||||
|
||||
@Test
|
||||
public void whenNotSynchronized_thenDataOutOfOrder() {
|
||||
|
||||
System.out.println("No synchronization");
|
||||
|
||||
for(int i = 0; i < numberToTest; i++) {
|
||||
int finalI = i;
|
||||
pool.execute(() -> {
|
||||
new com.baeldung.concurrent.synchronizestatic.none.Employee(finalI, "John", "Smith");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenSynchronizedMethod_thenDataInOrder() {
|
||||
|
||||
System.out.println("Synchronization with synchronized method");
|
||||
|
||||
for(int i = 0; i < numberToTest; i++) {
|
||||
int finalI = i;
|
||||
pool.execute(() -> {
|
||||
new com.baeldung.concurrent.synchronizestatic.synchronizedmethod.Employee(finalI, "John", "Smith");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenSynchronizedClass_thenDataInOrder() {
|
||||
|
||||
System.out.println("Synchronization with synchronized block on class");
|
||||
|
||||
for(int i = 0; i < numberToTest; i++) {
|
||||
int finalI = i;
|
||||
pool.execute(() -> {
|
||||
new com.baeldung.concurrent.synchronizestatic.synchronizedclass.Employee(finalI, "John", "Smith");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenSynchronizedBlock_thenDataInOrder() {
|
||||
|
||||
System.out.println("Synchronization with synchronized block on a private object");
|
||||
|
||||
for(int i = 0; i < numberToTest; i++) {
|
||||
int finalI = i;
|
||||
pool.execute(() -> {
|
||||
new com.baeldung.concurrent.synchronizestatic.synchronizedblock.Employee(finalI, "John", "Smith");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenAtomicInteger_thenDataInOrder() {
|
||||
// Not straight forward to test this because we cannot log/print
|
||||
// and increment values in a synchronized fashion like other
|
||||
// tests
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenReentrantLock_thenDataInOrder() {
|
||||
|
||||
System.out.println("Synchronization with ReentrantLock");
|
||||
|
||||
for(int i = 0; i < numberToTest; i++) {
|
||||
int finalI = i;
|
||||
pool.execute(() -> {
|
||||
new com.baeldung.concurrent.synchronizestatic.reentrantlock.Employee(finalI, "John", "Smith");
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -5,7 +5,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>core-java-conditionals</artifactId>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
<name>core-java-compiler</name>
|
||||
<name>core-java-conditionals</name>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<parent>
|
||||
|
@ -29,6 +29,11 @@
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>de.vandermeer</groupId>
|
||||
<artifactId>asciitable</artifactId>
|
||||
<version>${ascii.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
@ -157,6 +162,7 @@
|
||||
<maven-javadoc-plugin.version>3.0.0-M1</maven-javadoc-plugin.version>
|
||||
<source.version>1.8</source.version>
|
||||
<target.version>1.8</target.version>
|
||||
<ascii.version>0.3.2</ascii.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
44
core-java-modules/core-java-console/src/main/java/com/baeldung/consoletableoutput/BodyMassIndex.java
Normal file
44
core-java-modules/core-java-console/src/main/java/com/baeldung/consoletableoutput/BodyMassIndex.java
Normal file
@ -0,0 +1,44 @@
|
||||
package com.baeldung.consoletableoutput;
|
||||
|
||||
public class BodyMassIndex {
|
||||
|
||||
private String name;
|
||||
private double height;
|
||||
private double weight;
|
||||
|
||||
public BodyMassIndex(String name, double height, double weight) {
|
||||
this.name = name;
|
||||
this.height = height;
|
||||
this.weight = weight;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public double getHeight() {
|
||||
return height;
|
||||
}
|
||||
|
||||
public void setHeight(double height) {
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
public double getWeight() {
|
||||
return weight;
|
||||
}
|
||||
|
||||
public void setWeight(double weight) {
|
||||
this.weight = weight;
|
||||
}
|
||||
|
||||
public double calculate() {
|
||||
double bmi = weight / (height * height);
|
||||
String formattedBmi = String.format("%.2f", bmi);
|
||||
return Double.parseDouble(formattedBmi);
|
||||
}
|
||||
}
|
62
core-java-modules/core-java-console/src/main/java/com/baeldung/consoletableoutput/BodyMassIndexApplication.java
Normal file
62
core-java-modules/core-java-console/src/main/java/com/baeldung/consoletableoutput/BodyMassIndexApplication.java
Normal file
@ -0,0 +1,62 @@
|
||||
package com.baeldung.consoletableoutput;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import de.vandermeer.asciitable.AsciiTable;
|
||||
import de.vandermeer.skb.interfaces.transformers.textformat.TextAlignment;
|
||||
|
||||
public class BodyMassIndexApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
stringFormat();
|
||||
asciiTable();
|
||||
|
||||
}
|
||||
|
||||
public static void stringFormat() {
|
||||
List<BodyMassIndex> bodyMassIndices = new ArrayList<>();
|
||||
bodyMassIndices.add(new BodyMassIndex("Tom", 1.8, 80));
|
||||
bodyMassIndices.add(new BodyMassIndex("Elton", 1.9, 90));
|
||||
bodyMassIndices.add(new BodyMassIndex("Harry", 1.9, 90));
|
||||
bodyMassIndices.add(new BodyMassIndex("Hannah", 1.9, 90));
|
||||
|
||||
String leftAlignment = "| %-7s | %-7.2f | %-7.2f | %-5.2f |%n";
|
||||
|
||||
System.out.format("+---------+---------+---------+-------+%n");
|
||||
System.out.format("| Name | Height | Weight | BMI |%n");
|
||||
System.out.format("+---------+---------+---------+-------+%n");
|
||||
|
||||
for (BodyMassIndex bodyMassIndex : bodyMassIndices) {
|
||||
System.out.format(leftAlignment, bodyMassIndex.getName(), bodyMassIndex.getHeight(), bodyMassIndex.getWeight(), bodyMassIndex.calculate());
|
||||
System.out.format("+---------+---------+---------+-------+%n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void asciiTable() {
|
||||
List<BodyMassIndex> bodyMassIndices = new ArrayList<>();
|
||||
bodyMassIndices.add(new BodyMassIndex("Tom", 1.8, 80));
|
||||
bodyMassIndices.add(new BodyMassIndex("Elton", 1.9, 90));
|
||||
bodyMassIndices.add(new BodyMassIndex("Harry", 1.9, 90));
|
||||
bodyMassIndices.add(new BodyMassIndex("Hannah", 1.9, 90));
|
||||
|
||||
AsciiTable asciiTable = new AsciiTable();
|
||||
asciiTable.addRule();
|
||||
asciiTable.addRow("Name", "Height", "Weight", "BMI");
|
||||
asciiTable.addRule();
|
||||
|
||||
for (BodyMassIndex bodyMassIndex : bodyMassIndices) {
|
||||
|
||||
asciiTable.addRow(bodyMassIndex.getName(), bodyMassIndex.getHeight(), bodyMassIndex.getWeight(), bodyMassIndex.calculate());
|
||||
asciiTable.addRule();
|
||||
|
||||
}
|
||||
|
||||
asciiTable.setTextAlignment(TextAlignment.CENTER);
|
||||
String render = asciiTable.render();
|
||||
System.out.println(render);
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -54,7 +54,7 @@
|
||||
</build>
|
||||
|
||||
<properties>
|
||||
<joda-time.version>2.10</joda-time.version>
|
||||
<joda-time.version>2.12.5</joda-time.version>
|
||||
<hirondelle-date4j.version>RELEASE</hirondelle-date4j.version>
|
||||
<maven.compiler.source>1.9</maven.compiler.source>
|
||||
<maven.compiler.target>1.9</maven.compiler.target>
|
||||
|
@ -47,7 +47,7 @@
|
||||
</dependencies>
|
||||
|
||||
<properties>
|
||||
<joda-time.version>2.10</joda-time.version>
|
||||
<joda-time.version>2.12.5</joda-time.version>
|
||||
<hirondelle-date4j.version>1.5.1</hirondelle-date4j.version>
|
||||
<prettytime.version>3.2.7.Final</prettytime.version>
|
||||
<time4j-base.version>5.9</time4j-base.version>
|
||||
|
@ -11,4 +11,6 @@ This module contains articles about date operations in Java.
|
||||
- [Getting Yesterday’s Date in Java](https://www.baeldung.com/java-find-yesterdays-date)
|
||||
- [How to Get the Start and End Dates of a Year Using Java](https://www.baeldung.com/java-date-year-start-end)
|
||||
- [Convert Between Java LocalDate and Epoch](https://www.baeldung.com/java-localdate-epoch)
|
||||
- [Get First Date of Current Month in Java](https://www.baeldung.com/java-current-month-start-date)
|
||||
- [Time Conversions Using TimeUnit](https://www.baeldung.com/java-timeunit-conversion)
|
||||
- [[<-- Prev]](/core-java-modules/core-java-date-operations-2)
|
||||
|
105
core-java-modules/core-java-date-operations-3/src/test/java/com/baeldung/timeunitconversions/TimeUnitConversionsUnitTest.java
Normal file
105
core-java-modules/core-java-date-operations-3/src/test/java/com/baeldung/timeunitconversions/TimeUnitConversionsUnitTest.java
Normal file
@ -0,0 +1,105 @@
|
||||
package com.baeldung.timeunitconversions;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class TimeUnitConversionsUnitTest {
|
||||
|
||||
|
||||
@Test
|
||||
void givenSeconds_whenConvertToMinutes_thenCorrect() {
|
||||
int input = 60;
|
||||
|
||||
long minutes = TimeUnit.MINUTES.convert(input, TimeUnit.SECONDS);
|
||||
|
||||
assertThat(minutes).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenMinutes_whenConvertToSeconds_thenCorrect() {
|
||||
int input = 1;
|
||||
|
||||
long seconds = TimeUnit.SECONDS.convert(input, TimeUnit.MINUTES);
|
||||
|
||||
assertThat(seconds).isEqualTo(60);
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenSeconds_whenToMinutes_thenCorrect() {
|
||||
int input = 60;
|
||||
|
||||
long minutes = TimeUnit.SECONDS.toMinutes(input);
|
||||
|
||||
assertThat(minutes).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenMinutes_whenToSeconds_thenCorrect() {
|
||||
int input = 1;
|
||||
|
||||
long seconds = TimeUnit.MINUTES.toSeconds(input);
|
||||
|
||||
assertThat(seconds).isEqualTo(60);
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenNegativeInput_whenToMinutes_thenCorrect() {
|
||||
int input = -60;
|
||||
|
||||
long minutes = TimeUnit.SECONDS.toMinutes(input);
|
||||
assertThat(minutes).isEqualTo(-1);
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenNonTotalInput_whenToMinutes_thenCorrectTotalResultWithDecimalTruncate() {
|
||||
long positiveUnder = TimeUnit.SECONDS.toMinutes(59);
|
||||
long positiveAbove = TimeUnit.SECONDS.toMinutes(61);
|
||||
|
||||
assertThat(positiveUnder).isEqualTo(0);
|
||||
assertThat(positiveAbove).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenNonTotalNegativeInput_whenToMinutes_thenCorrectTotalResultWithDecimalTruncate() {
|
||||
long negativeUnder = TimeUnit.SECONDS.toMinutes(-59);
|
||||
long negativeAbove = TimeUnit.SECONDS.toMinutes(-61);
|
||||
|
||||
assertThat(negativeUnder).isEqualTo(0);
|
||||
assertThat(negativeAbove).isEqualTo(-1);
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenOverflowInput_whenToMillis_thenTruncatedToLimit() {
|
||||
long maxMillis = TimeUnit.DAYS.toMillis(Long.MAX_VALUE);
|
||||
long minMillis = TimeUnit.DAYS.toMillis(Long.MIN_VALUE);
|
||||
|
||||
assertThat(maxMillis).isEqualTo(Long.MAX_VALUE);
|
||||
assertThat(minMillis).isEqualTo(Long.MIN_VALUE);
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenInput_whenExtractFineTimeUnits_thenCorrect() {
|
||||
long inputSeconds = 3672;
|
||||
|
||||
long hours = TimeUnit.SECONDS.toHours(inputSeconds);
|
||||
|
||||
long secondsRemainingAfterHours = inputSeconds - TimeUnit.HOURS.toSeconds(hours);
|
||||
long minutes = TimeUnit.SECONDS.toMinutes(secondsRemainingAfterHours);
|
||||
|
||||
long seconds = secondsRemainingAfterHours - TimeUnit.MINUTES.toSeconds(minutes);
|
||||
|
||||
|
||||
assertThat(hours).isEqualTo(1);
|
||||
assertThat(minutes).isEqualTo(1);
|
||||
assertThat(seconds).isEqualTo(12);
|
||||
|
||||
assertThat(inputSeconds).isEqualTo(
|
||||
(hours * 60 * 60) +
|
||||
(minutes * 60) +
|
||||
(seconds)
|
||||
);
|
||||
}
|
||||
}
|
@ -54,7 +54,7 @@
|
||||
</build>
|
||||
|
||||
<properties>
|
||||
<joda-time.version>2.10</joda-time.version>
|
||||
<joda-time.version>2.12.5</joda-time.version>
|
||||
<maven.compiler.source>1.9</maven.compiler.source>
|
||||
<maven.compiler.target>1.9</maven.compiler.target>
|
||||
</properties>
|
||||
|
31
core-java-modules/core-java-datetime-conversion/src/main/java/com/baeldung/timestamptolong/TimestampToLong.java
Normal file
31
core-java-modules/core-java-datetime-conversion/src/main/java/com/baeldung/timestamptolong/TimestampToLong.java
Normal file
@ -0,0 +1,31 @@
|
||||
package com.baeldung.timestamptolong;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Date;
|
||||
|
||||
public class TimestampToLong {
|
||||
|
||||
public long usingSimpleDateFormat(String timestampString) throws ParseException {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
Date date = sdf.parse(timestampString);
|
||||
String currentDateString = sdf.format(date);
|
||||
return sdf.parse(currentDateString).getTime();
|
||||
}
|
||||
|
||||
public long usingInstantClass(String timestampString) {
|
||||
Instant instant = LocalDateTime.parse(timestampString, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))
|
||||
.atZone(ZoneId.systemDefault())
|
||||
.toInstant();
|
||||
return instant.toEpochMilli();
|
||||
}
|
||||
|
||||
public long usingJava8DateTime(String timestampString) {
|
||||
LocalDateTime localDateTime = LocalDateTime.parse(timestampString.replace(" ", "T"));
|
||||
return localDateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
|
||||
}
|
||||
}
|
43
core-java-modules/core-java-datetime-conversion/src/test/java/com/baeldung/timestamptolong/TimestampToLongUnitTest.java
Normal file
43
core-java-modules/core-java-datetime-conversion/src/test/java/com/baeldung/timestamptolong/TimestampToLongUnitTest.java
Normal file
@ -0,0 +1,43 @@
|
||||
package com.baeldung.timestamptolong;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Date;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public class TimestampToLongUnitTest {
|
||||
private static final String timestampString = "2023-11-15 01:02:03";
|
||||
|
||||
@Test
|
||||
public void givenSimpleDateFormat_whenFormattingDate_thenConvertToLong() throws ParseException {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
Date date = sdf.parse(timestampString);
|
||||
|
||||
String currentDateString = sdf.format(date);
|
||||
long actualTimestamp = sdf.parse(currentDateString).getTime();
|
||||
assertEquals(1700010123000L, actualTimestamp);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenInstantClass_whenGettingTimestamp_thenConvertToLong() {
|
||||
Instant instant = LocalDateTime.parse(timestampString, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))
|
||||
.atZone(ZoneId.systemDefault())
|
||||
.toInstant();
|
||||
long actualTimestamp = instant.toEpochMilli();
|
||||
assertEquals(1700010123000L, actualTimestamp);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenJava8DateTime_whenGettingTimestamp_thenConvertToLong() {
|
||||
LocalDateTime localDateTime = LocalDateTime.parse(timestampString.replace(" ", "T"));
|
||||
long actualTimestamp = localDateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
|
||||
assertEquals(1700010123000L, actualTimestamp);
|
||||
}
|
||||
}
|
@ -64,7 +64,7 @@
|
||||
</build>
|
||||
|
||||
<properties>
|
||||
<commons-validator.version>1.6</commons-validator.version>
|
||||
<commons-validator.version>1.7</commons-validator.version>
|
||||
<joda-time.version>2.12.5</joda-time.version>
|
||||
<hirondelle-date4j.version>RELEASE</hirondelle-date4j.version>
|
||||
<maven.compiler.source>1.9</maven.compiler.source>
|
||||
|
@ -6,6 +6,7 @@ import java.time.Instant;
|
||||
import java.time.ZoneId;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.temporal.UnsupportedTemporalTypeException;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import org.joda.time.format.DateTimeFormat;
|
||||
import org.junit.Test;
|
||||
@ -17,7 +18,7 @@ public class FormatInstantUnitTest {
|
||||
@Test
|
||||
public void givenInstant_whenUsingDateTimeFormatter_thenFormat() {
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(PATTERN_FORMAT)
|
||||
.withZone(ZoneId.systemDefault());
|
||||
.withZone(TimeZone.getTimeZone("UTC").toZoneId());
|
||||
|
||||
Instant instant = Instant.parse("2022-02-15T18:35:24.00Z");
|
||||
String formattedInstant = formatter.format(instant);
|
||||
|
@ -4,3 +4,4 @@
|
||||
|
||||
- [Introduction to Javadoc](http://www.baeldung.com/javadoc)
|
||||
- [Code Snippets in Java API Documentation](https://www.baeldung.com/java-doc-code-snippets)
|
||||
- [How to Document Generic Type Parameters in Javadoc](https://www.baeldung.com/java-javadoc-generic-type-parameters)
|
||||
|
23
core-java-modules/core-java-documentation/src/main/java/com/baeldung/generictype/Pair.java
Normal file
23
core-java-modules/core-java-documentation/src/main/java/com/baeldung/generictype/Pair.java
Normal file
@ -0,0 +1,23 @@
|
||||
package com.baeldung.generictype;
|
||||
|
||||
/**
|
||||
* @param <T> The type of the first value in the {@code Pair<T,S>}.
|
||||
* @param <S> The type of the second value in the {@code Pair<T,S>}.
|
||||
*/
|
||||
|
||||
public class Pair<T, S> {
|
||||
public T first;
|
||||
public S second;
|
||||
|
||||
/**
|
||||
* Constructs a new Pair object with the specified values.
|
||||
*
|
||||
* @param a The first value.
|
||||
* @param b The second value.
|
||||
*/
|
||||
|
||||
public Pair(T a, S b) {
|
||||
first = a;
|
||||
second = b;
|
||||
}
|
||||
}
|
42
core-java-modules/core-java-hex/test/java/com/baeldung/hextoint/HexToIntConversionUnitTest.java
Normal file
42
core-java-modules/core-java-hex/test/java/com/baeldung/hextoint/HexToIntConversionUnitTest.java
Normal file
@ -0,0 +1,42 @@
|
||||
package com.baeldung.hextoint;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public class HexToIntConversionUnitTest {
|
||||
|
||||
@Test
|
||||
public void givenValidHexString_whenUsingParseInt_thenExpectCorrectDecimalValue() {
|
||||
String hexString = "0x00FF00";
|
||||
int expectedDecimalValue = 65280;
|
||||
|
||||
int decimalValue = Integer.parseInt(hexString.substring(2), 16);
|
||||
|
||||
assertEquals(expectedDecimalValue, decimalValue);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenValidHexString_whenUsingIntegerDecode_thenExpectCorrectDecimalValue() {
|
||||
String hexString = "0x00FF00";
|
||||
int expectedDecimalValue = 65280;
|
||||
|
||||
int decimalValue = Integer.decode(hexString);
|
||||
|
||||
assertEquals(expectedDecimalValue, decimalValue);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenValidHexString_whenUsingBigInteger_thenExpectCorrectDecimalValue() {
|
||||
String hexString = "0x00FF00";
|
||||
int expectedDecimalValue = 65280;
|
||||
|
||||
BigInteger bigIntegerValue = new BigInteger(hexString.substring(2), 16);
|
||||
int decimalValue = bigIntegerValue.intValue();
|
||||
assertEquals(expectedDecimalValue, decimalValue);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -5,5 +5,6 @@ This module contains articles about core Java input and output (IO)
|
||||
### Relevant Articles:
|
||||
- [Get File Extension From MIME Type in Java](https://www.baeldung.com/java-mime-type-file-extension)
|
||||
- [How to Remove Line Breaks From a File in Java](https://www.baeldung.com/java-file-remove-line-breaks)
|
||||
- [Difference Between ZipFile and ZipInputStream in Java](https://www.baeldung.com/java-zipfile-vs-zipinputstream)
|
||||
- [[<-- Prev]](/core-java-modules/core-java-io-4)
|
||||
|
||||
|
@ -8,3 +8,4 @@ This module contains articles about core Java input/output(IO) APIs.
|
||||
- [Check if a File Is Empty in Java](https://www.baeldung.com/java-check-file-empty)
|
||||
- [Converting Relative to Absolute Paths in Java](https://www.baeldung.com/java-from-relative-to-absolute-paths)
|
||||
- [Detect EOF in Java](https://www.baeldung.com/java-file-detect-end-of-file)
|
||||
- [PrintWriter vs. FileWriter in Java](https://www.baeldung.com/java-printwriter-filewriter-difference)
|
||||
|
@ -56,7 +56,7 @@
|
||||
<source.version>11</source.version>
|
||||
<target.version>11</target.version>
|
||||
<json.version>20200518</json.version>
|
||||
<opencsv.version>4.1</opencsv.version>
|
||||
<opencsv.version>5.8</opencsv.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
63
core-java-modules/core-java-io-conversions-2/src/test/java/com/baeldung/filetofrombytearray/FileToByteArrayUnitTest.java
Normal file
63
core-java-modules/core-java-io-conversions-2/src/test/java/com/baeldung/filetofrombytearray/FileToByteArrayUnitTest.java
Normal file
@ -0,0 +1,63 @@
|
||||
package com.baeldung.filetofrombytearray;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class FileToByteArrayUnitTest {
|
||||
|
||||
private static final String FILE_NAME = "src" + File.separator + "test" + File.separator + "resources" + File.separator + "sample.txt";
|
||||
private final byte[] expectedByteArray = { 72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100 };
|
||||
|
||||
@Test
|
||||
void givenFile_whenUsingFileInputStreamClass_thenConvert() throws IOException {
|
||||
File myFile = new File(FILE_NAME);
|
||||
byte[] byteArray = new byte[(int) myFile.length()];
|
||||
try (FileInputStream inputStream = new FileInputStream(myFile)) {
|
||||
inputStream.read(byteArray);
|
||||
}
|
||||
|
||||
assertArrayEquals(expectedByteArray, byteArray);
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenFile_whenUsingNioApiFilesClass_thenConvert() throws IOException {
|
||||
byte[] byteArray = Files.readAllBytes(Paths.get(FILE_NAME));
|
||||
|
||||
assertArrayEquals(expectedByteArray, byteArray);
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenFile_whenUsingApacheCommonsIOUtilsClass_thenConvert() throws IOException {
|
||||
File myFile = new File(FILE_NAME);
|
||||
byte[] byteArray = new byte[(int) myFile.length()];
|
||||
try (FileInputStream inputStream = new FileInputStream(myFile)) {
|
||||
byteArray = IOUtils.toByteArray(inputStream);
|
||||
}
|
||||
|
||||
assertArrayEquals(expectedByteArray, byteArray);
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenFile_whenUsingApacheCommonsFileUtilsClass_thenConvert() throws IOException {
|
||||
byte[] byteArray = FileUtils.readFileToByteArray(new File(FILE_NAME));
|
||||
|
||||
assertArrayEquals(expectedByteArray, byteArray);
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenFile_whenUsingGuavaFilesClass_thenConvert() throws IOException {
|
||||
byte[] byteArray = com.google.common.io.Files.toByteArray(new File(FILE_NAME));
|
||||
|
||||
assertArrayEquals(expectedByteArray, byteArray);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
package com.baeldung.size;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class FileSizeUtils {
|
||||
public static long getFileSizeInBytes(File file) {
|
||||
if (file.exists()) {
|
||||
return file.length();
|
||||
} else {
|
||||
throw new IllegalArgumentException("File not found.");
|
||||
}
|
||||
}
|
||||
|
||||
public static double getFileSizeInKilobytes(File file) {
|
||||
long bytes = getFileSizeInBytes(file);
|
||||
return (double) bytes / 1024;
|
||||
}
|
||||
|
||||
public static double getFileSizeInMegabytes(File file) {
|
||||
double kilobytes = getFileSizeInKilobytes(file);
|
||||
return kilobytes / 1024;
|
||||
}
|
||||
|
||||
public static double getFileSizeInGigabytes(File file) {
|
||||
double megabytes = getFileSizeInMegabytes(file);
|
||||
return megabytes / 1024;
|
||||
}
|
||||
}
|
@ -1,6 +1,8 @@
|
||||
package com.baeldung.size;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
@ -10,9 +12,9 @@ import java.net.URL;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
public class JavaFileSizeUnitTest {
|
||||
private static final long EXPECTED_FILE_SIZE_IN_BYTES = 11;
|
||||
@ -85,4 +87,23 @@ public class JavaFileSizeUnitTest {
|
||||
assertEquals(EXPECTED_FILE_SIZE_IN_BYTES, stream.available());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenGetFileSizeInDifferentUnits_thenCorrect(){
|
||||
filePath = String.join(File.separator, new String[] { "src", "test", "resources", "size", "sample_file_1.in" });
|
||||
File file = new File(filePath);
|
||||
if (file.exists()) {
|
||||
long expectedBytes = file.length();
|
||||
double expectedKilobytes = (double) expectedBytes / 1024;
|
||||
double expectedMegabytes = expectedKilobytes / 1024;
|
||||
double expectedGigabytes = expectedMegabytes / 1024;
|
||||
|
||||
assertEquals(expectedBytes, FileSizeUtils.getFileSizeInBytes(file));
|
||||
assertEquals(expectedKilobytes, FileSizeUtils.getFileSizeInKilobytes(file), 0.01);
|
||||
assertEquals(expectedMegabytes, FileSizeUtils.getFileSizeInMegabytes(file), 0.01);
|
||||
assertEquals(expectedGigabytes, FileSizeUtils.getFileSizeInGigabytes(file), 0.01);
|
||||
} else {
|
||||
fail("File not found.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,3 +4,4 @@
|
||||
- [Java Naming and Directory Interface Overview](https://www.baeldung.com/jndi)
|
||||
- [LDAP Authentication Using Pure Java](https://www.baeldung.com/java-ldap-auth)
|
||||
- [Testing LDAP Connections With Java](https://www.baeldung.com/java-test-ldap-connections)
|
||||
- [JNDI – What Is java:comp/env?](https://www.baeldung.com/java-jndi-comp-env)
|
||||
|
72
core-java-modules/core-java-jndi/src/test/java/com/baeldung/jndi/JndiNamingUnitTest.java
Normal file
72
core-java-modules/core-java-jndi/src/test/java/com/baeldung/jndi/JndiNamingUnitTest.java
Normal file
@ -0,0 +1,72 @@
|
||||
package com.baeldung.jndi;
|
||||
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.jdbc.datasource.DriverManagerDataSource;
|
||||
import org.springframework.jndi.JndiTemplate;
|
||||
import org.springframework.mock.jndi.SimpleNamingContextBuilder;
|
||||
|
||||
import javax.naming.*;
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import java.util.Enumeration;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class JndiNamingUnitTest {
|
||||
|
||||
private static InitialContext context;
|
||||
private static DriverManagerDataSource dataSource;
|
||||
|
||||
@BeforeAll
|
||||
static void setUp() throws Exception {
|
||||
SimpleNamingContextBuilder builder = new SimpleNamingContextBuilder();
|
||||
dataSource = new DriverManagerDataSource("jdbc:h2:mem:mydb");
|
||||
builder.activate();
|
||||
|
||||
JndiTemplate jndiTemplate = new JndiTemplate();
|
||||
context = (InitialContext) jndiTemplate.getContext();
|
||||
|
||||
dataSource.setDriverClassName("org.h2.Driver");
|
||||
context.bind("java:comp/env/jdbc/datasource", dataSource);
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenACompositeName_whenAddingAnElement_thenNameIsAdded() throws Exception {
|
||||
Name objectName = new CompositeName("java:comp/env/jdbc");
|
||||
|
||||
Enumeration<String> items = objectName.getAll();
|
||||
while(items.hasMoreElements()) {
|
||||
System.out.println(items.nextElement());
|
||||
}
|
||||
|
||||
objectName.add("New Name");
|
||||
|
||||
assertEquals("env", objectName.get(1));
|
||||
assertEquals("New Name", objectName.get(objectName.size() - 1));
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenContext_whenLookupByName_thenReturnsValidObject() throws Exception {
|
||||
DataSource ds = (DataSource) context.lookup("java:comp/env/jdbc/datasource");
|
||||
|
||||
assertNotNull(ds);
|
||||
assertNotNull(ds.getConnection());
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenSubContext_whenLookupByName_thenReturnsValidObject() throws Exception {
|
||||
Context subContext = (Context) context.lookup("java:comp/env");
|
||||
DataSource ds = (DataSource) subContext.lookup("jdbc/datasource");
|
||||
|
||||
assertNotNull(ds);
|
||||
assertNotNull(ds.getConnection());
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
static void tearDown() throws Exception {
|
||||
context.close();
|
||||
}
|
||||
|
||||
}
|
@ -29,7 +29,6 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.5.1</version>
|
||||
<configuration>
|
||||
<source>17</source>
|
||||
<target>17</target>
|
||||
@ -50,7 +49,7 @@
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<mapstruct.version>1.5.5.Final</mapstruct.version>
|
||||
<mapstruct.version>1.6.0.Beta1</mapstruct.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
58
core-java-modules/core-java-lang-6/src/main/java/com/baeldung/compressbytes/CompressByteArrayUtil.java
Normal file
58
core-java-modules/core-java-lang-6/src/main/java/com/baeldung/compressbytes/CompressByteArrayUtil.java
Normal file
@ -0,0 +1,58 @@
|
||||
package com.baeldung.compressbytes;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.util.zip.DataFormatException;
|
||||
import java.util.zip.Deflater;
|
||||
import java.util.zip.Inflater;
|
||||
|
||||
public class CompressByteArrayUtil {
|
||||
|
||||
public static byte[] compress(byte[] input) {
|
||||
Deflater deflater = new Deflater();
|
||||
deflater.setInput(input);
|
||||
deflater.finish();
|
||||
|
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
byte[] buffer = new byte[1024];
|
||||
|
||||
while (!deflater.finished()) {
|
||||
int compressedSize = deflater.deflate(buffer);
|
||||
outputStream.write(buffer, 0, compressedSize);
|
||||
}
|
||||
|
||||
return outputStream.toByteArray();
|
||||
}
|
||||
|
||||
public static byte[] decompress(byte[] input) throws DataFormatException {
|
||||
Inflater inflater = new Inflater();
|
||||
inflater.setInput(input);
|
||||
|
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
byte[] buffer = new byte[1024];
|
||||
|
||||
while (!inflater.finished()) {
|
||||
int decompressedSize = inflater.inflate(buffer);
|
||||
outputStream.write(buffer, 0, decompressedSize);
|
||||
}
|
||||
|
||||
return outputStream.toByteArray();
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
String inputString = "Baeldung helps developers explore the Java ecosystem and simply be better engineers. " +
|
||||
"We publish to-the-point guides and courses, with a strong focus on building web applications, Spring, " +
|
||||
"Spring Security, and RESTful APIs";
|
||||
byte[] input = inputString.getBytes();
|
||||
|
||||
// Compression
|
||||
byte[] compressedData = compress(input);
|
||||
|
||||
// Decompression
|
||||
byte[] decompressedData = decompress(compressedData);
|
||||
|
||||
System.out.println("Original: " + input.length + " bytes");
|
||||
System.out.println("Compressed: " + compressedData.length + " bytes");
|
||||
System.out.println("Decompressed: " + decompressedData.length + " bytes");
|
||||
}
|
||||
|
||||
}
|
@ -4,9 +4,7 @@ public class InterruptThread extends Thread {
|
||||
@Override
|
||||
public void run() {
|
||||
while (!isInterrupted()) {
|
||||
if (isInterrupted()) {
|
||||
break;
|
||||
}
|
||||
break;
|
||||
// business logic
|
||||
}
|
||||
}
|
||||
|
90
core-java-modules/core-java-numbers-6/src/test/java/com/baeldung/genericnumberscomparator/GenericNumbersComparatorUnitTest.java
Normal file
90
core-java-modules/core-java-numbers-6/src/test/java/com/baeldung/genericnumberscomparator/GenericNumbersComparatorUnitTest.java
Normal file
@ -0,0 +1,90 @@
|
||||
package com.baeldung.genericnumberscomparator;
|
||||
|
||||
import static org.assertj.core.api.Assertions.entry;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.Comparator;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.BiPredicate;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class GenericNumbersComparatorUnitTest {
|
||||
|
||||
public int compareDouble(Number num1, Number num2) {
|
||||
return Double.compare(num1.doubleValue(), num2.doubleValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenNumbers_whenUseCompareDouble_thenWillExecuteComparison() {
|
||||
assertEquals(0, compareDouble(5, 5.0));
|
||||
}
|
||||
|
||||
// we create a method that compares Integer, but this could also be done for other types e.g. Double, BigInteger
|
||||
public int compareTo(Integer int1, Integer int2) {
|
||||
return int1.compareTo(int2);
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenNumbers_whenUseCompareTo_thenWillExecuteComparison() {
|
||||
assertEquals(-1, compareTo(5, 7));
|
||||
}
|
||||
|
||||
// for this example, we create a function that compares Integer, but this could also be done for other types e.g. Double, BigInteger
|
||||
Map<Class<? extends Number>, BiFunction<Number, Number, Integer>> comparisonMap = Map.ofEntries(entry(Integer.class, (num1, num2) -> ((Integer) num1).compareTo((Integer) num2)));
|
||||
|
||||
public int compareUsingMap(Number num1, Number num2) {
|
||||
return comparisonMap.get(num1.getClass())
|
||||
.apply(num1, num2);
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenNumbers_whenUseCompareUsingMap_thenWillExecuteComparison() {
|
||||
assertEquals(-1, compareUsingMap(5, 7));
|
||||
}
|
||||
|
||||
public interface NumberComparator {
|
||||
int compare(Number num1, Number num2);
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenNumbers_whenUseProxy_thenWillExecuteComparison() {
|
||||
NumberComparator proxy = (NumberComparator) Proxy.newProxyInstance(NumberComparator.class.getClassLoader(), new Class[] { NumberComparator.class },
|
||||
(p, method, args) -> Double.compare(((Number) args[0]).doubleValue(), ((Number) args[1]).doubleValue()));
|
||||
assertEquals(0, proxy.compare(5, 5.0));
|
||||
}
|
||||
|
||||
public int compareUsingReflection(Number num1, Number num2) throws Exception {
|
||||
Method method = num1.getClass()
|
||||
.getMethod("compareTo", num1.getClass());
|
||||
return (int) method.invoke(num1, num2);
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenNumbers_whenUseCompareUsingReflection_thenWillExecuteComparison() throws Exception {
|
||||
assertEquals(-1, compareUsingReflection(5, 7));
|
||||
}
|
||||
|
||||
Function<Number, Double> toDouble = Number::doubleValue;
|
||||
BiPredicate<Number, Number> isEqual = (num1, num2) -> toDouble.apply(num1)
|
||||
.equals(toDouble.apply(num2));
|
||||
|
||||
@Test
|
||||
void givenNumbers_whenUseIsEqual_thenWillExecuteComparison() {
|
||||
assertEquals(true, isEqual.test(5, 5.0));
|
||||
}
|
||||
|
||||
private boolean someCondition;
|
||||
Function<Number, ?> dynamicFunction = someCondition ? Number::doubleValue : Number::intValue;
|
||||
Comparator<Number> dynamicComparator = (num1, num2) -> ((Comparable) dynamicFunction.apply(num1)).compareTo(dynamicFunction.apply(num2));
|
||||
|
||||
@Test
|
||||
void givenNumbers_whenUseDynamicComparator_thenWillExecuteComparison() {
|
||||
assertEquals(0, dynamicComparator.compare(5, 5.0));
|
||||
}
|
||||
|
||||
}
|
@ -3,7 +3,7 @@ package com.baeldung.floatdoubleconversions;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class FloatDoubleConversionsTest {
|
||||
public class FloatDoubleConversionsUnitTest {
|
||||
|
||||
@Test
|
||||
public void whenDoubleType_thenFloatTypeSuccess(){
|
@ -47,14 +47,14 @@
|
||||
<dependency>
|
||||
<groupId>io.rest-assured</groupId>
|
||||
<artifactId>json-path</artifactId>
|
||||
<version>${rest-assured.version}</version>
|
||||
<version>${json-path.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<properties>
|
||||
<hibernate.core.version>5.4.0.Final</hibernate.core.version>
|
||||
<rest-assured.version>3.1.1</rest-assured.version>
|
||||
<json-path.version>5.3.2</json-path.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
@ -8,88 +8,88 @@ import java.util.Optional;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
// Uncomment code when code base is compatible with Java 9
|
||||
//public class Java9OptionalUnitTest {
|
||||
//
|
||||
// @Test
|
||||
// public void givenOptionalOfSome_whenToStream_thenShouldTreatItAsOneElementStream() {
|
||||
// //given
|
||||
// Optional<String> value = Optional.of("a");
|
||||
//
|
||||
// //when
|
||||
// List<String> collect = value.stream().map(String::toUpperCase).collect(Collectors.toList());
|
||||
//
|
||||
// //then
|
||||
// assertThat(collect).hasSameElementsAs(List.of("A"));
|
||||
// }
|
||||
//
|
||||
// @Test
|
||||
// public void givenOptionalOfNone_whenToStream_thenShouldTreatItAsZeroElementStream() {
|
||||
// //given
|
||||
// Optional<String> value = Optional.empty();
|
||||
//
|
||||
// //when
|
||||
// List<String> collect = value.stream().map(String::toUpperCase).collect(Collectors.toList());
|
||||
//
|
||||
// //then
|
||||
// assertThat(collect).isEmpty();
|
||||
// }
|
||||
//
|
||||
// @Test
|
||||
// public void givenOptional_whenPresent_thenShouldExecuteProperCallback() {
|
||||
// //given
|
||||
// Optional<String> value = Optional.of("properValue");
|
||||
// AtomicInteger successCounter = new AtomicInteger(0);
|
||||
// AtomicInteger onEmptyOptionalCounter = new AtomicInteger(0);
|
||||
//
|
||||
// //when
|
||||
// value.ifPresentOrElse((v) -> successCounter.incrementAndGet(), onEmptyOptionalCounter::incrementAndGet);
|
||||
//
|
||||
// //then
|
||||
// assertThat(successCounter.get()).isEqualTo(1);
|
||||
// assertThat(onEmptyOptionalCounter.get()).isEqualTo(0);
|
||||
// }
|
||||
//
|
||||
// @Test
|
||||
// public void givenOptional_whenNotPresent_thenShouldExecuteProperCallback() {
|
||||
// //given
|
||||
// Optional<String> value = Optional.empty();
|
||||
// AtomicInteger successCounter = new AtomicInteger(0);
|
||||
// AtomicInteger onEmptyOptionalCounter = new AtomicInteger(0);
|
||||
//
|
||||
// //when
|
||||
// value.ifPresentOrElse((v) -> successCounter.incrementAndGet(), onEmptyOptionalCounter::incrementAndGet);
|
||||
//
|
||||
// //then
|
||||
// assertThat(successCounter.get()).isEqualTo(0);
|
||||
// assertThat(onEmptyOptionalCounter.get()).isEqualTo(1);
|
||||
// }
|
||||
//
|
||||
// @Test
|
||||
// public void givenOptional_whenPresent_thenShouldTakeAValueFromIt() {
|
||||
// //given
|
||||
// String expected = "properValue";
|
||||
// Optional<String> value = Optional.of(expected);
|
||||
// Optional<String> defaultValue = Optional.of("default");
|
||||
//
|
||||
// //when
|
||||
// Optional<String> result = value.or(() -> defaultValue);
|
||||
//
|
||||
// //then
|
||||
// assertThat(result.get()).isEqualTo(expected);
|
||||
// }
|
||||
//
|
||||
// @Test
|
||||
// public void givenOptional_whenEmpty_thenShouldTakeAValueFromOr() {
|
||||
// //given
|
||||
// String defaultString = "default";
|
||||
// Optional<String> value = Optional.empty();
|
||||
// Optional<String> defaultValue = Optional.of(defaultString);
|
||||
//
|
||||
// //when
|
||||
// Optional<String> result = value.or(() -> defaultValue);
|
||||
//
|
||||
// //then
|
||||
// assertThat(result.get()).isEqualTo(defaultString);
|
||||
// }
|
||||
//}
|
||||
|
||||
public class Java9OptionalUnitTest {
|
||||
|
||||
@Test
|
||||
public void givenOptionalOfSome_whenToStream_thenShouldTreatItAsOneElementStream() {
|
||||
//given
|
||||
Optional<String> value = Optional.of("a");
|
||||
|
||||
//when
|
||||
List<String> collect = value.stream().map(String::toUpperCase).collect(Collectors.toList());
|
||||
|
||||
//then
|
||||
assertThat(collect).hasSameElementsAs(List.of("A"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenOptionalOfNone_whenToStream_thenShouldTreatItAsZeroElementStream() {
|
||||
//given
|
||||
Optional<String> value = Optional.empty();
|
||||
|
||||
//when
|
||||
List<String> collect = value.stream().map(String::toUpperCase).collect(Collectors.toList());
|
||||
|
||||
//then
|
||||
assertThat(collect).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenOptional_whenPresent_thenShouldExecuteProperCallback() {
|
||||
//given
|
||||
Optional<String> value = Optional.of("properValue");
|
||||
AtomicInteger successCounter = new AtomicInteger(0);
|
||||
AtomicInteger onEmptyOptionalCounter = new AtomicInteger(0);
|
||||
|
||||
//when
|
||||
value.ifPresentOrElse((v) -> successCounter.incrementAndGet(), onEmptyOptionalCounter::incrementAndGet);
|
||||
|
||||
//then
|
||||
assertThat(successCounter.get()).isEqualTo(1);
|
||||
assertThat(onEmptyOptionalCounter.get()).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenOptional_whenNotPresent_thenShouldExecuteProperCallback() {
|
||||
//given
|
||||
Optional<String> value = Optional.empty();
|
||||
AtomicInteger successCounter = new AtomicInteger(0);
|
||||
AtomicInteger onEmptyOptionalCounter = new AtomicInteger(0);
|
||||
|
||||
//when
|
||||
value.ifPresentOrElse((v) -> successCounter.incrementAndGet(), onEmptyOptionalCounter::incrementAndGet);
|
||||
|
||||
//then
|
||||
assertThat(successCounter.get()).isEqualTo(0);
|
||||
assertThat(onEmptyOptionalCounter.get()).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenOptional_whenPresent_thenShouldTakeAValueFromIt() {
|
||||
//given
|
||||
String expected = "properValue";
|
||||
Optional<String> value = Optional.of(expected);
|
||||
Optional<String> defaultValue = Optional.of("default");
|
||||
|
||||
//when
|
||||
Optional<String> result = value.or(() -> defaultValue);
|
||||
|
||||
//then
|
||||
assertThat(result.get()).isEqualTo(expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenOptional_whenEmpty_thenShouldTakeAValueFromOr() {
|
||||
//given
|
||||
String defaultString = "default";
|
||||
Optional<String> value = Optional.empty();
|
||||
Optional<String> defaultValue = Optional.of(defaultString);
|
||||
|
||||
//when
|
||||
Optional<String> result = value.or(() -> defaultValue);
|
||||
|
||||
//then
|
||||
assertThat(result.get()).isEqualTo(defaultString);
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user