diff --git a/.github/ISSUE_TEMPLATE/issue_report.md b/.github/ISSUE_TEMPLATE/issue_report.md
new file mode 100644
index 0000000000..4bc8c8121c
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/issue_report.md
@@ -0,0 +1,32 @@
+---
+name: Issue Report
+about: Report an issue to help us improve
+title: '[ISSUE] '
+---
+
+**Article and Module Links**
+A link to the affected article and the affected module. You can find the link to the module in the Conclusion section in the "on Github" standard phase.
+
+**Describe the Issue**
+A clear and concise description of what the issue is.
+
+**To Reproduce**
+Steps to reproduce the behavior:
+1. Go to '...'
+2. Click on '....'
+3. Scroll down to '....'
+4. See error
+
+**Expected Behavior**
+A clear and concise description of what you expected to happen.
+
+**Screenshots**
+If applicable, add screenshots to help explain your problem.
+
+**Environment (please complete the following information):**
+- OS: [e.g. Windows]
+- Browser [e.g. chrome, safari]
+- Version [e.g. 22]
+
+**Additional Context**
+Add any other context about the issue here.
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000000..642f4c6707
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,11 @@
+# Contributing to Baeldung Tutorials
+First off, thank you for considering contributing to Baeldung Tutorials.
+
+## Reporting Issues
+Before you submit an issue, please review the guidelines below:
+
+1. **No Custom Modifications:** If your issue arises from any custom modifications you've made to the code in the repository, we won't be able to assist. We can only help if the issue is reproducible with the untouched codebase from this repo. If you're working with a modified version, consider asking for help on StackOverflow or other relevant forums.
+2. **Use a clear and descriptive title** for the issue to identify the problem.
+3. **Include a link to the article** you're having issues with.
+4. **Describe the exact steps which reproduce the problem** in as many details as possible.
+5. **Additional Details:** Offer any other context or descriptions that could be useful. Screenshots, error messages, copy/pasteable snippets, or logs can be immensely helpful.
\ No newline at end of file
diff --git a/apache-httpclient-2/src/test/java/com/baeldung/httpclient/cookies/HttpClientGettingCookieValueUnitTest.java b/apache-httpclient-2/src/test/java/com/baeldung/httpclient/cookies/HttpClientGettingCookieValueUnitTest.java
index ef57406705..6a8308483b 100644
--- a/apache-httpclient-2/src/test/java/com/baeldung/httpclient/cookies/HttpClientGettingCookieValueUnitTest.java
+++ b/apache-httpclient-2/src/test/java/com/baeldung/httpclient/cookies/HttpClientGettingCookieValueUnitTest.java
@@ -14,6 +14,7 @@ import org.apache.hc.client5.http.impl.classic.HttpClientBuilder;
import org.apache.hc.client5.http.impl.cookie.BasicClientCookie;
import org.apache.hc.client5.http.protocol.HttpClientContext;
+import org.apache.http.cookie.ClientCookie;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -51,8 +52,8 @@ class HttpClientGettingCookieValueUnitTest {
private BasicCookieStore createCustomCookieStore() {
BasicCookieStore cookieStore = new BasicCookieStore();
BasicClientCookie cookie = new BasicClientCookie("custom_cookie", "test_value");
- cookie.setDomain("baeldung.com");
- cookie.setAttribute("domain", "true");
+ cookie.setDomain("github.com");
+ cookie.setAttribute(ClientCookie.DOMAIN_ATTR, "github.com");
cookie.setPath("/");
cookieStore.addCookie(cookie);
return cookieStore;
diff --git a/apache-httpclient-2/src/test/resources/logback.xml b/apache-httpclient-2/src/test/resources/logback.xml
index 366a94e86e..dc1bbea439 100644
--- a/apache-httpclient-2/src/test/resources/logback.xml
+++ b/apache-httpclient-2/src/test/resources/logback.xml
@@ -4,6 +4,7 @@
%date [%level] %logger - %msg %n
+
diff --git a/apache-kafka-2/README.md b/apache-kafka-2/README.md
index dc675a0811..40ee701be1 100644
--- a/apache-kafka-2/README.md
+++ b/apache-kafka-2/README.md
@@ -13,3 +13,4 @@ You can build the project from the command line using: *mvn clean install*, or i
- [Read Data From the Beginning Using Kafka Consumer API](https://www.baeldung.com/java-kafka-consumer-api-read)
- [Get Partition Count for a Topic in Kafka](https://www.baeldung.com/java-kafka-partition-count-topic)
- [bootstrap-server in Kafka Configuration](https://www.baeldung.com/java-kafka-bootstrap-server)
+- [Introduction to Apache Kafka](https://www.baeldung.com/apache-kafka)
diff --git a/apache-kafka-2/src/test/java/com/baeldung/kafka/multipletopics/MultipleTopicsLiveTest.java b/apache-kafka-2/src/test/java/com/baeldung/kafka/multipletopics/MultipleTopicsLiveTest.java
new file mode 100644
index 0000000000..653456a678
--- /dev/null
+++ b/apache-kafka-2/src/test/java/com/baeldung/kafka/multipletopics/MultipleTopicsLiveTest.java
@@ -0,0 +1,103 @@
+package com.baeldung.kafka.multipletopics;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.time.Duration;
+import java.util.Arrays;
+import java.util.Properties;
+import java.util.concurrent.ExecutionException;
+
+import org.apache.kafka.clients.consumer.ConsumerConfig;
+import org.apache.kafka.clients.consumer.ConsumerRecord;
+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.common.serialization.StringDeserializer;
+import org.apache.kafka.common.serialization.StringSerializer;
+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;
+
+// This live test needs a Docker Daemon running so that a kafka container can be created
+
+@Testcontainers
+public class MultipleTopicsLiveTest {
+
+ private final Logger log = LoggerFactory.getLogger(MultipleTopicsLiveTest.class);
+
+ private static final String CARD_PAYMENTS_TOPIC = "card-payments";
+ private static final String BANK_TRANSFERS_TOPIC = "bank-transfers";
+ private static KafkaProducer producer;
+ private static KafkaConsumer consumer;
+
+ @Container
+ private static final KafkaContainer KAFKA_CONTAINER = new KafkaContainer(DockerImageName.parse("confluentinc/cp-kafka:latest"));
+
+ @BeforeAll
+ static void setup() {
+ KAFKA_CONTAINER.addExposedPort(9092);
+ producer = new KafkaProducer<>(getProducerProperties());
+ consumer = new KafkaConsumer<>(getConsumerProperties());
+ }
+
+ @AfterAll
+ static void destroy() {
+ KAFKA_CONTAINER.stop();
+ }
+
+ private static Properties getProducerProperties() {
+ Properties producerProperties = new Properties();
+ producerProperties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, KAFKA_CONTAINER.getBootstrapServers());
+ producerProperties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());
+ producerProperties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());
+ return producerProperties;
+ }
+
+ private static Properties getConsumerProperties() {
+ Properties consumerProperties = new Properties();
+ consumerProperties.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, KAFKA_CONTAINER.getBootstrapServers());
+ consumerProperties.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());
+ consumerProperties.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());
+ consumerProperties.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest");
+ consumerProperties.put(ConsumerConfig.GROUP_ID_CONFIG, "payments");
+ return consumerProperties;
+ }
+
+ @Test
+ void whenSendingMessagesOnTwoTopics_thenConsumerReceivesMessages() throws Exception {
+ publishMessages();
+
+ consumer.subscribe(Arrays.asList(CARD_PAYMENTS_TOPIC, BANK_TRANSFERS_TOPIC));
+
+ int eventsProcessed = 0;
+ for (ConsumerRecord record : consumer.poll(Duration.ofSeconds(10))) {
+ log.info("Event on topic={}, payload={}", record.topic(), record.value());
+ eventsProcessed++;
+ }
+
+ assertThat(eventsProcessed).isEqualTo(2);
+ }
+
+ private void publishMessages() throws ExecutionException, InterruptedException {
+ ProducerRecord cardPayment = new ProducerRecord<>(CARD_PAYMENTS_TOPIC, createCardPayment());
+ producer.send(cardPayment).get();
+
+ ProducerRecord bankTransfer = new ProducerRecord<>(BANK_TRANSFERS_TOPIC, createBankTransfer());
+ producer.send(bankTransfer).get();
+ }
+
+ private String createCardPayment() {
+ return "{\"paymentReference\":\"A184028KM0013790\", \"type\":\"card\", \"amount\":\"275\", \"currency\":\"GBP\"}";
+ }
+
+ private String createBankTransfer() {
+ return "{\"paymentReference\":\"19ae2-18mk73-009\", \"type\":\"bank\", \"amount\":\"150\", \"currency\":\"EUR\"}";
+ }
+}
diff --git a/apache-poi-3/README.md b/apache-poi-3/README.md
new file mode 100644
index 0000000000..9e9d6a94eb
--- /dev/null
+++ b/apache-poi-3/README.md
@@ -0,0 +1,3 @@
+## Relevant Articles
+- [How To Convert Excel Data Into List Of Java Objects](https://www.baeldung.com/java-convert-excel-data-into-list)
+- [Expand Columns with Apache POI](https://www.baeldung.com/java-apache-poi-expand-columns)
diff --git a/apache-poi-3/pom.xml b/apache-poi-3/pom.xml
new file mode 100644
index 0000000000..905db3d58c
--- /dev/null
+++ b/apache-poi-3/pom.xml
@@ -0,0 +1,97 @@
+
+
+ 4.0.0
+ apache-poi-3
+ 0.0.1-SNAPSHOT
+ apache-poi-3
+
+
+ com.baeldung
+ parent-modules
+ 1.0.0-SNAPSHOT
+
+
+
+
+ org.apache.poi
+ poi-ooxml
+ ${poi.version}
+
+
+ org.apache.poi
+ poi-scratchpad
+ ${poi.version}
+
+
+
+ com.github.ozlerhakan
+ poiji
+ ${poiji.version}
+
+
+
+
+ org.apache.poi
+ poi
+ ${poi.version}
+
+
+
+ org.apache.poi
+ poi-ooxml-schemas
+ 4.1.2
+
+
+
+ org.apache.xmlbeans
+ xmlbeans
+ 5.1.1
+
+
+
+ org.apache.commons
+ commons-collections4
+ 4.4
+
+
+
+ org.dhatim
+ fastexcel
+ ${fastexcel.version}
+
+
+
+ org.dhatim
+ fastexcel-reader
+ ${fastexcel.version}
+
+
+
+ net.sourceforge.jexcelapi
+ jxl
+ ${jxl.version}
+
+
+
+ org.apache.logging.log4j
+ log4j-api
+ 2.17.1
+
+
+
+ org.apache.logging.log4j
+ log4j-core
+ 2.17.1
+
+
+
+
+ 5.2.3
+ 4.1.1
+ 0.15.7
+ 2.6.12
+
+
+
\ No newline at end of file
diff --git a/apache-poi-3/src/main/java/com/baeldung/convert/exceldatatolist/FoodInfo.java b/apache-poi-3/src/main/java/com/baeldung/convert/exceldatatolist/FoodInfo.java
new file mode 100644
index 0000000000..b8fe4522de
--- /dev/null
+++ b/apache-poi-3/src/main/java/com/baeldung/convert/exceldatatolist/FoodInfo.java
@@ -0,0 +1,54 @@
+package com.baeldung.convert.exceldatatolist;
+
+import com.poiji.annotation.ExcelCellName;
+
+public class FoodInfo {
+
+ @ExcelCellName("Category")
+ private String category; //food category
+ @ExcelCellName("Name")
+ private String name; // food name
+ @ExcelCellName("Measure")
+ private String measure;
+ @ExcelCellName("Calories")
+ private double calories; //amount of calories in kcal/measure
+
+ @Override
+ public String toString() {
+ return "FoodInfo{" + "category='" + category + '\'' + ", name='" + name + '\'' + ", measure='" + measure + '\'' + ", calories=" + calories + "} \n";
+ }
+
+
+ public String getCategory() {
+ return category;
+ }
+
+ public void setCategory(String category) {
+ this.category = category;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getMeasure() {
+ return measure;
+ }
+
+ public void setMeasure(String measure) {
+ this.measure = measure;
+ }
+
+ public double getCalories() {
+ return calories;
+ }
+
+ public void setCalories(double calories) {
+ this.calories = calories;
+ }
+
+}
diff --git a/apache-poi-3/src/main/java/com/baeldung/convert/exceldatatolist/fastexcel/ExcelDataToListOfObjectsFastExcel.java b/apache-poi-3/src/main/java/com/baeldung/convert/exceldatatolist/fastexcel/ExcelDataToListOfObjectsFastExcel.java
new file mode 100644
index 0000000000..87d31520e6
--- /dev/null
+++ b/apache-poi-3/src/main/java/com/baeldung/convert/exceldatatolist/fastexcel/ExcelDataToListOfObjectsFastExcel.java
@@ -0,0 +1,42 @@
+package com.baeldung.convert.exceldatatolist.fastexcel;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.stream.Stream;
+
+import org.dhatim.fastexcel.reader.ReadableWorkbook;
+import org.dhatim.fastexcel.reader.Row;
+import org.dhatim.fastexcel.reader.Sheet;
+
+import com.baeldung.convert.exceldatatolist.FoodInfo;
+
+public class ExcelDataToListOfObjectsFastExcel {
+ public static List excelDataToListOfObjets_withFastExcel(String fileLocation)throws IOException, NumberFormatException {
+ List foodData = new ArrayList();
+
+ try (FileInputStream file = new FileInputStream(fileLocation);
+ ReadableWorkbook wb = new ReadableWorkbook(file)) {
+ Sheet sheet = wb.getFirstSheet();
+ for (Row row:
+ sheet.read()
+ ) {
+ if(row.getRowNum() == 1) {
+ continue;
+ }
+ FoodInfo food = new FoodInfo();
+ food.setCategory(row.getCellText(0));
+ food.setName(row.getCellText(1));
+ food.setMeasure(row.getCellText(2));
+ food.setCalories(Double.parseDouble(row.getCellText(3)));
+
+ foodData.add(food);
+
+ }
+ }
+
+ return foodData;
+ }
+}
diff --git a/apache-poi-3/src/main/java/com/baeldung/convert/exceldatatolist/jexcelapi/ExcelDataToListOfObjectsJxl.java b/apache-poi-3/src/main/java/com/baeldung/convert/exceldatatolist/jexcelapi/ExcelDataToListOfObjectsJxl.java
new file mode 100644
index 0000000000..61ba5e4700
--- /dev/null
+++ b/apache-poi-3/src/main/java/com/baeldung/convert/exceldatatolist/jexcelapi/ExcelDataToListOfObjectsJxl.java
@@ -0,0 +1,37 @@
+package com.baeldung.convert.exceldatatolist.jexcelapi;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import com.baeldung.convert.exceldatatolist.FoodInfo;
+
+import jxl.Sheet;
+import jxl.Workbook;
+import jxl.read.biff.BiffException;
+
+public class ExcelDataToListOfObjectsJxl {
+ public static List excelDataToListOfObjets_withJxl(String fileLocation) throws IOException, BiffException {
+
+ List foodData = new ArrayList();
+
+ Workbook workbook = Workbook.getWorkbook(new File(fileLocation));
+ Sheet sheet = workbook.getSheet(0);
+
+ int rows = sheet.getRows();
+
+ for (int i = 1; i < rows; i++) {
+ FoodInfo foodInfo = new FoodInfo();
+
+ foodInfo.setCategory(sheet.getCell(0, i).getContents());
+ foodInfo.setName(sheet.getCell(1, i).getContents());
+ foodInfo.setMeasure(sheet.getCell(2, i).getContents());
+ foodInfo.setCalories(Double.parseDouble(sheet.getCell(3, i).getContents()));
+
+ foodData.add(foodInfo);
+
+ }
+ return foodData;
+ }
+}
diff --git a/apache-poi-3/src/main/java/com/baeldung/convert/exceldatatolist/poi/ExcelDataToListApachePOI.java b/apache-poi-3/src/main/java/com/baeldung/convert/exceldatatolist/poi/ExcelDataToListApachePOI.java
new file mode 100644
index 0000000000..8b568b889a
--- /dev/null
+++ b/apache-poi-3/src/main/java/com/baeldung/convert/exceldatatolist/poi/ExcelDataToListApachePOI.java
@@ -0,0 +1,39 @@
+package com.baeldung.convert.exceldatatolist.poi;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.poi.ss.usermodel.DataFormatter;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+
+import com.baeldung.convert.exceldatatolist.FoodInfo;
+
+public class ExcelDataToListApachePOI {
+ public static List excelDataToListOfObjets_withApachePOI(String fileLocation) throws IOException {
+ FileInputStream file = new FileInputStream(new File(fileLocation));
+ Workbook workbook = new XSSFWorkbook(file);
+ Sheet sheet = workbook.getSheetAt(0);
+ List foodData = new ArrayList();
+ DataFormatter dataFormatter = new DataFormatter();
+ for (int n = 1; n < sheet.getPhysicalNumberOfRows(); n++) {
+ Row row = sheet.getRow(n);
+ FoodInfo foodInfo = new FoodInfo();
+ int i = row.getFirstCellNum();
+
+ foodInfo.setCategory(dataFormatter.formatCellValue(row.getCell(i)));
+ foodInfo.setName(dataFormatter.formatCellValue(row.getCell(++i)));
+ foodInfo.setMeasure(dataFormatter.formatCellValue(row.getCell(++i)));
+ foodInfo.setCalories(Double.parseDouble(dataFormatter.formatCellValue(row.getCell(++i))));
+
+ foodData.add(foodInfo);
+
+ }
+ return foodData;
+ }
+}
diff --git a/apache-poi-3/src/main/java/com/baeldung/convert/exceldatatolist/poiji/ExcelDataToListOfObjectsPOIJI.java b/apache-poi-3/src/main/java/com/baeldung/convert/exceldatatolist/poiji/ExcelDataToListOfObjectsPOIJI.java
new file mode 100644
index 0000000000..be190d38f7
--- /dev/null
+++ b/apache-poi-3/src/main/java/com/baeldung/convert/exceldatatolist/poiji/ExcelDataToListOfObjectsPOIJI.java
@@ -0,0 +1,13 @@
+package com.baeldung.convert.exceldatatolist.poiji;
+
+import java.io.File;
+import java.util.List;
+
+import com.baeldung.convert.exceldatatolist.FoodInfo;
+import com.poiji.bind.Poiji;
+
+public class ExcelDataToListOfObjectsPOIJI {
+ public static List excelDataToListOfObjets_withPOIJI(String fileLocation){
+ return Poiji.fromExcel(new File(fileLocation), FoodInfo.class);
+ }
+}
diff --git a/apache-poi-3/src/main/resources/food_info.xls b/apache-poi-3/src/main/resources/food_info.xls
new file mode 100644
index 0000000000..1377d8e18d
Binary files /dev/null and b/apache-poi-3/src/main/resources/food_info.xls differ
diff --git a/apache-poi-3/src/main/resources/food_info.xlsx b/apache-poi-3/src/main/resources/food_info.xlsx
new file mode 100644
index 0000000000..c604ff367d
Binary files /dev/null and b/apache-poi-3/src/main/resources/food_info.xlsx differ
diff --git a/apache-poi-3/src/test/java/com/baeldung/convert/exceldatatolist/ExcelDataToListOfObjectsUnitTest.java b/apache-poi-3/src/test/java/com/baeldung/convert/exceldatatolist/ExcelDataToListOfObjectsUnitTest.java
new file mode 100644
index 0000000000..5d65c04b31
--- /dev/null
+++ b/apache-poi-3/src/test/java/com/baeldung/convert/exceldatatolist/ExcelDataToListOfObjectsUnitTest.java
@@ -0,0 +1,53 @@
+package com.baeldung.convert.exceldatatolist;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+import java.util.List;
+
+// import org.junit.jupiter.api.Test;
+// import static org.junit.jupiter.api.Assertions.*;
+import org.junit.Test;
+
+import com.baeldung.convert.exceldatatolist.fastexcel.ExcelDataToListOfObjectsFastExcel;
+import com.baeldung.convert.exceldatatolist.jexcelapi.ExcelDataToListOfObjectsJxl;
+import com.baeldung.convert.exceldatatolist.poi.ExcelDataToListApachePOI;
+import com.baeldung.convert.exceldatatolist.poiji.ExcelDataToListOfObjectsPOIJI;
+
+import jxl.read.biff.BiffException;
+
+public class ExcelDataToListOfObjectsUnitTest {
+
+ @Test
+ public void whenParsingExcelFileWithPOIJI_thenConvertsToList() throws IOException {
+ List foodInfoList = ExcelDataToListOfObjectsPOIJI.excelDataToListOfObjets_withPOIJI("src/main/resources/food_info.xlsx");
+
+ assertEquals("Beverages", foodInfoList.get(0).getCategory());
+ assertEquals("Dairy", foodInfoList.get(3).getCategory());
+ }
+
+ @Test
+ public void whenParsingExcelFileWithApachePOI_thenConvertsToList() throws IOException {
+ List foodInfoList = ExcelDataToListApachePOI.excelDataToListOfObjets_withApachePOI("src/main/resources/food_info.xlsx");
+
+ assertEquals("Beverages", foodInfoList.get(0).getCategory());
+ assertEquals("Dairy", foodInfoList.get(3).getCategory());
+ }
+
+ @Test
+ public void whenParsingExcelFileWithFastExcel_thenConvertsToList() throws IOException {
+ List foodInfoList = ExcelDataToListOfObjectsFastExcel.excelDataToListOfObjets_withFastExcel("src/main/resources/food_info.xlsx");
+
+ assertEquals("Beverages", foodInfoList.get(0).getCategory());
+ assertEquals("Dairy", foodInfoList.get(3).getCategory());
+ }
+
+ @Test
+ public void whenParsingExcelFileWithJxl_thenConvertsToList() throws IOException, BiffException {
+ List foodInfoList = ExcelDataToListOfObjectsJxl.excelDataToListOfObjets_withJxl("src/main/resources/food_info.xls");
+
+ assertEquals("Beverages", foodInfoList.get(0).getCategory());
+ assertEquals("Dairy", foodInfoList.get(3).getCategory());
+ }
+
+}
diff --git a/apache-poi-3/src/test/java/com/baeldung/poi/excel/expandcolumn/ExpandColumnUnitTest.java b/apache-poi-3/src/test/java/com/baeldung/poi/excel/expandcolumn/ExpandColumnUnitTest.java
new file mode 100644
index 0000000000..04d0aef211
--- /dev/null
+++ b/apache-poi-3/src/test/java/com/baeldung/poi/excel/expandcolumn/ExpandColumnUnitTest.java
@@ -0,0 +1,70 @@
+package com.baeldung.poi.excel.expandcolumn;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.*;
+
+import java.io.IOException;
+
+import org.apache.poi.ss.usermodel.*;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+class ExpandColumnUnitTest {
+
+ private Workbook workbook;
+ private Sheet sheet;
+
+ @BeforeEach
+ void prepareSpreadsheet() {
+ workbook = new XSSFWorkbook();
+ sheet = workbook.createSheet();
+
+ Row headerRow = sheet.createRow(0);
+ Cell headerCell1 = headerRow.createCell(0);
+ headerCell1.setCellValue("Full Name");
+ Cell headerCell2 = headerRow.createCell(1);
+ headerCell2.setCellValue("Abbreviation");
+
+ Row dataRow = sheet.createRow(1);
+ Cell dataCell1 = dataRow.createCell(0);
+ dataCell1.setCellValue("Java Virtual Machine");
+ Cell dataCell2 = dataRow.createCell(1);
+ dataCell2.setCellValue("JVM");
+
+ dataRow = sheet.createRow(2);
+ dataCell1 = dataRow.createCell(0);
+ dataCell1.setCellValue("Java Runtime Environment");
+ dataCell2 = dataRow.createCell(1);
+ dataCell2.setCellValue("JRE");
+ }
+
+ @Test
+ void whenSetColumnWidth_thenColumnSetToTheSpecifiedWidth() {
+
+ Row row = sheet.getRow(2);
+ String cellValue = row.getCell(0).getStringCellValue();
+ int targetWidth = cellValue.length() * 256;
+
+ sheet.setColumnWidth(0, targetWidth);
+
+ assertEquals(targetWidth, sheet.getColumnWidth(0));
+ }
+
+ @Test
+ void whenAutoSizeColumn_thenColumnExpands() {
+
+ int originalWidth = sheet.getColumnWidth(0);
+
+ sheet.autoSizeColumn(0);
+
+ assertThat(sheet.getColumnWidth(0)).isGreaterThan(originalWidth);
+ }
+
+ @AfterEach
+ void cleanup() throws IOException {
+ workbook.close();
+ }
+
+}
\ No newline at end of file
diff --git a/aws-modules/aws-s3/README.md b/aws-modules/aws-s3/README.md
index cb039b7c61..9b862c8685 100644
--- a/aws-modules/aws-s3/README.md
+++ b/aws-modules/aws-s3/README.md
@@ -4,7 +4,7 @@ This module contains articles about Simple Storage Service (S3) on AWS
### Relevant articles
-- [AWS S3 with Java](https://www.baeldung.com/aws-s3-java)
+- [AWS S3 with Java](https://www.baeldung.com/java-aws-s3)
- [Multipart Uploads in Amazon S3 with Java](https://www.baeldung.com/aws-s3-multipart-upload)
- [Using the JetS3t Java Client With Amazon S3](https://www.baeldung.com/jets3t-amazon-s3)
- [Check if a Specified Key Exists in a Given S3 Bucket Using Java](https://www.baeldung.com/java-aws-s3-check-specified-key-exists)
diff --git a/core-java-modules/core-java-16/README.md b/core-java-modules/core-java-16/README.md
index b2740d194c..11b0fba8d3 100644
--- a/core-java-modules/core-java-16/README.md
+++ b/core-java-modules/core-java-16/README.md
@@ -5,3 +5,4 @@
- [Collecting Stream Elements into a List in Java](https://www.baeldung.com/java-stream-to-list-collecting)
- [New Features in Java 16](https://www.baeldung.com/java-16-new-features)
- [Guide to Java 8 groupingBy Collector](https://www.baeldung.com/java-groupingby-collector)
+- [Value-Based Classes in Java](https://www.baeldung.com/java-value-based-classes)
diff --git a/core-java-modules/core-java-16/src/main/java/com/baeldung/value_based_class/Point.java b/core-java-modules/core-java-16/src/main/java/com/baeldung/value_based_class/Point.java
new file mode 100644
index 0000000000..13e2238274
--- /dev/null
+++ b/core-java-modules/core-java-16/src/main/java/com/baeldung/value_based_class/Point.java
@@ -0,0 +1,49 @@
+package com.baeldung.value_based_class;
+
+import java.util.Objects;
+
+import jdk.internal.ValueBased;
+
+/**
+ * This class is written with the intention that it can serve as an example of
+ * what a Value-based class could be.
+ */
+
+@ValueBased
+public final class Point {
+ private final int x;
+ private final int y;
+ private final int z;
+
+ private static Point ORIGIN = new Point(0, 0, 0);
+
+ private Point(int x, int y, int z) {
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ }
+
+ public static Point valueOfPoint(int x, int y, int z) {
+ // returns a cached instance if it is origin, or a new instance
+ if (isOrigin(x, y, z))
+ return ORIGIN;
+ return new Point(x, y, z);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other == null || getClass() != other.getClass())
+ return false;
+ Point point = (Point) other;
+ return x == point.x && y == point.y && z == point.z;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(x, y, z);
+ }
+
+ private static boolean isOrigin(int x, int y, int z) {
+ return x == 0 && y == 0 && z == 0;
+ }
+}
diff --git a/core-java-modules/core-java-16/src/test/java/com/baeldung/value_based_class/ValueBasedClassUnitTest.java b/core-java-modules/core-java-16/src/test/java/com/baeldung/value_based_class/ValueBasedClassUnitTest.java
new file mode 100644
index 0000000000..781f368982
--- /dev/null
+++ b/core-java-modules/core-java-16/src/test/java/com/baeldung/value_based_class/ValueBasedClassUnitTest.java
@@ -0,0 +1,41 @@
+package com.baeldung.value_based_class;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class ValueBasedClassUnitTest {
+ @Test
+ public void givenAutoboxedAndPrimitive_whenCompared_thenReturnEquals() {
+ int primitive_a = 125;
+ Integer obj_a = 125; // this is autoboxed
+ Assert.assertSame(primitive_a, obj_a);
+ }
+
+ @Test
+ public void givenValueBasedPoint_whenCreated_thenReturnsObjects() {
+ Point p1 = Point.valueOfPoint(1, 2, 3);
+ Point p2 = Point.valueOfPoint(2, 3, 4);
+
+ Assert.assertNotEquals(p1, p2);
+ }
+
+ @Test
+ public void givenValueBasedPoint_whenCompared_thenReturnEquals() {
+ Point p1 = Point.valueOfPoint(1, 2, 3);
+ Point p2 = Point.valueOfPoint(1, 2, 3);
+
+ Assert.assertEquals(p1, p2);
+ }
+
+ @Test
+ public void givenValueBasedPoint_whenOrigin_thenReturnCachedInstance() {
+ Point p1 = Point.valueOfPoint(0, 0, 0);
+ Point p2 = Point.valueOfPoint(0, 0, 0);
+ Point p3 = Point.valueOfPoint(1, 2, 3);
+
+ // the following should not be assumed for value-based classes
+
+ Assert.assertTrue(p1 == p2);
+ Assert.assertFalse(p1 == p3);
+ }
+}
diff --git a/core-java-modules/core-java-21/README.md b/core-java-modules/core-java-21/README.md
index c63f3b360b..ffb999a4ba 100644
--- a/core-java-modules/core-java-21/README.md
+++ b/core-java-modules/core-java-21/README.md
@@ -1 +1,5 @@
-## Relevant Articles
\ No newline at end of file
+## Relevant Articles
+- [Sequenced Collections in Java 21](https://www.baeldung.com/java-21-sequenced-collections)
+- [String Templates in Java 21](https://www.baeldung.com/java-21-string-templates)
+- [Unnamed Classes and Instance Main Methods in Java 21](https://www.baeldung.com/java-21-unnamed-class-instance-main)
+- [Unnamed Patterns and Variables in Java 21](https://www.baeldung.com/java-unnamed-patterns-variables)
diff --git a/core-java-modules/core-java-21/pom.xml b/core-java-modules/core-java-21/pom.xml
index 83b2b1c858..7b8fa9063f 100644
--- a/core-java-modules/core-java-21/pom.xml
+++ b/core-java-modules/core-java-21/pom.xml
@@ -12,23 +12,36 @@
0.0.1-SNAPSHOT
-
-
-
-
-
-
-
-
-
-
-
-
+
+ 21
+ 21
+ UTF-8
+
-
-
-
-
-
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+ 21
+
+ false
+
+ --enable-preview
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+ --enable-preview
+
+
+
+
+
\ No newline at end of file
diff --git a/core-java-modules/core-java-21/src/main/java/com/baeldung/stringtemplates/StringCompositionTechniques.java b/core-java-modules/core-java-21/src/main/java/com/baeldung/stringtemplates/StringCompositionTechniques.java
new file mode 100644
index 0000000000..7e66144f1c
--- /dev/null
+++ b/core-java-modules/core-java-21/src/main/java/com/baeldung/stringtemplates/StringCompositionTechniques.java
@@ -0,0 +1,37 @@
+package com.baeldung.stringtemplates;
+
+import java.text.MessageFormat;
+
+public class StringCompositionTechniques {
+ String composeUsingPlus(String feelsLike, String temperature, String unit) {
+ return "Today's weather is " + feelsLike + ", with a temperature of " + temperature + " degrees " + unit;
+ }
+
+ String composeUsingStringBuffer(String feelsLike, String temperature, String unit) {
+ return new StringBuffer().append("Today's weather is ")
+ .append(feelsLike)
+ .append(", with a temperature of ")
+ .append(temperature)
+ .append(" degrees ")
+ .append(unit)
+ .toString();
+ }
+
+ String composeUsingStringBuilder(String feelsLike, String temperature, String unit) {
+ return new StringBuilder().append("Today's weather is ")
+ .append(feelsLike)
+ .append(", with a temperature of ")
+ .append(temperature)
+ .append(" degrees ")
+ .append(unit)
+ .toString();
+ }
+
+ String composeUsingFormatters(String feelsLike, String temperature, String unit) {
+ return String.format("Today's weather is %s, with a temperature of %s degrees %s", feelsLike, temperature, unit);
+ }
+
+ String composeUsingMessageFormatter(String feelsLike, String temperature, String unit) {
+ return MessageFormat.format("Today''s weather is {0}, with a temperature of {1} degrees {2}", feelsLike, temperature, unit);
+ }
+}
diff --git a/core-java-modules/core-java-21/src/main/java/com/baeldung/stringtemplates/StringTemplateExamples.java b/core-java-modules/core-java-21/src/main/java/com/baeldung/stringtemplates/StringTemplateExamples.java
new file mode 100644
index 0000000000..0fb18a84e9
--- /dev/null
+++ b/core-java-modules/core-java-21/src/main/java/com/baeldung/stringtemplates/StringTemplateExamples.java
@@ -0,0 +1,56 @@
+package com.baeldung.stringtemplates;
+
+import static java.lang.StringTemplate.RAW;
+import static java.util.FormatProcessor.FMT;
+
+public class StringTemplateExamples {
+ String interpolationUsingSTRProcessor(String feelsLike, String temperature, String unit) {
+ return STR
+ . "Today's weather is \{ feelsLike }, with a temperature of \{ temperature } degrees \{ unit }" ;
+ }
+
+ String interpolationOfJSONBlock(String feelsLike, String temperature, String unit) {
+ return STR
+ . """
+ {
+ "feelsLike": "\{ feelsLike }",
+ "temperature": "\{ temperature }",
+ "unit": "\{ unit }"
+ }
+ """ ;
+ }
+
+ String interpolationWithExpressions() {
+ return STR
+ . "Today's weather is \{ getFeelsLike() }, with a temperature of \{ getTemperature() } degrees \{ getUnit() }" ;
+ }
+
+ String interpolationWithTemplates() {
+ StringTemplate str = RAW
+ . "Today's weather is \{ getFeelsLike() }, with a temperature of \{ getTemperature() } degrees \{ getUnit() }" ;
+ return STR.process(str);
+ }
+
+ String interpolationOfJSONBlockWithFMT(String feelsLike, float temperature, String unit) {
+ return FMT
+ . """
+ {
+ "feelsLike": "%1s\{ feelsLike }",
+ "temperature": "%2.2f\{ temperature }",
+ "unit": "%1s\{ unit }"
+ }
+ """ ;
+ }
+
+ private String getFeelsLike() {
+ return "pleasant";
+ }
+
+ private String getTemperature() {
+ return "25";
+ }
+
+ private String getUnit() {
+ return "Celsius";
+ }
+}
diff --git a/core-java-modules/core-java-21/src/main/java/com/baeldung/unnamed/variables/Car.java b/core-java-modules/core-java-21/src/main/java/com/baeldung/unnamed/variables/Car.java
new file mode 100644
index 0000000000..8f51c03539
--- /dev/null
+++ b/core-java-modules/core-java-21/src/main/java/com/baeldung/unnamed/variables/Car.java
@@ -0,0 +1,11 @@
+package com.baeldung.unnamed.variables;
+
+public record Car(String name, String color, T engine) { }
+
+abstract class Engine { }
+
+class GasEngine extends Engine { }
+
+class ElectricEngine extends Engine { }
+
+class HybridEngine extends Engine { }
\ No newline at end of file
diff --git a/core-java-modules/core-java-21/src/main/java/com/baeldung/unnamed/variables/UnnamedPatterns.java b/core-java-modules/core-java-21/src/main/java/com/baeldung/unnamed/variables/UnnamedPatterns.java
new file mode 100644
index 0000000000..310ce621f9
--- /dev/null
+++ b/core-java-modules/core-java-21/src/main/java/com/baeldung/unnamed/variables/UnnamedPatterns.java
@@ -0,0 +1,50 @@
+package com.baeldung.unnamed.variables;
+
+public class UnnamedPatterns {
+
+ static String getObjectsColorWithNamedPattern(Object object) {
+ if (object instanceof Car(String name, String color, Engine engine)) {
+ return color;
+ }
+ return "No color!";
+ }
+
+ static String getObjectsColorWithUnnamedPattern(Object object) {
+ if (object instanceof Car(_, String color, _)) {
+ return color;
+ }
+ return "No color!";
+ }
+
+ static String getObjectsColorWithSwitchAndNamedPattern(Object object) {
+ return switch (object) {
+ case Car(String name, String color, Engine engine) -> color;
+ default -> "No color!";
+ };
+ }
+
+ static String getObjectsColorWithSwitchAndUnnamedPattern(Object object) {
+ return switch (object) {
+ case Car(_, String color, _) -> color;
+ default -> "No color!";
+ };
+ }
+
+ static String getEngineTypeWithNamedPattern(Car> car) {
+ return switch (car) {
+ case Car(String name, String color, GasEngine engine) -> "gas";
+ case Car(String name, String color, ElectricEngine engine) -> "electric";
+ case Car(String name, String color, HybridEngine engine) -> "hybrid";
+ default -> "none";
+ };
+ }
+
+ static String getEngineTypeWithUnnamedPattern(Car> car) {
+ return switch (car) {
+ case Car(_, _, GasEngine _) -> "gas";
+ case Car(_, _, ElectricEngine _) -> "electric";
+ case Car(_, _, HybridEngine _) -> "hybrid";
+ default -> "none";
+ };
+ }
+}
diff --git a/core-java-modules/core-java-21/src/main/java/com/baeldung/unnamed/variables/UnnamedVariables.java b/core-java-modules/core-java-21/src/main/java/com/baeldung/unnamed/variables/UnnamedVariables.java
new file mode 100644
index 0000000000..82e76b40a4
--- /dev/null
+++ b/core-java-modules/core-java-21/src/main/java/com/baeldung/unnamed/variables/UnnamedVariables.java
@@ -0,0 +1,134 @@
+package com.baeldung.unnamed.variables;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Queue;
+
+class Transaction implements AutoCloseable {
+
+ @Override
+ public void close() {
+ System.out.println("Closed!");
+ }
+}
+
+public class UnnamedVariables {
+
+ static int countCarsOverLimitWithNamedVariable(Collection> cars, int limit) {
+ var total = 0;
+ var totalOverLimit = 0;
+ for (var car : cars) {
+ total++;
+ if (total > limit) {
+ totalOverLimit++;
+ // side effect
+ }
+ }
+ return totalOverLimit;
+ }
+
+ static int countCarsOverLimitWithUnnamedVariable(Collection> cars, int limit) {
+ var total = 0;
+ var totalOverLimit = 0;
+ for (var _ : cars) {
+ total++;
+ if (total > limit) {
+ totalOverLimit++;
+ // side effect
+ }
+ }
+ return totalOverLimit;
+ }
+
+ static void sendNotificationToCarsWithNamedVariable(Collection> cars) {
+ sendOneTimeNotification();
+ for (int i = 0; i < cars.size(); i++) {
+ // Notify car
+ }
+ }
+
+ static void sendNotificationToCarsWithUnnamedVariable(Collection> cars) {
+ for (int i = 0, _ = sendOneTimeNotification(); i < cars.size(); i++) {
+ // Notify car
+ }
+ }
+
+ private static int sendOneTimeNotification() {
+ System.out.println("Sending one time notification!");
+ return 1;
+ }
+
+ static Car> removeThreeCarsAndReturnFirstRemovedWithNamedVariables(Queue> cars) {
+ var x = cars.poll();
+ var y = cars.poll();
+ var z = cars.poll();
+ return x;
+ }
+
+ static Car> removeThreeCarsAndReturnFirstRemovedWithUnnamedVariables(Queue> cars) {
+ var car = cars.poll();
+ var _ = cars.poll();
+ var _ = cars.poll();
+ return car;
+ }
+
+ static void handleCarExceptionWithNamedVariables(Car> car) {
+ try {
+ someOperationThatFails(car);
+ } catch (IllegalStateException ex) {
+ System.out.println("Got an illegal state exception for: " + car.name());
+ } catch (RuntimeException ex) {
+ System.out.println("Got a runtime exception!");
+ }
+ }
+
+ static void handleCarExceptionWithUnnamedVariables(Car> car) {
+ try {
+ someOperationThatFails(car);
+ } catch (IllegalStateException | NumberFormatException _) {
+ System.out.println("Got an illegal state exception for: " + car.name());
+ } catch (RuntimeException _) {
+ System.out.println("Got a runtime exception!");
+ }
+ }
+
+ static void obtainTransactionAndUpdateCarWithNamedVariables(Car> car) {
+ try (var transaction = new Transaction()) {
+ updateCar(car);
+ }
+ }
+
+ static void obtainTransactionAndUpdateCarWithUnnamedVariables(Car> car) {
+ try (var _ = new Transaction()) {
+ updateCar(car);
+ }
+ }
+
+ static void updateCar(Car> car) {
+ // Some update logic
+ System.out.println("Car updated!");
+ }
+
+ static Map>> getCarsByFirstLetterWithNamedVariables(List> cars) {
+ Map>> carMap = new HashMap<>();
+ cars.forEach(car ->
+ carMap.computeIfAbsent(car.name().substring(0, 1), firstLetter -> new ArrayList<>()).add(car)
+ );
+ return carMap;
+ }
+
+ static Map>> getCarsByFirstLetterWithUnnamedVariables(List> cars) {
+ Map>> carMap = new HashMap<>();
+ cars.forEach(car ->
+ carMap.computeIfAbsent(car.name().substring(0, 1), _ -> new ArrayList<>()).add(car)
+ );
+ return carMap;
+ }
+
+ private static void someOperationThatFails(Car> car) {
+ throw new IllegalStateException("Triggered exception for: " + car.name());
+ }
+}
diff --git a/core-java-modules/core-java-21/src/main/java/com/baeldung/unnamedclasses/HelloWorld.java b/core-java-modules/core-java-21/src/main/java/com/baeldung/unnamedclasses/HelloWorld.java
new file mode 100644
index 0000000000..bf0e2c96c2
--- /dev/null
+++ b/core-java-modules/core-java-21/src/main/java/com/baeldung/unnamedclasses/HelloWorld.java
@@ -0,0 +1,3 @@
+void main() {
+ System.out.println("Hello, World!");
+}
diff --git a/core-java-modules/core-java-21/src/main/java/com/baeldung/unnamedclasses/HelloWorldChild.java b/core-java-modules/core-java-21/src/main/java/com/baeldung/unnamedclasses/HelloWorldChild.java
new file mode 100644
index 0000000000..827be7c788
--- /dev/null
+++ b/core-java-modules/core-java-21/src/main/java/com/baeldung/unnamedclasses/HelloWorldChild.java
@@ -0,0 +1,7 @@
+package com.baeldung.unnamedclasses;
+
+public class HelloWorldChild extends HelloWorldSuper {
+ void main() {
+ System.out.println("Hello, World!");
+ }
+}
diff --git a/core-java-modules/core-java-21/src/main/java/com/baeldung/unnamedclasses/HelloWorldSuper.java b/core-java-modules/core-java-21/src/main/java/com/baeldung/unnamedclasses/HelloWorldSuper.java
new file mode 100644
index 0000000000..59c88716a4
--- /dev/null
+++ b/core-java-modules/core-java-21/src/main/java/com/baeldung/unnamedclasses/HelloWorldSuper.java
@@ -0,0 +1,7 @@
+package com.baeldung.unnamedclasses;
+
+public class HelloWorldSuper {
+ public static void main(String[] args) {
+ System.out.println("Hello from the superclass");
+ }
+}
diff --git a/core-java-modules/core-java-21/src/main/java/com/baeldung/unnamedclasses/HelloWorldWithMethod.java b/core-java-modules/core-java-21/src/main/java/com/baeldung/unnamedclasses/HelloWorldWithMethod.java
new file mode 100644
index 0000000000..698516544e
--- /dev/null
+++ b/core-java-modules/core-java-21/src/main/java/com/baeldung/unnamedclasses/HelloWorldWithMethod.java
@@ -0,0 +1,6 @@
+private String getMessage() {
+ return "Hello, World!";
+}
+void main() {
+ System.out.println(getMessage());
+}
diff --git a/core-java-modules/core-java-21/src/test/java/com.baeldung.stringtemplates/StringTemplatesUnitTest.java b/core-java-modules/core-java-21/src/test/java/com.baeldung.stringtemplates/StringTemplatesUnitTest.java
new file mode 100644
index 0000000000..b9917cab18
--- /dev/null
+++ b/core-java-modules/core-java-21/src/test/java/com.baeldung.stringtemplates/StringTemplatesUnitTest.java
@@ -0,0 +1,67 @@
+package com.baeldung.stringtemplates;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class StringTemplatesUnitTest {
+
+ @Test
+ public void whenStringConcat_thenReturnComposedString() {
+ StringCompositionTechniques stringCompositionTechniques = new StringCompositionTechniques();
+ Assert.assertEquals("Today's weather is pleasant, with a temperature of 25 degrees Celsius", stringCompositionTechniques.composeUsingPlus("pleasant", "25", "Celsius"));
+ }
+
+ @Test
+ public void whenStringBuffer_thenReturnComposedString() {
+ StringCompositionTechniques stringCompositionTechniques = new StringCompositionTechniques();
+ Assert.assertEquals("Today's weather is pleasant, with a temperature of 25 degrees Celsius", stringCompositionTechniques.composeUsingStringBuffer("pleasant", "25", "Celsius"));
+ }
+
+ @Test
+ public void whenStringBuilder_thenReturnComposedString() {
+ StringCompositionTechniques stringCompositionTechniques = new StringCompositionTechniques();
+ Assert.assertEquals("Today's weather is pleasant, with a temperature of 25 degrees Celsius", stringCompositionTechniques.composeUsingStringBuilder("pleasant", "25", "Celsius"));
+ }
+
+ @Test
+ public void whenStringFormatter_thenReturnComposedFormattedString() {
+ StringCompositionTechniques stringCompositionTechniques = new StringCompositionTechniques();
+ Assert.assertEquals("Today's weather is pleasant, with a temperature of 25 degrees Celsius", stringCompositionTechniques.composeUsingFormatters("pleasant", "25", "Celsius"));
+ }
+
+ @Test
+ public void whenMessageFormatter_thenReturnComposedFormattedString() {
+ StringCompositionTechniques stringCompositionTechniques = new StringCompositionTechniques();
+ Assert.assertEquals("Today's weather is pleasant, with a temperature of 25 degrees Celsius", stringCompositionTechniques.composeUsingMessageFormatter("pleasant", "25", "Celsius"));
+ }
+
+ @Test
+ public void whenUsingStringTemplateSTR_thenReturnInterpolatedString() {
+ StringTemplateExamples templateExamples = new StringTemplateExamples();
+ Assert.assertEquals("Today's weather is pleasant, with a temperature of 25 degrees Celsius", templateExamples.interpolationUsingSTRProcessor("pleasant", "25", "Celsius"));
+ }
+
+ @Test
+ public void whenUsingMultilineStringTemplateSTR_thenReturnInterpolatedString() {
+ StringTemplateExamples templateExamples = new StringTemplateExamples();
+ Assert.assertEquals("{\n" + " \"feelsLike\": \"pleasant\",\n" + " \"temperature\": \"25\",\n" + " \"unit\": \"Celsius\"\n" + "}\n", templateExamples.interpolationOfJSONBlock("pleasant", "25", "Celsius"));
+ }
+
+ @Test
+ public void whenUsingExpressionSTR_thenReturnInterpolatedString() {
+ StringTemplateExamples templateExamples = new StringTemplateExamples();
+ Assert.assertEquals("Today's weather is pleasant, with a temperature of 25 degrees Celsius", templateExamples.interpolationWithExpressions());
+ }
+
+ @Test
+ public void whenUsingExpressionRAW_thenReturnInterpolatedString() {
+ StringTemplateExamples templateExamples = new StringTemplateExamples();
+ Assert.assertEquals("Today's weather is pleasant, with a temperature of 25 degrees Celsius", templateExamples.interpolationWithTemplates());
+ }
+
+ @Test
+ public void whenUsingExpressionFMT_thenReturnInterpolatedString() {
+ StringTemplateExamples templateExamples = new StringTemplateExamples();
+ Assert.assertEquals("{\n" + " \"feelsLike\": \"pleasant\",\n" + " \"temperature\": \"25.86\",\n" + " \"unit\": \"Celsius\"\n" + "}\n", templateExamples.interpolationOfJSONBlockWithFMT("pleasant", 25.8636F, "Celsius"));
+ }
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-21/src/test/java/com/baeldung/unnamed/variables/CarScenario.java b/core-java-modules/core-java-21/src/test/java/com/baeldung/unnamed/variables/CarScenario.java
new file mode 100644
index 0000000000..2acb83cdef
--- /dev/null
+++ b/core-java-modules/core-java-21/src/test/java/com/baeldung/unnamed/variables/CarScenario.java
@@ -0,0 +1,13 @@
+package com.baeldung.unnamed.variables;
+
+import java.util.List;
+
+class CarScenario {
+
+ protected final List> cars = List.of(
+ new Car<>("Mitsubishi", "blue", new GasEngine()),
+ new Car<>("Toyota", "red", new ElectricEngine()),
+ new Car<>("Jaguar", "white", new HybridEngine())
+ );
+
+}
diff --git a/core-java-modules/core-java-21/src/test/java/com/baeldung/unnamed/variables/UnnamedPatternsUnitTest.java b/core-java-modules/core-java-21/src/test/java/com/baeldung/unnamed/variables/UnnamedPatternsUnitTest.java
new file mode 100644
index 0000000000..9d860a201a
--- /dev/null
+++ b/core-java-modules/core-java-21/src/test/java/com/baeldung/unnamed/variables/UnnamedPatternsUnitTest.java
@@ -0,0 +1,44 @@
+package com.baeldung.unnamed.variables;
+
+import static com.baeldung.unnamed.variables.UnnamedPatterns.getEngineTypeWithNamedPattern;
+import static com.baeldung.unnamed.variables.UnnamedPatterns.getEngineTypeWithUnnamedPattern;
+import static com.baeldung.unnamed.variables.UnnamedPatterns.getObjectsColorWithNamedPattern;
+import static com.baeldung.unnamed.variables.UnnamedPatterns.getObjectsColorWithSwitchAndNamedPattern;
+import static com.baeldung.unnamed.variables.UnnamedPatterns.getObjectsColorWithSwitchAndUnnamedPattern;
+import static com.baeldung.unnamed.variables.UnnamedPatterns.getObjectsColorWithUnnamedPattern;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.junit.jupiter.api.Test;
+
+public class UnnamedPatternsUnitTest extends CarScenario {
+
+ @Test
+ public void whenExtractingColorWithNamedPatterns_thenReturnBlue() {
+ assertEquals("blue", getObjectsColorWithNamedPattern(cars.get(0)));
+ }
+
+ @Test
+ public void whenExtractingColorWithUnnamedPatterns_thenReturnBlue() {
+ assertEquals("blue", getObjectsColorWithUnnamedPattern(cars.get(0)));
+ }
+
+ @Test
+ public void whenExtractingColorWithSwitchAndNamedPatterns_thenReturnBlue() {
+ assertEquals("blue", getObjectsColorWithSwitchAndNamedPattern(cars.get(0)));
+ }
+
+ @Test
+ public void whenExtractingColorWithSwitchAndUnnamedPatterns_thenReturnBlue() {
+ assertEquals("blue", getObjectsColorWithSwitchAndUnnamedPattern(cars.get(0)));
+ }
+
+ @Test
+ public void whenExtractingEngineTypeWithNamedPatterns_thenReturnGas() {
+ assertEquals("gas", getEngineTypeWithNamedPattern(cars.get(0)));
+ }
+
+ @Test
+ public void whenExtractingEngineTypeWithUnnamedPatterns_thenReturnGas() {
+ assertEquals("gas", getEngineTypeWithUnnamedPattern(cars.get(0)));
+ }
+}
diff --git a/core-java-modules/core-java-21/src/test/java/com/baeldung/unnamed/variables/UnnamedVariablesUnitTest.java b/core-java-modules/core-java-21/src/test/java/com/baeldung/unnamed/variables/UnnamedVariablesUnitTest.java
new file mode 100644
index 0000000000..094879c277
--- /dev/null
+++ b/core-java-modules/core-java-21/src/test/java/com/baeldung/unnamed/variables/UnnamedVariablesUnitTest.java
@@ -0,0 +1,93 @@
+package com.baeldung.unnamed.variables;
+
+import static com.baeldung.unnamed.variables.UnnamedVariables.countCarsOverLimitWithNamedVariable;
+import static com.baeldung.unnamed.variables.UnnamedVariables.countCarsOverLimitWithUnnamedVariable;
+import static com.baeldung.unnamed.variables.UnnamedVariables.getCarsByFirstLetterWithNamedVariables;
+import static com.baeldung.unnamed.variables.UnnamedVariables.getCarsByFirstLetterWithUnnamedVariables;
+import static com.baeldung.unnamed.variables.UnnamedVariables.handleCarExceptionWithNamedVariables;
+import static com.baeldung.unnamed.variables.UnnamedVariables.handleCarExceptionWithUnnamedVariables;
+import static com.baeldung.unnamed.variables.UnnamedVariables.obtainTransactionAndUpdateCarWithNamedVariables;
+import static com.baeldung.unnamed.variables.UnnamedVariables.obtainTransactionAndUpdateCarWithUnnamedVariables;
+import static com.baeldung.unnamed.variables.UnnamedVariables.removeThreeCarsAndReturnFirstRemovedWithNamedVariables;
+import static com.baeldung.unnamed.variables.UnnamedVariables.removeThreeCarsAndReturnFirstRemovedWithUnnamedVariables;
+import static com.baeldung.unnamed.variables.UnnamedVariables.sendNotificationToCarsWithNamedVariable;
+import static com.baeldung.unnamed.variables.UnnamedVariables.sendNotificationToCarsWithUnnamedVariable;
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.util.LinkedList;
+
+import org.junit.jupiter.api.Test;
+
+public class UnnamedVariablesUnitTest extends CarScenario {
+
+ @Test
+ public void whenCountingCarsOverLimitWithNamedVariables_thenShouldReturnOne() {
+ assertEquals(1, countCarsOverLimitWithNamedVariable(cars, 2));
+ }
+
+ @Test
+ public void whenCountingCarsOverLimitWithUnnamedVariables_thenShouldReturnOne() {
+ assertEquals(1, countCarsOverLimitWithUnnamedVariable(cars, 2));
+ }
+
+ @Test
+ public void whenNotifyingCarsWithNamedVariables_thenShouldNotFail() {
+ assertDoesNotThrow(() -> sendNotificationToCarsWithNamedVariable(cars));
+ }
+
+ @Test
+ public void whenNotifyingCarsWithUnnamedVariables_thenShouldNotFail() {
+ assertDoesNotThrow(() -> sendNotificationToCarsWithUnnamedVariable(cars));
+ }
+
+ @Test
+ public void whenPollingCarsWithNamedVariables_thenReturnFirstOneAndEmptyQueue() {
+ var carQueue = new LinkedList<>(cars);
+ assertEquals("Mitsubishi", removeThreeCarsAndReturnFirstRemovedWithNamedVariables(carQueue).name());
+ assertEquals(0, carQueue.size());
+ }
+
+ @Test
+ public void whenPollingCarsWithUnnamedVariables_thenReturnFirstOneAndEmptyQueue() {
+ var carQueue = new LinkedList<>(cars);
+ assertEquals("Mitsubishi", removeThreeCarsAndReturnFirstRemovedWithUnnamedVariables(carQueue).name());
+ assertEquals(0, carQueue.size());
+ }
+
+ @Test
+ public void whenHandlingExceptionWithNamedVariables_thenNoExceptionIsThrown() {
+ assertDoesNotThrow(() -> handleCarExceptionWithNamedVariables(cars.get(0)));
+ }
+
+ @Test
+ public void whenHandlingExceptionWithUnnamedVariables_thenNoExceptionIsThrown() {
+ assertDoesNotThrow(() -> handleCarExceptionWithUnnamedVariables(cars.get(0)));
+ }
+
+ @Test
+ public void whenHandlingTransactionUpdateWithNamedVariables_thenNoExceptionIsThrown() {
+ assertDoesNotThrow(() -> obtainTransactionAndUpdateCarWithNamedVariables(cars.get(0)));
+ }
+
+ @Test
+ public void whenHandlingTransactionUpdateWithUnnamedVariables_thenNoExceptionIsThrown() {
+ assertDoesNotThrow(() -> obtainTransactionAndUpdateCarWithUnnamedVariables(cars.get(0)));
+ }
+
+ @Test
+ public void whenGettingCarsByFirstLetterWithNamedVariables_thenHaveThreeKeys() {
+ var carsByLetter = getCarsByFirstLetterWithNamedVariables(cars);
+ assertEquals(1, carsByLetter.get("M").size());
+ assertEquals(1, carsByLetter.get("T").size());
+ assertEquals(1, carsByLetter.get("J").size());
+ }
+
+ @Test
+ public void whenGettingCarsByFirstLetterWithUnnamedVariables_thenHaveThreeKeys() {
+ var carsByLetter = getCarsByFirstLetterWithUnnamedVariables(cars);
+ assertEquals(1, carsByLetter.get("M").size());
+ assertEquals(1, carsByLetter.get("T").size());
+ assertEquals(1, carsByLetter.get("J").size());
+ }
+}
diff --git a/core-java-modules/core-java-8-datetime-2/README.md b/core-java-modules/core-java-8-datetime-2/README.md
index b860ca979d..ac1e1ca81f 100644
--- a/core-java-modules/core-java-8-datetime-2/README.md
+++ b/core-java-modules/core-java-8-datetime-2/README.md
@@ -5,4 +5,5 @@
- [Parsing Date Strings with Varying Formats](https://www.baeldung.com/java-parsing-dates-many-formats)
- [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)
- [[<-- Prev]](/core-java-modules/core-java-datetime-java8-1)
diff --git a/core-java-modules/core-java-8-datetime-2/src/test/java/com/baeldung/stringtime/AddMinuteStringTimeUnitTest.java b/core-java-modules/core-java-8-datetime-2/src/test/java/com/baeldung/stringtime/AddMinuteStringTimeUnitTest.java
new file mode 100644
index 0000000000..15b430cc6a
--- /dev/null
+++ b/core-java-modules/core-java-8-datetime-2/src/test/java/com/baeldung/stringtime/AddMinuteStringTimeUnitTest.java
@@ -0,0 +1,37 @@
+package com.baeldung.stringtime;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.time.LocalTime;
+import java.util.Calendar;
+import java.util.Date;
+import org.junit.jupiter.api.Test;
+
+public class AddMinuteStringTimeUnitTest {
+
+ @Test
+ public void givenTimeStringUsingSimpleDateFormat_whenIncrementedWith10Minutes_thenResultShouldBeCorrect() throws ParseException {
+ String timeString = "23:45";
+ SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm");
+ Date date = timeFormat.parse(timeString);
+
+ Calendar cal = Calendar.getInstance();
+ cal.setTime(date);
+ cal.add(Calendar.MINUTE, 10);
+ String result = timeFormat.format(cal.getTime());
+ assertEquals("23:55", result);
+
+ }
+
+ @Test
+ public void givenTimeStringUsingLocalTime_whenIncrementedWith10Minutes_thenResultShouldBeCorrect() {
+ String timeString = "23:45";
+ LocalTime time = LocalTime.parse(timeString);
+ LocalTime newTime = time.plusMinutes(10);
+ String result = newTime.toString();
+ assertEquals("23:55", result);
+ }
+
+}
diff --git a/core-java-modules/core-java-8-datetime/src/test/java/com/baeldung/dateapi/JavaDurationUnitTest.java b/core-java-modules/core-java-8-datetime/src/test/java/com/baeldung/dateapi/JavaDurationUnitTest.java
index be43fb609a..d1bd77776a 100644
--- a/core-java-modules/core-java-8-datetime/src/test/java/com/baeldung/dateapi/JavaDurationUnitTest.java
+++ b/core-java-modules/core-java-8-datetime/src/test/java/com/baeldung/dateapi/JavaDurationUnitTest.java
@@ -3,9 +3,11 @@ package com.baeldung.dateapi;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
import java.time.Duration;
import java.time.Instant;
+import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.temporal.ChronoUnit;
@@ -19,7 +21,7 @@ public class JavaDurationUnitTest {
LocalTime finalTime = initialTime.plus(Duration.ofSeconds(30));
long seconds = Duration.between(initialTime, finalTime)
- .getSeconds();
+ .getSeconds();
assertThat(seconds).isEqualTo(30);
}
@@ -34,6 +36,22 @@ public class JavaDurationUnitTest {
assertThat(seconds).isEqualTo(30);
}
+ @Test
+ public void givenADuration_whenCallingisZeroAndisNegative_thenGetExpectedResult() {
+ LocalDateTime start = LocalDateTime.parse("2020-01-01T08:00:00");
+ LocalDateTime end = LocalDateTime.parse("2020-01-01T12:00:00");
+ assertFalse(Duration.between(start, end)
+ .isNegative());
+ assertTrue(Duration.between(end, start)
+ .isNegative());
+
+ LocalDateTime theTime = LocalDateTime.parse("2023-09-09T08:00:00");
+ assertTrue(Duration.between(theTime, theTime)
+ .isZero());
+ assertFalse(Duration.between(theTime, theTime)
+ .isNegative());
+ }
+
@Test
public void test2() {
Instant start = Instant.parse("2017-10-03T10:15:30.00Z");
@@ -53,17 +71,17 @@ public class JavaDurationUnitTest {
assertEquals(1, fromMinutes.toHours());
assertEquals(120, duration.plusSeconds(60)
- .getSeconds());
+ .getSeconds());
assertEquals(30, duration.minusSeconds(30)
- .getSeconds());
+ .getSeconds());
assertEquals(120, duration.plus(60, ChronoUnit.SECONDS)
- .getSeconds());
+ .getSeconds());
assertEquals(30, duration.minus(30, ChronoUnit.SECONDS)
- .getSeconds());
+ .getSeconds());
Duration fromChar1 = Duration.parse("P1DT1H10M10.5S");
Duration fromChar2 = Duration.parse("PT10M");
}
-}
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-9-streams/README.md b/core-java-modules/core-java-9-streams/README.md
index 0ad8500689..d9663e0858 100644
--- a/core-java-modules/core-java-9-streams/README.md
+++ b/core-java-modules/core-java-9-streams/README.md
@@ -4,3 +4,4 @@ This module contains articles about Java 9 streams
### Relevant Articles:
- [How to Break from Java Stream forEach](https://www.baeldung.com/java-break-stream-foreach)
+- [Creating Stream of Regex Matches](https://www.baeldung.com/java-stream-regex-matches)
diff --git a/core-java-modules/core-java-arrays-guides/README.md b/core-java-modules/core-java-arrays-guides/README.md
index 0af77980af..d8b0d126a1 100644
--- a/core-java-modules/core-java-arrays-guides/README.md
+++ b/core-java-modules/core-java-arrays-guides/README.md
@@ -9,3 +9,4 @@ This module contains complete guides about arrays in Java
- [Guide to ArrayStoreException](https://www.baeldung.com/java-arraystoreexception)
- [Creating a Generic Array in Java](https://www.baeldung.com/java-generic-array)
- [Maximum Size of Java Arrays](https://www.baeldung.com/java-arrays-max-size)
+- [Merge Two Arrays and Remove Duplicates in Java](https://www.baeldung.com/java-merge-two-arrays-delete-duplicates)
diff --git a/core-java-modules/core-java-arrays-guides/src/main/java/com/baeldung/mergeandremoveduplicate/MergeArraysAndRemoveDuplicate.java b/core-java-modules/core-java-arrays-guides/src/main/java/com/baeldung/mergeandremoveduplicate/MergeArraysAndRemoveDuplicate.java
new file mode 100644
index 0000000000..e0b249565f
--- /dev/null
+++ b/core-java-modules/core-java-arrays-guides/src/main/java/com/baeldung/mergeandremoveduplicate/MergeArraysAndRemoveDuplicate.java
@@ -0,0 +1,96 @@
+package com.baeldung.mergeandremoveduplicate;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.stream.Stream;
+
+public class MergeArraysAndRemoveDuplicate {
+
+ public static int[] removeDuplicateOnSortedArray(int[] arr) {
+ // Initialize a new array to store unique elements
+ int[] uniqueArray = new int[arr.length];
+ uniqueArray[0] = arr[0];
+ int uniqueCount = 1;
+
+ // Iterate through the sorted array to remove duplicates
+ for (int i = 1; i < arr.length; i++) {
+ if (arr[i] != arr[i - 1]) {
+ uniqueArray[uniqueCount] = arr[i];
+ uniqueCount++;
+ }
+ }
+ int[] truncatedArray = new int[uniqueCount];
+ System.arraycopy(uniqueArray, 0, truncatedArray, 0, uniqueCount);
+ return truncatedArray;
+ }
+
+ public static int[] mergeAndRemoveDuplicatesUsingStream(int[] arr1, int[] arr2) {
+ Stream s1 = Arrays.stream(arr1).boxed();
+ Stream s2 = Arrays.stream(arr2).boxed();
+ return Stream.concat(s1, s2)
+ .distinct()
+ .mapToInt(Integer::intValue)
+ .toArray();
+ }
+
+ public static int[] mergeAndRemoveDuplicatesUsingSet(int[] arr1, int[] arr2) {
+ int[] mergedArr = mergeArrays(arr1, arr2);
+ Set uniqueInts = new HashSet<>();
+
+ for (int el : mergedArr) {
+ uniqueInts.add(el);
+ }
+
+ return getArrayFromSet(uniqueInts);
+ }
+
+ private static int[] getArrayFromSet(Set set) {
+ int[] mergedArrWithoutDuplicated = new int[set.size()];
+ int i = 0;
+ for (Integer el: set) {
+ mergedArrWithoutDuplicated[i] = el;
+ i++;
+ }
+ return mergedArrWithoutDuplicated;
+ }
+
+ public static int[] mergeAndRemoveDuplicates(int[] arr1, int[] arr2) {
+ return removeDuplicate(mergeArrays(arr1, arr2));
+ }
+
+ public static int[] mergeAndRemoveDuplicatesOnSortedArray(int[] arr1, int[] arr2) {
+ return removeDuplicateOnSortedArray(mergeArrays(arr1, arr2));
+ }
+
+ private static int[] mergeArrays(int[] arr1, int[] arr2) {
+ int[] mergedArrays = new int[arr1.length + arr2.length];
+ System.arraycopy(arr1, 0, mergedArrays, 0, arr1.length);
+ System.arraycopy(arr2, 0, mergedArrays, arr1.length, arr2.length);
+
+ return mergedArrays;
+ }
+ private static int[] removeDuplicate(int[] arr) {
+ int[] withoutDuplicates = new int[arr.length];
+ int i = 0;
+
+ for(int element : arr) {
+ if(!isElementPresent(withoutDuplicates, element)) {
+ withoutDuplicates[i] = element;
+ i++;
+ }
+ }
+ int[] truncatedArray = new int[i];
+ System.arraycopy(withoutDuplicates, 0, truncatedArray, 0, i);
+ return truncatedArray;
+ }
+
+ private static boolean isElementPresent(int[] arr, int element) {
+ for(int el : arr) {
+ if(el == element) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/core-java-modules/core-java-arrays-guides/src/test/java/com/baeldung/mergeandremoveduplicate/MergeArraysAndRemoveDuplicateUnitTest.java b/core-java-modules/core-java-arrays-guides/src/test/java/com/baeldung/mergeandremoveduplicate/MergeArraysAndRemoveDuplicateUnitTest.java
new file mode 100644
index 0000000000..5076ef8159
--- /dev/null
+++ b/core-java-modules/core-java-arrays-guides/src/test/java/com/baeldung/mergeandremoveduplicate/MergeArraysAndRemoveDuplicateUnitTest.java
@@ -0,0 +1,74 @@
+package com.baeldung.mergeandremoveduplicate;
+
+import org.junit.jupiter.api.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Arrays;
+import java.util.stream.Collectors;
+
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+
+public class MergeArraysAndRemoveDuplicateUnitTest {
+
+ private final Logger logger = LoggerFactory.getLogger(MergeArraysAndRemoveDuplicateUnitTest.class);
+
+ private static String getCommaDelimited(int[] arr) {
+ return Arrays.stream(arr)
+ .mapToObj(Integer::toString)
+ .collect(Collectors.joining(", "));
+ }
+
+ @Test
+ public void givenNoLibraryAndUnSortedArrays_whenArr1andArr2_thenMergeAndRemoveDuplicates() {
+ int[] arr1 = {3, 2, 1, 4, 5, 6, 8, 7, 9};
+ int[] arr2 = {8, 9, 10, 11, 12, 13, 15, 14, 15, 14, 16, 17};
+ int[] expectedArr = {3, 2, 1, 4, 5, 6, 8, 7, 9, 10, 11, 12, 13, 15, 14, 16, 17};
+
+ int[] mergedArr = MergeArraysAndRemoveDuplicate.mergeAndRemoveDuplicates(arr1, arr2);
+
+ //merged array maintains the order of the elements in the arrays
+ assertArrayEquals(expectedArr, mergedArr);
+
+ logger.info(getCommaDelimited(mergedArr));
+ }
+
+ @Test
+ public void givenNoLibraryAndSortedArrays_whenArr1andArr2_thenMergeAndRemoveDuplicates() {
+ int[] arr1 = {1, 2, 3, 4, 5, 5, 6, 7, 7, 8};
+ int[] arr2 = {8, 9, 10, 11, 12, 13, 14, 15, 15, 16, 17};
+ int[] expectedArr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17};
+
+ int[] mergedArr = MergeArraysAndRemoveDuplicate.mergeAndRemoveDuplicatesOnSortedArray(arr1, arr2);
+
+ assertArrayEquals(expectedArr, mergedArr);
+
+ logger.info(getCommaDelimited(mergedArr));
+ }
+
+ @Test
+ public void givenSet_whenArr1andArr2_thenMergeAndRemoveDuplicates() {
+ int[] arr1 = {3, 2, 1, 4, 5, 6, 8, 7, 9};
+ int[] arr2 = {8, 9, 10, 11, 12, 13, 15, 14, 15, 14, 16, 17};
+ int[] expectedArr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17};
+
+ int[] mergedArr = MergeArraysAndRemoveDuplicate.mergeAndRemoveDuplicatesUsingSet(arr1, arr2);
+
+ assertArrayEquals(expectedArr, mergedArr);
+
+ logger.info(getCommaDelimited(mergedArr));
+ }
+
+ @Test
+ public void givenStream_whenArr1andArr2_thenMergeAndRemoveDuplicates() {
+ int[] arr1 = {3, 2, 1, 4, 5, 6, 8, 7, 9};
+ int[] arr2 = {8, 9, 10, 11, 12, 13, 15, 14, 15, 14, 16, 17};
+ int[] expectedArr = {3, 2, 1, 4, 5, 6, 8, 7, 9, 10, 11, 12, 13, 15, 14, 16, 17};
+
+ int[] mergedArr = MergeArraysAndRemoveDuplicate.mergeAndRemoveDuplicatesUsingStream(arr1, arr2);
+
+ assertArrayEquals(expectedArr, mergedArr);
+
+ logger.info(getCommaDelimited(mergedArr));
+ }
+}
diff --git a/core-java-modules/core-java-arrays-operations-advanced-2/README.md b/core-java-modules/core-java-arrays-operations-advanced-2/README.md
new file mode 100644
index 0000000000..17ffa2562d
--- /dev/null
+++ b/core-java-modules/core-java-arrays-operations-advanced-2/README.md
@@ -0,0 +1,2 @@
+## Relevant Articles
+- [Find the Middle Element of an Array in Java](https://www.baeldung.com/java-array-middle-item)
diff --git a/core-java-modules/core-java-arrays-operations-advanced-2/pom.xml b/core-java-modules/core-java-arrays-operations-advanced-2/pom.xml
new file mode 100644
index 0000000000..53cccb8a73
--- /dev/null
+++ b/core-java-modules/core-java-arrays-operations-advanced-2/pom.xml
@@ -0,0 +1,46 @@
+
+
+ 4.0.0
+ core-java-arrays-operations-advanced-2
+ core-java-arrays-operations-advanced-2
+ jar
+
+
+ core-java-modules
+ com.baeldung.core-java-modules
+ 0.0.1-SNAPSHOT
+
+
+
+
+ org.apache.commons
+ commons-lang3
+ ${commons-lang3.version}
+
+
+
+
+
+
+ maven-assembly-plugin
+
+
+ jar-with-dependencies
+
+
+
+
+ make-assembly
+ package
+
+ single
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/core-java-modules/core-java-arrays-operations-advanced/src/main/java/com/baeldung/arraymiddle/MiddleOfArray.java b/core-java-modules/core-java-arrays-operations-advanced-2/src/main/java/com/baeldung/arraymiddle/MiddleOfArray.java
similarity index 99%
rename from core-java-modules/core-java-arrays-operations-advanced/src/main/java/com/baeldung/arraymiddle/MiddleOfArray.java
rename to core-java-modules/core-java-arrays-operations-advanced-2/src/main/java/com/baeldung/arraymiddle/MiddleOfArray.java
index f389893209..bfff003512 100644
--- a/core-java-modules/core-java-arrays-operations-advanced/src/main/java/com/baeldung/arraymiddle/MiddleOfArray.java
+++ b/core-java-modules/core-java-arrays-operations-advanced-2/src/main/java/com/baeldung/arraymiddle/MiddleOfArray.java
@@ -62,4 +62,4 @@ public class MiddleOfArray {
return array[mid];
}
}
-}
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-arrays-operations-advanced/src/test/java/com/baeldung/arraymiddle/MiddleOfArrayUnitTest.java b/core-java-modules/core-java-arrays-operations-advanced-2/src/test/java/com/baeldung/arraymiddle/MiddleOfArrayUnitTest.java
similarity index 99%
rename from core-java-modules/core-java-arrays-operations-advanced/src/test/java/com/baeldung/arraymiddle/MiddleOfArrayUnitTest.java
rename to core-java-modules/core-java-arrays-operations-advanced-2/src/test/java/com/baeldung/arraymiddle/MiddleOfArrayUnitTest.java
index 706412d83e..64a9796e67 100644
--- a/core-java-modules/core-java-arrays-operations-advanced/src/test/java/com/baeldung/arraymiddle/MiddleOfArrayUnitTest.java
+++ b/core-java-modules/core-java-arrays-operations-advanced-2/src/test/java/com/baeldung/arraymiddle/MiddleOfArrayUnitTest.java
@@ -86,4 +86,4 @@ public class MiddleOfArrayUnitTest {
MiddleOfArray middleOfArray = new MiddleOfArray();
Assert.assertEquals(expectMedian, middleOfArray.medianOfArray(array, 0, 100));
}
-}
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-arrays-operations-advanced/README.md b/core-java-modules/core-java-arrays-operations-advanced/README.md
index 0647d89d16..b379958f37 100644
--- a/core-java-modules/core-java-arrays-operations-advanced/README.md
+++ b/core-java-modules/core-java-arrays-operations-advanced/README.md
@@ -14,4 +14,3 @@ This module contains articles about advanced operations on arrays in Java. They
- [Slicing Arrays in Java](https://www.baeldung.com/java-slicing-arrays)
- [Combining Two or More Byte Arrays](https://www.baeldung.com/java-concatenate-byte-arrays)
- [Calculating the Sum of Two Arrays in Java](https://www.baeldung.com/java-sum-arrays-element-wise)
-- [Find the Middle Element of an Array in Java](https://www.baeldung.com/java-array-middle-item)
diff --git a/core-java-modules/core-java-char/README.md b/core-java-modules/core-java-char/README.md
index e4af3121c5..56040a3ea5 100644
--- a/core-java-modules/core-java-char/README.md
+++ b/core-java-modules/core-java-char/README.md
@@ -5,3 +5,4 @@ This module contains articles about Java Character Class
### Relevant Articles:
- [Character#isAlphabetic vs. Character#isLetter](https://www.baeldung.com/java-character-isletter-isalphabetic)
- [Difference Between Java’s “char” and “String”](https://www.baeldung.com/java-char-vs-string)
+- [Increment Character in Java](https://www.baeldung.com/java-char-sequence)
diff --git a/core-java-modules/core-java-char/src/test/java/com/baeldung/incrementchar/IncrementCharUnitTest.java b/core-java-modules/core-java-char/src/test/java/com/baeldung/incrementchar/IncrementCharUnitTest.java
new file mode 100644
index 0000000000..7621e85762
--- /dev/null
+++ b/core-java-modules/core-java-char/src/test/java/com/baeldung/incrementchar/IncrementCharUnitTest.java
@@ -0,0 +1,29 @@
+package com.baeldung.incrementchar;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
+class IncrementCharUnitTest {
+ @Test
+ void whenUsingForLoop_thenGenerateCharacters(){
+ final List allCapitalCharacters = Arrays.asList('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z');
+ List characters = new ArrayList<>();
+ for (char character = 'A'; character <= 'Z'; character++) {
+ characters.add(character);
+ }
+ Assertions.assertEquals(characters, allCapitalCharacters);
+ }
+
+ @Test
+ void whenUsingStreams_thenGenerateCharacters() {
+ final List allCapitalCharacters = Arrays.asList('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z');
+ final List characters = IntStream.rangeClosed('A', 'Z').mapToObj(c -> (char) c).collect(Collectors.toList());
+ Assertions.assertEquals(characters, allCapitalCharacters);
+ }
+}
diff --git a/core-java-modules/core-java-collections-5/README.md b/core-java-modules/core-java-collections-5/README.md
index 1769d11686..e478d87ad0 100644
--- a/core-java-modules/core-java-collections-5/README.md
+++ b/core-java-modules/core-java-collections-5/README.md
@@ -5,4 +5,6 @@
### Relevant Articles:
- [Introduction to Roaring Bitmap](https://www.baeldung.com/java-roaring-bitmap-intro)
- [Creating Custom Iterator in Java](https://www.baeldung.com/java-creating-custom-iterator)
+- [Difference Between Arrays.sort() and Collections.sort()](https://www.baeldung.com/java-arrays-collections-sort-methods)
+- [Skipping the First Iteration in Java](https://www.baeldung.com/java-skip-first-iteration)
- More articles: [[<-- prev]](/core-java-modules/core-java-collections-4)
diff --git a/core-java-modules/core-java-collections-5/src/main/java/com/baeldung/collectionsvsarrays/NonStableSortExample.java b/core-java-modules/core-java-collections-5/src/main/java/com/baeldung/collectionsvsarrays/NonStableSortExample.java
new file mode 100644
index 0000000000..cd754489a6
--- /dev/null
+++ b/core-java-modules/core-java-collections-5/src/main/java/com/baeldung/collectionsvsarrays/NonStableSortExample.java
@@ -0,0 +1,26 @@
+package com.baeldung.collectionsvsarrays;
+
+import com.baeldung.collectionsvsarrays.sorting.Quicksort;
+import java.util.Comparator;
+import java.util.List;
+
+public class NonStableSortExample {
+
+
+
+ public static void main(String[] args) {
+ List tasks = Tasks.supplier.get();
+ Quicksort.sort(tasks, Comparator.comparingInt(Task::getPriority));
+ System.out.println("After sorting by priority:");
+ for (Task task : tasks) {
+ System.out.println(task);
+ }
+ Quicksort.sort(tasks, Comparator.comparing(Task::getDueDate));
+ System.out.println("\nAfter sorting by due date:");
+ for (Task task : tasks) {
+ System.out.println(task);
+ }
+ }
+
+
+}
diff --git a/core-java-modules/core-java-collections-5/src/main/java/com/baeldung/collectionsvsarrays/ObjectOverheadBenchmark.java b/core-java-modules/core-java-collections-5/src/main/java/com/baeldung/collectionsvsarrays/ObjectOverheadBenchmark.java
new file mode 100644
index 0000000000..9a8adff507
--- /dev/null
+++ b/core-java-modules/core-java-collections-5/src/main/java/com/baeldung/collectionsvsarrays/ObjectOverheadBenchmark.java
@@ -0,0 +1,56 @@
+package com.baeldung.collectionsvsarrays;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.ThreadLocalRandom;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Supplier;
+import java.util.stream.Collectors;
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Fork;
+import org.openjdk.jmh.annotations.Measurement;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.annotations.Warmup;
+import org.openjdk.jmh.infra.Blackhole;
+
+@Measurement(iterations = 2, time = 10, timeUnit = TimeUnit.MINUTES)
+@Warmup(iterations = 5, time = 10)
+@Fork(value = 2)
+public class ObjectOverheadBenchmark {
+
+ private static final ThreadLocalRandom RANDOM = ThreadLocalRandom.current();
+
+ @State(Scope.Benchmark)
+ public static class Input {
+ public Supplier> randomNumbers = () -> RANDOM.ints().limit(10000).boxed().collect(Collectors.toList());
+ }
+
+ @Benchmark
+ @BenchmarkMode(Mode.Throughput)
+ public void sortingPrimitiveArray(Input input, Blackhole blackhole) {
+ final int[] array = input.randomNumbers.get().stream().mapToInt(Integer::intValue).toArray();
+ Arrays.sort(array);
+ final List result = Arrays.stream(array).boxed().collect(Collectors.toList());
+ blackhole.consume(result);
+ }
+
+ @Benchmark
+ @BenchmarkMode(Mode.Throughput)
+ public void sortingObjectArray(Input input, Blackhole blackhole) {
+ final Integer[] array = input.randomNumbers.get().toArray(new Integer[0]);
+ Arrays.sort(array);
+ blackhole.consume(array);
+ }
+
+ @Benchmark
+ @BenchmarkMode(Mode.Throughput)
+ public void sortingObjects(Input input, Blackhole blackhole) {
+ final List list = input.randomNumbers.get();
+ Collections.sort(list);
+ blackhole.consume(list);
+ }
+}
diff --git a/core-java-modules/core-java-collections-5/src/main/java/com/baeldung/collectionsvsarrays/PerformanceBenchmark.java b/core-java-modules/core-java-collections-5/src/main/java/com/baeldung/collectionsvsarrays/PerformanceBenchmark.java
new file mode 100644
index 0000000000..6e645b0fb9
--- /dev/null
+++ b/core-java-modules/core-java-collections-5/src/main/java/com/baeldung/collectionsvsarrays/PerformanceBenchmark.java
@@ -0,0 +1,51 @@
+package com.baeldung.collectionsvsarrays;
+
+import com.baeldung.collectionsvsarrays.sorting.MergeSort;
+import com.baeldung.collectionsvsarrays.sorting.Quicksort;
+import java.util.Random;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Supplier;
+import java.util.stream.IntStream;
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Fork;
+import org.openjdk.jmh.annotations.Measurement;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.Warmup;
+
+@Measurement(iterations = 2, time = 10, timeUnit = TimeUnit.MINUTES)
+@Warmup(iterations = 5, time = 10)
+public class PerformanceBenchmark {
+
+ private static final Random RANDOM = new Random();
+ private static final int ARRAY_SIZE = 10000;
+ private static final int[] randomNumbers = RANDOM.ints(ARRAY_SIZE).toArray();
+ private static final int[] sameNumbers = IntStream.generate(() -> 42).limit(ARRAY_SIZE).toArray();
+ public static final Supplier randomNumbersSupplier = randomNumbers::clone;
+ public static final Supplier sameNumbersSupplier = sameNumbers::clone;
+
+ @Benchmark
+ @BenchmarkMode(Mode.Throughput)
+ @Fork(value = 1, jvmArgs = {"-Xlog:gc:file=gc-logs-quick-sort-same-number-%t.txt,filesize=900m -Xmx6gb -Xms6gb"})
+ public void quickSortSameNumber() {
+ Quicksort.sort(sameNumbersSupplier.get());
+ }
+ @Benchmark
+ @BenchmarkMode(Mode.Throughput)
+ @Fork(value = 1, jvmArgs = {"-Xlog:gc:file=gc-logs-quick-sort-random-number-%t.txt,filesize=900m -Xmx6gb -Xms6gb"})
+ public void quickSortRandomNumber() {
+ Quicksort.sort(randomNumbersSupplier.get());
+ }
+ @Benchmark
+ @BenchmarkMode(Mode.Throughput)
+ @Fork(value = 1, jvmArgs = {"-Xlog:gc:file=gc-logs-merge-sort-same-number-%t.txt,filesize=900m -Xmx6gb -Xms6gb"})
+ public void mergeSortSameNumber() {
+ MergeSort.sort(sameNumbersSupplier.get());
+ }
+ @Benchmark
+ @BenchmarkMode(Mode.Throughput)
+ @Fork(value = 1, jvmArgs = {"-Xlog:gc:file=gc-logs-merge-sort-random-number-%t.txt,filesize=900m -Xmx6gb -Xms6gb"})
+ public void mergeSortRandomNumber() {
+ MergeSort.sort(randomNumbersSupplier.get());
+ }
+}
diff --git a/core-java-modules/core-java-collections-5/src/main/java/com/baeldung/collectionsvsarrays/StableSortExample.java b/core-java-modules/core-java-collections-5/src/main/java/com/baeldung/collectionsvsarrays/StableSortExample.java
new file mode 100644
index 0000000000..336673bac8
--- /dev/null
+++ b/core-java-modules/core-java-collections-5/src/main/java/com/baeldung/collectionsvsarrays/StableSortExample.java
@@ -0,0 +1,23 @@
+package com.baeldung.collectionsvsarrays;
+
+
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+public class StableSortExample {
+
+ public static void main(String[] args) {
+ final List tasks = Tasks.supplier.get();
+ Collections.sort(tasks, Comparator.comparingInt(Task::getPriority));
+ System.out.println("After sorting by priority:");
+ for (Task task : tasks) {
+ System.out.println(task);
+ }
+ Collections.sort(tasks, Comparator.comparing(Task::getDueDate));
+ System.out.println("\nAfter sorting by due date:");
+ for (Task task : tasks) {
+ System.out.println(task);
+ }
+ }
+}
diff --git a/core-java-modules/core-java-collections-5/src/main/java/com/baeldung/collectionsvsarrays/Task.java b/core-java-modules/core-java-collections-5/src/main/java/com/baeldung/collectionsvsarrays/Task.java
new file mode 100644
index 0000000000..133c39ccd2
--- /dev/null
+++ b/core-java-modules/core-java-collections-5/src/main/java/com/baeldung/collectionsvsarrays/Task.java
@@ -0,0 +1,30 @@
+package com.baeldung.collectionsvsarrays;
+
+public class Task {
+ private final long id;
+ private final int priority;
+ private final String dueDate;
+
+ public Task(final long id, int priority, String dueDate) {
+ this.id = id;
+ this.priority = priority;
+ this.dueDate = dueDate;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("Task: #%-2d | Priority: %d | Due Date: %s", getId(), getPriority(), getDueDate());
+ }
+
+ public int getPriority() {
+ return priority;
+ }
+
+ public String getDueDate() {
+ return dueDate;
+ }
+
+ private long getId() {
+ return id;
+ }
+}
diff --git a/core-java-modules/core-java-collections-5/src/main/java/com/baeldung/collectionsvsarrays/Tasks.java b/core-java-modules/core-java-collections-5/src/main/java/com/baeldung/collectionsvsarrays/Tasks.java
new file mode 100644
index 0000000000..fc413f549f
--- /dev/null
+++ b/core-java-modules/core-java-collections-5/src/main/java/com/baeldung/collectionsvsarrays/Tasks.java
@@ -0,0 +1,30 @@
+package com.baeldung.collectionsvsarrays;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Supplier;
+
+public class Tasks {
+
+ private static final List tasks;
+ public static final Supplier> supplier;
+
+ static {
+ tasks = new ArrayList<>();
+ tasks.add(new Task(1, 1, "2023-09-01"));
+ tasks.add(new Task(2, 2, "2023-08-30"));
+ tasks.add(new Task(3, 1, "2023-08-29"));
+ tasks.add(new Task(4, 2, "2023-09-02"));
+ tasks.add(new Task(5, 3, "2023-09-05"));
+ tasks.add(new Task(6, 1, "2023-09-03"));
+ tasks.add(new Task(7, 3, "2023-08-28"));
+ tasks.add(new Task(8, 2, "2023-09-01"));
+ tasks.add(new Task(9, 1, "2023-08-28"));
+ tasks.add(new Task(10, 2, "2023-09-04"));
+ tasks.add(new Task(11, 3, "2023-08-31"));
+ tasks.add(new Task(12, 1, "2023-08-30"));
+ tasks.add(new Task(13, 3, "2023-09-02"));
+
+ supplier = () -> new ArrayList<>(tasks);
+ }
+}
diff --git a/core-java-modules/core-java-collections-5/src/main/java/com/baeldung/collectionsvsarrays/sorting/MergeSort.java b/core-java-modules/core-java-collections-5/src/main/java/com/baeldung/collectionsvsarrays/sorting/MergeSort.java
new file mode 100644
index 0000000000..6078db50e0
--- /dev/null
+++ b/core-java-modules/core-java-collections-5/src/main/java/com/baeldung/collectionsvsarrays/sorting/MergeSort.java
@@ -0,0 +1,47 @@
+package com.baeldung.collectionsvsarrays.sorting;
+
+public class MergeSort {
+
+ public static void sort(int[] a) {
+ sort(a, a.length);
+ }
+ public static void sort(int[] a, int n) {
+ if (n < 2) {
+ return;
+ }
+ int mid = n / 2;
+ int[] l = new int[mid];
+ int[] r = new int[n - mid];
+
+ for (int i = 0; i < mid; i++) {
+ l[i] = a[i];
+ }
+ for (int i = mid; i < n; i++) {
+ r[i - mid] = a[i];
+ }
+ sort(l, mid);
+ sort(r, n - mid);
+
+ merge(a, l, r, mid, n - mid);
+ }
+ private static void merge(
+ int[] a, int[] l, int[] r, int left, int right) {
+
+ int i = 0, j = 0, k = 0;
+ while (i < left && j < right) {
+ if (l[i] <= r[j]) {
+ a[k++] = l[i++];
+ }
+ else {
+ a[k++] = r[j++];
+ }
+ }
+ while (i < left) {
+ a[k++] = l[i++];
+ }
+ while (j < right) {
+ a[k++] = r[j++];
+ }
+ }
+
+}
diff --git a/core-java-modules/core-java-collections-5/src/main/java/com/baeldung/collectionsvsarrays/sorting/Quicksort.java b/core-java-modules/core-java-collections-5/src/main/java/com/baeldung/collectionsvsarrays/sorting/Quicksort.java
new file mode 100644
index 0000000000..eab47b901b
--- /dev/null
+++ b/core-java-modules/core-java-collections-5/src/main/java/com/baeldung/collectionsvsarrays/sorting/Quicksort.java
@@ -0,0 +1,72 @@
+package com.baeldung.collectionsvsarrays.sorting;
+
+import java.util.Comparator;
+import java.util.List;
+
+public class Quicksort {
+
+ public static void sort(int arr[]) {
+ sort(arr, 0, arr.length - 1);
+ }
+ public static void sort(int arr[], int begin, int end) {
+ if (begin < end) {
+ int partitionIndex = partition(arr, begin, end);
+
+ sort(arr, begin, partitionIndex-1);
+ sort(arr, partitionIndex+1, end);
+ }
+ }
+ private static int partition(int arr[], int begin, int end) {
+ int pivot = arr[end];
+ int i = (begin-1);
+
+ for (int j = begin; j < end; j++) {
+ if (arr[j] <= pivot) {
+ i++;
+
+ int swapTemp = arr[i];
+ arr[i] = arr[j];
+ arr[j] = swapTemp;
+ }
+ }
+
+ int swapTemp = arr[i+1];
+ arr[i+1] = arr[end];
+ arr[end] = swapTemp;
+
+ return i+1;
+ }
+
+ public static void sort(List list, Comparator comparator) {
+ sort(list, 0, list.size() - 1, comparator);
+ }
+ public static void sort(List list, int low, int high, Comparator comparator) {
+ if (low < high) {
+ int partitionIndex = partition(list, low, high, comparator);
+
+ sort(list, low, partitionIndex - 1, comparator);
+ sort(list, partitionIndex + 1, high, comparator);
+ }
+ }
+
+ private static int partition(List list, int begin, int end, Comparator comparator) {
+ T pivot = list.get(end);
+ int i = (begin-1);
+
+ for (int j = begin; j < end; j++) {
+ if (comparator.compare(list.get(j), pivot) <= 0) {
+ i++;
+
+ T swapTemp = list.get(i);
+ list.set(i, list.get(j));
+ list.set(j, swapTemp);
+ }
+ }
+
+ T swapTemp = list.get(i+1);
+ list.set(i+1,list.get(end));
+ list.set(end, swapTemp);
+
+ return i+1;
+ }
+}
diff --git a/core-java-modules/core-java-collections-5/src/main/java/com/baeldung/skippingfirstelement/SkipFirstElementExample.java b/core-java-modules/core-java-collections-5/src/main/java/com/baeldung/skippingfirstelement/SkipFirstElementExample.java
new file mode 100644
index 0000000000..86982486fa
--- /dev/null
+++ b/core-java-modules/core-java-collections-5/src/main/java/com/baeldung/skippingfirstelement/SkipFirstElementExample.java
@@ -0,0 +1,126 @@
+package com.baeldung.skippingfirstelement;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+public class SkipFirstElementExample {
+
+ private final List stringList = new ArrayList<>();
+ private final Set stringSet = new HashSet<>();
+ private final Map stringMap = new HashMap<>();
+
+ public SkipFirstElementExample() {
+ // Initializing a List
+ stringList.add("Monday");
+ stringList.add("Tuesday");
+ stringList.add("Wednesday");
+ stringList.add("Thursday");
+ stringList.add("Friday");
+ stringList.add("Saturday");
+ stringList.add("Sunday");
+ // Initializing a Set
+ stringSet.add("Monday");
+ stringSet.add("Tuesday");
+ stringSet.add("Wednesday");
+ stringSet.add("Thursday");
+ stringSet.add("Friday");
+ stringSet.add("Saturday");
+ stringSet.add("Sunday");
+ // Initializing a Map
+ stringMap.put("Monday", "The day when coffee is a life support system.");
+ stringMap.put("Tuesday", "The day you realize that Monday's optimism was a lie.");
+ stringMap.put("Wednesday", "Hump Day, or as it's known, the 'Is it Friday yet?' day.");
+ stringMap.put("Thursday", "The day that says, 'Hold my beer, Friday is coming!'");
+ stringMap.put("Friday", "The golden child of the weekdays. The superhero of the workweek.");
+ stringMap.put("Saturday", "The day of rest? More like the day of 'What can I binge-watch next?'");
+ stringMap.put("Sunday", "The day before you have to adult again.");
+ }
+
+ void skippingFirstElementInListWithForLoop(List stringList) {
+ for (int i = 1; i < stringList.size(); i++) {
+ process(stringList.get(i));
+ }
+ }
+
+ void skippingFirstElementInListWithWhileLoop(List stringList) {
+ final Iterator iterator = stringList.iterator();
+ if (iterator.hasNext()) {
+ iterator.next();
+ }
+ while (iterator.hasNext()) {
+ process(iterator.next());
+ }
+ }
+
+ void skippingFirstElementInSetWithWhileLoop(Set stringSet) {
+ final Iterator iterator = stringSet.iterator();
+ if (iterator.hasNext()) {
+ iterator.next();
+ }
+ while (iterator.hasNext()) {
+ process(iterator.next());
+ }
+ }
+
+ void skippingFirstElementInListWithWhileLoopStoringFirstElement(List stringList) {
+ final Iterator iterator = stringList.iterator();
+ String firstElement = null;
+ if (iterator.hasNext()) {
+ firstElement = iterator.next();
+ }
+ while (iterator.hasNext()) {
+ process(iterator.next());
+ // additional logic using fistElement
+ }
+ }
+
+ void skippingFirstElementInMapWithStreamSkip(Map stringMap) {
+ stringMap.entrySet().stream().skip(1).forEach(this::process);
+ }
+
+ void skippingFirstElementInListWithSubList(List stringList) {
+ for (final String element : stringList.subList(1, stringList.size())) {
+ process(element);
+ }
+ }
+
+ void skippingFirstElementInListWithForLoopWithAdditionalCheck(List stringList) {
+ for (int i = 0; i < stringList.size(); i++) {
+ if (i == 0) {
+ // do something else
+ } else {
+ process(stringList.get(i));
+ }
+ }
+ }
+
+ void skippingFirstElementInListWithWhileLoopWithCounter(List stringList) {
+ int counter = 0;
+ while (counter < stringList.size()) {
+ if (counter != 0) {
+ process(stringList.get(counter));
+ }
+ ++counter;
+ }
+ }
+
+ void skippingFirstElementInListWithReduce(List stringList) {
+ stringList.stream().reduce((skip, element) -> {
+ process(element);
+ return element;
+ });
+ }
+
+ protected void process(String string) {
+ System.out.println(string);
+ }
+ protected void process(Entry mapEntry) {
+ System.out.println(mapEntry);
+ }
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-collections-5/src/test/java/com/baeldung/skippingfirstelement/SkipFirstElementExampleUnitTest.java b/core-java-modules/core-java-collections-5/src/test/java/com/baeldung/skippingfirstelement/SkipFirstElementExampleUnitTest.java
new file mode 100644
index 0000000000..9821b22ac7
--- /dev/null
+++ b/core-java-modules/core-java-collections-5/src/test/java/com/baeldung/skippingfirstelement/SkipFirstElementExampleUnitTest.java
@@ -0,0 +1,122 @@
+package com.baeldung.skippingfirstelement;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Stream;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.condition.EnabledForJreRange;
+import org.junit.jupiter.api.condition.JRE;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+@EnabledForJreRange(min = JRE.JAVA_9)
+class SkipFirstElementExampleUnitTest {
+
+ private static TestableSkipFirstElement testableSkip = new TestableSkipFirstElement();
+
+ @BeforeEach
+ void setup() {
+ testableSkip.reset();
+ }
+
+ private static Stream listProvider() {
+ return Stream.of(
+ Arguments.of(
+ List.of("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"),
+ List.of("Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"))
+ );
+ }
+
+ private static Stream mapProvider() {
+ return Stream.of(
+ Arguments.of(
+ Map.of(
+ "Monday", "The day when coffee is a life support system.",
+ "Tuesday", "The day you realize that Monday's optimism was a lie.",
+ "Wednesday", "Hump Day, or as it's known, the 'Is it Friday yet?' day.",
+ "Thursday", "The day that says, 'Hold my beer, Friday is coming!'",
+ "Friday", "The golden child of the weekdays. The superhero of the workweek.",
+ "Saturday", "The day of rest? More like the day of 'What can I binge-watch next?'",
+ "Sunday", "The day before you have to adult again."
+ )
+ )
+ );
+ }
+
+ @ParameterizedTest
+ @MethodSource("listProvider")
+ void skippingFirstElementInListWithForLoop(List input, List expected) {
+ testableSkip.skippingFirstElementInListWithForLoop(input);
+ List> actual = testableSkip.getResult();
+ assertEquals(actual, expected);
+ }
+
+ @ParameterizedTest
+ @MethodSource("listProvider")
+ void skippingFirstElementInListWithWhileLoop(List input, List expected) {
+ testableSkip.skippingFirstElementInListWithWhileLoop(input);
+ List> actual = testableSkip.getResult();
+ assertEquals(actual, expected);
+ }
+
+ @ParameterizedTest
+ @MethodSource("listProvider")
+ void skippingFirstElementInSetWithWhileLoop(List input) {
+ testableSkip.skippingFirstElementInSetWithWhileLoop(new HashSet<>(input));
+ Set> actual = new HashSet<>(testableSkip.getResult());
+ assertEquals(actual.size(), input.size() - 1);
+ }
+
+ @ParameterizedTest
+ @MethodSource("listProvider")
+ void skippingFirstElementInListWithWhileLoopStoringFirstElement(List input, List expected) {
+ testableSkip.skippingFirstElementInListWithWhileLoopStoringFirstElement(input);
+ List> actual = testableSkip.getResult();
+ assertEquals(actual, expected);
+ }
+
+ @ParameterizedTest
+ @MethodSource("mapProvider")
+ void skippingFirstElementInMapWithStreamSkip(Map input) {
+ testableSkip.skippingFirstElementInMapWithStreamSkip(input);
+ List> actual = testableSkip.getResult();
+ assertEquals(actual.size(), input.size() - 1);
+ }
+
+ @ParameterizedTest
+ @MethodSource("listProvider")
+ void skippingFirstElementInListWithSubList(List input, List expected) {
+ testableSkip.skippingFirstElementInListWithSubList(input);
+ List> actual = testableSkip.getResult();
+ assertEquals(actual, expected);
+ }
+
+ @ParameterizedTest
+ @MethodSource("listProvider")
+ void skippingFirstElementInListWithForLoopWithAdditionalCheck(List input, List expected) {
+ testableSkip.skippingFirstElementInListWithForLoopWithAdditionalCheck(input);
+ List> actual = testableSkip.getResult();
+ assertEquals(actual, expected);
+ }
+
+ @ParameterizedTest
+ @MethodSource("listProvider")
+ void skippingFirstElementInListWithWhileLoopWithCounter(List input, List expected) {
+ testableSkip.skippingFirstElementInListWithWhileLoopWithCounter(input);
+ List> actual = testableSkip.getResult();
+ assertEquals(actual, expected);
+ }
+
+ @ParameterizedTest
+ @MethodSource("listProvider")
+ void skippingFirstElementInListWithReduce(List input, List expected) {
+ testableSkip.skippingFirstElementInListWithReduce(input);
+ List> actual = testableSkip.getResult();
+ assertEquals(actual, expected);
+ }
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-collections-5/src/test/java/com/baeldung/skippingfirstelement/TestableSkip.java b/core-java-modules/core-java-collections-5/src/test/java/com/baeldung/skippingfirstelement/TestableSkip.java
new file mode 100644
index 0000000000..0e2f340485
--- /dev/null
+++ b/core-java-modules/core-java-collections-5/src/test/java/com/baeldung/skippingfirstelement/TestableSkip.java
@@ -0,0 +1,10 @@
+package com.baeldung.skippingfirstelement;
+
+import java.util.List;
+
+public interface TestableSkip {
+
+ void reset();
+
+ List> getResult();
+}
diff --git a/core-java-modules/core-java-collections-5/src/test/java/com/baeldung/skippingfirstelement/TestableSkipFirstElement.java b/core-java-modules/core-java-collections-5/src/test/java/com/baeldung/skippingfirstelement/TestableSkipFirstElement.java
new file mode 100644
index 0000000000..99facb73ad
--- /dev/null
+++ b/core-java-modules/core-java-collections-5/src/test/java/com/baeldung/skippingfirstelement/TestableSkipFirstElement.java
@@ -0,0 +1,37 @@
+package com.baeldung.skippingfirstelement;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map.Entry;
+
+public class TestableSkipFirstElement extends SkipFirstElementExample implements TestableSkip {
+
+
+ private List processedList = new ArrayList<>();
+ private List> processedEntryList = new ArrayList<>();
+
+ @Override
+ public void process(String string) {
+ processedList.add(string);
+ }
+
+ @Override
+ public void process(Entry stringEntry) {
+ processedEntryList.add(stringEntry);
+ }
+
+ @Override
+ public void reset() {
+ processedList.clear();
+ processedEntryList.clear();
+ }
+
+ @Override
+ public List> getResult() {
+ if (!processedList.isEmpty())
+ return processedList;
+ return processedEntryList;
+ }
+
+
+}
diff --git a/core-java-modules/core-java-collections-array-list-2/README.md b/core-java-modules/core-java-collections-array-list-2/README.md
new file mode 100644
index 0000000000..575e0dbb07
--- /dev/null
+++ b/core-java-modules/core-java-collections-array-list-2/README.md
@@ -0,0 +1,6 @@
+## Core Java Collections ArrayList
+
+This module contains articles about the Java ArrayList collection
+
+### Relevant Articles:
+- [Create an ArrayList with Multiple Object Types](https://www.baeldung.com/java-arraylist-multiple-object-types)
diff --git a/core-java-modules/core-java-collections-array-list-2/pom.xml b/core-java-modules/core-java-collections-array-list-2/pom.xml
new file mode 100644
index 0000000000..042f6e5bb5
--- /dev/null
+++ b/core-java-modules/core-java-collections-array-list-2/pom.xml
@@ -0,0 +1,32 @@
+
+ 4.0.0
+ core-java-collections-array-list-2
+ core-java-collections-array-list-2
+ jar
+
+ com.baeldung.core-java-modules
+ core-java-modules
+ 0.0.1-SNAPSHOT
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+ ${maven-compiler-plugin.target}
+
+
+
+
+
+
+ 17
+ 17
+
+
diff --git a/core-java-modules/core-java-collections-array-list-2/src/main/java/com/baeldung/list/multipleobjecttypes/AlternativeMultipeTypeList.java b/core-java-modules/core-java-collections-array-list-2/src/main/java/com/baeldung/list/multipleobjecttypes/AlternativeMultipeTypeList.java
new file mode 100644
index 0000000000..5315147dff
--- /dev/null
+++ b/core-java-modules/core-java-collections-array-list-2/src/main/java/com/baeldung/list/multipleobjecttypes/AlternativeMultipeTypeList.java
@@ -0,0 +1,51 @@
+package com.baeldung.list.multipleobjecttypes;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.function.Predicate;
+
+public class AlternativeMultipeTypeList {
+
+ public static void main(String[] args) {
+ // List of Parent Class
+ ArrayList myList = new ArrayList<>();
+ myList.add(1.2);
+ myList.add(2);
+ myList.add(-3.5);
+
+ // List of Interface type
+ ArrayList