Merge branch 'eugenp:master' into master
This commit is contained in:
commit
837cf3194a
Binary file not shown.
Binary file not shown.
|
@ -1,7 +1,5 @@
|
|||
package com.baeldung.algorithms.dfs;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.Queue;
|
||||
import java.util.Stack;
|
||||
|
||||
public class BinaryTree {
|
||||
|
@ -124,69 +122,43 @@ public class BinaryTree {
|
|||
}
|
||||
}
|
||||
|
||||
public void traverseLevelOrder() {
|
||||
if (root == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Queue<Node> nodes = new LinkedList<>();
|
||||
nodes.add(root);
|
||||
|
||||
while (!nodes.isEmpty()) {
|
||||
|
||||
Node node = nodes.remove();
|
||||
|
||||
System.out.print(" " + node.value);
|
||||
|
||||
if (node.left != null) {
|
||||
nodes.add(node.left);
|
||||
}
|
||||
|
||||
if (node.left != null) {
|
||||
nodes.add(node.right);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void traverseInOrderWithoutRecursion() {
|
||||
Stack<Node> stack = new Stack<Node>();
|
||||
Stack<Node> stack = new Stack<>();
|
||||
Node current = root;
|
||||
stack.push(root);
|
||||
while(! stack.isEmpty()) {
|
||||
while(current.left != null) {
|
||||
current = current.left;
|
||||
stack.push(current);
|
||||
}
|
||||
current = stack.pop();
|
||||
visit(current.value);
|
||||
if(current.right != null) {
|
||||
current = current.right;
|
||||
|
||||
while (current != null || !stack.isEmpty()) {
|
||||
while (current != null) {
|
||||
stack.push(current);
|
||||
current = current.left;
|
||||
}
|
||||
|
||||
Node top = stack.pop();
|
||||
visit(top.value);
|
||||
current = top.right;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void traversePreOrderWithoutRecursion() {
|
||||
Stack<Node> stack = new Stack<Node>();
|
||||
Node current = root;
|
||||
Stack<Node> stack = new Stack<>();
|
||||
Node current;
|
||||
stack.push(root);
|
||||
while(! stack.isEmpty()) {
|
||||
current = stack.pop();
|
||||
visit(current.value);
|
||||
|
||||
|
||||
if(current.right != null)
|
||||
stack.push(current.right);
|
||||
|
||||
|
||||
if(current.left != null)
|
||||
stack.push(current.left);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void traversePostOrderWithoutRecursion() {
|
||||
Stack<Node> stack = new Stack<Node>();
|
||||
Stack<Node> stack = new Stack<>();
|
||||
Node prev = root;
|
||||
Node current = root;
|
||||
Node current;
|
||||
stack.push(root);
|
||||
|
||||
while (!stack.isEmpty()) {
|
||||
|
@ -206,14 +178,14 @@ public class BinaryTree {
|
|||
stack.push(current.left);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void visit(int value) {
|
||||
System.out.print(" " + value);
|
||||
}
|
||||
}
|
||||
|
||||
class Node {
|
||||
|
||||
private void visit(int value) {
|
||||
System.out.print(" " + value);
|
||||
}
|
||||
|
||||
static class Node {
|
||||
int value;
|
||||
Node left;
|
||||
Node right;
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
package com.baeldung.algorithms.dfs;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class BinaryTreeUnitTest {
|
||||
|
||||
@Test
|
||||
|
@ -13,7 +13,7 @@ public class BinaryTreeUnitTest {
|
|||
|
||||
BinaryTree bt = createBinaryTree();
|
||||
|
||||
assertTrue(!bt.isEmpty());
|
||||
assertFalse(bt.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -111,14 +111,6 @@ public class BinaryTreeUnitTest {
|
|||
bt.traversePostOrderWithoutRecursion();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenABinaryTree_WhenTraversingLevelOrder_ThenPrintValues() {
|
||||
|
||||
BinaryTree bt = createBinaryTree();
|
||||
|
||||
bt.traverseLevelOrder();
|
||||
}
|
||||
|
||||
private BinaryTree createBinaryTree() {
|
||||
BinaryTree bt = new BinaryTree();
|
||||
|
||||
|
|
|
@ -27,3 +27,4 @@ HELP.md
|
|||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
|
|
@ -4,15 +4,15 @@ This following table contains test URLs that can be used with the Olingo V2 demo
|
|||
|
||||
| URL | Description |
|
||||
|------------------------------------------|-------------------------------------------------|
|
||||
| `http://localhost:8180/odata/$metadata` | fetch OData metadata document |
|
||||
| `http://localhost:8180/odata/CarMakers?$top=10&$skip=10` | Get 10 entities starting at offset 10 |
|
||||
| `http://localhost:8180/odata/CarMakers?$count` | Return total count of entities in this set |
|
||||
| `http://localhost:8180/odata/CarMakers?$filter=startswith(Name,'B')` | Return entities where the *Name* property starts with 'B' |
|
||||
| `http://localhost:8180/odata/CarModels?$filter=Year eq 2008 and CarMakerDetails/Name eq 'BWM'` | Return *CarModel* entities where the *Name* property of its maker starts with 'B' |
|
||||
| `http://localhost:8180/odata/CarModels(1L)?$expand=CarMakerDetails` | Return the *CarModel* with primary key '1', along with its maker|
|
||||
| `http://localhost:8180/odata/CarModels(1L)?$select=Name,Sku` | Return the *CarModel* with primary key '1', returing only its *Name* and *Sku* properties |
|
||||
| `http://localhost:8180/odata/CarModels?$orderBy=Name asc,Sku desc` | Return *CarModel* entities, ordered by the their *Name* and *Sku* properties |
|
||||
| `http://localhost:8180/odata/CarModels?$format=json` | Return *CarModel* entities, using a JSON representation|
|
||||
| `http://localhost:8080/odata/$metadata` | fetch OData metadata document |
|
||||
| `http://localhost:8080/odata/CarMakers?$top=10&$skip=10` | Get 10 entities starting at offset 10 |
|
||||
| `http://localhost:8080/odata/CarMakers?$count` | Return total count of entities in this set |
|
||||
| `http://localhost:8080/odata/CarMakers?$filter=startswith(Name,'B')` | Return entities where the *Name* property starts with 'B' |
|
||||
| `http://localhost:8080/odata/CarModels?$filter=Year eq 2008 and CarMakerDetails/Name eq 'BWM'` | Return *CarModel* entities where the *Name* property of its maker starts with 'B' |
|
||||
| `http://localhost:8080/odata/CarModels(1L)?$expand=CarMakerDetails` | Return the *CarModel* with primary key '1', along with its maker|
|
||||
| `http://localhost:8080/odata/CarModels(1L)?$select=Name,Sku` | Return the *CarModel* with primary key '1', returing only its *Name* and *Sku* properties |
|
||||
| `http://localhost:8080/odata/CarModels?$orderBy=Name asc,Sku desc` | Return *CarModel* entities, ordered by the their *Name* and *Sku* properties |
|
||||
| `http://localhost:8080/odata/CarModels?$format=json` | Return *CarModel* entities, using a JSON representation|
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -3,16 +3,16 @@
|
|||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.baeldung.examples.olingo2</groupId>
|
||||
<artifactId>olingo2</artifactId>
|
||||
<name>olingo2</name>
|
||||
<description>Sample Olingo 2 Project</description>
|
||||
<groupId>com.baeldung.examples.olingo</groupId>
|
||||
<artifactId>apache-olingo</artifactId>
|
||||
<name>apache-olingo</name>
|
||||
<description>Sample Apache Olingo Project</description>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>parent-boot-2</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<relativePath>../../parent-boot-2</relativePath>
|
||||
<relativePath>../parent-boot-2</relativePath>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
|
@ -43,7 +43,7 @@
|
|||
<dependency>
|
||||
<groupId>org.apache.olingo</groupId>
|
||||
<artifactId>olingo-odata2-core</artifactId>
|
||||
<version>${olingo2.version}</version>
|
||||
<version>${olingo.version}</version>
|
||||
<!-- Avoid jax-rs version conflict by excluding Olingo's version -->
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
|
@ -55,12 +55,12 @@
|
|||
<dependency>
|
||||
<groupId>org.apache.olingo</groupId>
|
||||
<artifactId>olingo-odata2-jpa-processor-core</artifactId>
|
||||
<version>${olingo2.version}</version>
|
||||
<version>${olingo.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.olingo</groupId>
|
||||
<artifactId>olingo-odata2-jpa-processor-ref</artifactId>
|
||||
<version>${olingo2.version}</version>
|
||||
<version>${olingo.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.eclipse.persistence</groupId>
|
||||
|
@ -80,7 +80,7 @@
|
|||
</build>
|
||||
|
||||
<properties>
|
||||
<olingo2.version>2.0.11</olingo2.version>
|
||||
<olingo.version>2.0.11</olingo.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
|
@ -27,11 +27,6 @@ import org.slf4j.Logger;
|
|||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* ODataJPAServiceFactory implementation for our sample domain
|
||||
* @author Philippe
|
||||
*
|
||||
*/
|
||||
@Component
|
||||
public class CarsODataJPAServiceFactory extends ODataJPAServiceFactory {
|
||||
|
||||
|
@ -44,7 +39,7 @@ public class CarsODataJPAServiceFactory extends ODataJPAServiceFactory {
|
|||
|
||||
/**
|
||||
* This method will be called by Olingo on every request to
|
||||
* initialize the ODataJPAContext that will be used.
|
||||
* initialize the ODataJPAContext that will be used.
|
||||
*/
|
||||
@Override
|
||||
public ODataJPAContext initializeODataJPAContext() throws ODataJPARuntimeException {
|
||||
|
@ -54,14 +49,14 @@ public class CarsODataJPAServiceFactory extends ODataJPAServiceFactory {
|
|||
ODataContext octx = ctx.getODataContext();
|
||||
HttpServletRequest request = (HttpServletRequest)octx.getParameter(ODataContext.HTTP_SERVLET_REQUEST_OBJECT);
|
||||
EntityManager em = (EntityManager)request.getAttribute(JerseyConfig.EntityManagerFilter.EM_REQUEST_ATTRIBUTE);
|
||||
|
||||
|
||||
// Here we're passing the EM that was created by the EntityManagerFilter (see JerseyConfig)
|
||||
ctx.setEntityManager(new EntityManagerWrapper(em));
|
||||
ctx.setPersistenceUnitName("default");
|
||||
|
||||
|
||||
// We're managing the EM's lifecycle, so we must inform Olingo that it should not
|
||||
// try to manage transactions and/or persistence sessions
|
||||
ctx.setContainerManaged(true);
|
||||
ctx.setContainerManaged(true);
|
||||
return ctx;
|
||||
}
|
||||
|
|
@ -1,6 +1,12 @@
|
|||
package com.baeldung.examples.olingo2;
|
||||
package com.baeldung.examples.olingo2;
|
||||
|
||||
import java.io.IOException;
|
||||
import org.apache.olingo.odata2.api.ODataServiceFactory;
|
||||
import org.apache.olingo.odata2.core.rest.ODataRootLocator;
|
||||
import org.apache.olingo.odata2.core.rest.app.ODataApplication;
|
||||
import org.glassfish.jersey.server.ResourceConfig;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
|
@ -15,28 +21,15 @@ import javax.ws.rs.container.ContainerResponseFilter;
|
|||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.ext.Provider;
|
||||
|
||||
import org.apache.olingo.odata2.api.ODataServiceFactory;
|
||||
import org.apache.olingo.odata2.core.rest.ODataRootLocator;
|
||||
import org.apache.olingo.odata2.core.rest.app.ODataApplication;
|
||||
import org.glassfish.jersey.server.ResourceConfig;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Jersey JAX-RS configuration
|
||||
* @author Philippe
|
||||
*
|
||||
*/
|
||||
@Component
|
||||
@ApplicationPath("/odata")
|
||||
public class JerseyConfig extends ResourceConfig {
|
||||
|
||||
|
||||
public JerseyConfig(CarsODataJPAServiceFactory serviceFactory, EntityManagerFactory emf) {
|
||||
|
||||
|
||||
|
||||
public JerseyConfig(CarsODataJPAServiceFactory serviceFactory, EntityManagerFactory emf) {
|
||||
|
||||
ODataApplication app = new ODataApplication();
|
||||
|
||||
|
||||
app
|
||||
.getClasses()
|
||||
.forEach( c -> {
|
||||
|
@ -46,11 +39,11 @@ public class JerseyConfig extends ResourceConfig {
|
|||
register(c);
|
||||
}
|
||||
});
|
||||
|
||||
register(new CarsRootLocator(serviceFactory));
|
||||
|
||||
register(new CarsRootLocator(serviceFactory));
|
||||
register( new EntityManagerFilter(emf));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This filter handles the EntityManager transaction lifecycle.
|
||||
* @author Philippe
|
||||
|
@ -72,7 +65,7 @@ public class JerseyConfig extends ResourceConfig {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void filter(ContainerRequestContext ctx) throws IOException {
|
||||
public void filter(ContainerRequestContext ctx) {
|
||||
log.info("[I60] >>> filter");
|
||||
EntityManager em = this.emf.createEntityManager();
|
||||
httpRequest.setAttribute(EM_REQUEST_ATTRIBUTE, em);
|
||||
|
@ -85,7 +78,7 @@ public class JerseyConfig extends ResourceConfig {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
|
||||
public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) {
|
||||
|
||||
log.info("[I68] <<< filter");
|
||||
EntityManager em = (EntityManager) httpRequest.getAttribute(EM_REQUEST_ATTRIBUTE);
|
|
@ -7,7 +7,7 @@ import org.springframework.boot.web.servlet.support.SpringBootServletInitializer
|
|||
@SpringBootApplication
|
||||
public class Olingo2SampleApplication extends SpringBootServletInitializer {
|
||||
|
||||
public static void main(String[] args) {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(Olingo2SampleApplication.class);
|
||||
}
|
||||
}
|
|
@ -7,7 +7,7 @@ import org.springframework.test.context.junit4.SpringRunner;
|
|||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest
|
||||
public class Olingo2SampleApplicationUnitTest {
|
||||
public class Olingo2SampleApplicationIntegrationTest {
|
||||
|
||||
@Test
|
||||
public void contextLoads() {
|
|
@ -9,4 +9,6 @@ This module contains articles about Apache POI.
|
|||
- [Numeric Format Using POI](https://www.baeldung.com/apache-poi-numeric-format)
|
||||
- [Microsoft Word Processing in Java with Apache POI](https://www.baeldung.com/java-microsoft-word-with-apache-poi)
|
||||
- [Creating a MS PowerPoint Presentation in Java](https://www.baeldung.com/apache-poi-slideshow)
|
||||
- [Finding the Last Row in an Excel Spreadsheet From Java](https://www.baeldung.com/java-excel-find-last-row)
|
||||
- [Setting Formulas in Excel with Apache POI](https://www.baeldung.com/java-apache-poi-set-formulas)
|
||||
- More articles: [[<-- prev]](../apache-poi)
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
</dependencies>
|
||||
|
||||
<properties>
|
||||
<poi.version>5.0.0</poi.version>
|
||||
<poi.version>5.2.0</poi.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
|
|
|
@ -1,26 +1,25 @@
|
|||
package com.baeldung.poi.excel.setformula;
|
||||
|
||||
import org.apache.poi.xssf.usermodel.XSSFCell;
|
||||
import org.apache.poi.xssf.usermodel.XSSFFormulaEvaluator;
|
||||
import org.apache.poi.xssf.usermodel.XSSFSheet;
|
||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
public class ExcelFormula {
|
||||
public double setFormula(String fileLocation, XSSFWorkbook wb, String formula) throws IOException {
|
||||
XSSFSheet sheet = wb.getSheetAt(0);
|
||||
int lastCellNum = sheet.getRow(0).getLastCellNum();
|
||||
XSSFCell formulaCell = sheet.getRow(0).createCell(lastCellNum);
|
||||
formulaCell.setCellFormula(formula);
|
||||
XSSFFormulaEvaluator formulaEvaluator = wb.getCreationHelper().createFormulaEvaluator();
|
||||
formulaEvaluator.evaluateFormulaCell(formulaCell);
|
||||
FileOutputStream fileOut = new FileOutputStream(new File(fileLocation));
|
||||
wb.write(fileOut);
|
||||
wb.close();
|
||||
fileOut.close();
|
||||
return formulaCell.getNumericCellValue();
|
||||
}
|
||||
}
|
||||
package com.baeldung.poi.excel.setformula;
|
||||
|
||||
import org.apache.poi.xssf.usermodel.XSSFCell;
|
||||
import org.apache.poi.xssf.usermodel.XSSFFormulaEvaluator;
|
||||
import org.apache.poi.xssf.usermodel.XSSFSheet;
|
||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
public class ExcelFormula {
|
||||
public double setFormula(String fileLocation, XSSFWorkbook wb, String formula) throws IOException {
|
||||
XSSFSheet sheet = wb.getSheetAt(0);
|
||||
int lastCellNum = sheet.getRow(0).getLastCellNum();
|
||||
XSSFCell formulaCell = sheet.getRow(0).createCell(lastCellNum);
|
||||
formulaCell.setCellFormula(formula);
|
||||
XSSFFormulaEvaluator formulaEvaluator = wb.getCreationHelper().createFormulaEvaluator();
|
||||
formulaEvaluator.evaluateFormulaCell(formulaCell);
|
||||
FileOutputStream fileOut = new FileOutputStream(fileLocation);
|
||||
wb.write(fileOut);
|
||||
wb.close();
|
||||
fileOut.close();
|
||||
return formulaCell.getNumericCellValue();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
package com.baeldung.poi.excel.lastrow;
|
||||
|
||||
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 org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
public class LastRowUnitTest {
|
||||
private static final String FILE_NAME = "lastRowTest.xlsx";
|
||||
private String fileLocation;
|
||||
|
||||
@Before
|
||||
public void setup() throws URISyntaxException {
|
||||
fileLocation = Paths.get(ClassLoader.getSystemResource(FILE_NAME).toURI()).toString();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenExampleGrid_whenGetRow_thenReturnRowObjectIfModified() throws IOException {
|
||||
Workbook workbook = new XSSFWorkbook(fileLocation);
|
||||
Sheet sheet = workbook.getSheetAt(0);
|
||||
|
||||
assertEquals(7, sheet.getLastRowNum());
|
||||
assertEquals(6, sheet.getPhysicalNumberOfRows());
|
||||
|
||||
assertNotNull(sheet.getRow(0));
|
||||
assertNotNull(sheet.getRow(1));
|
||||
assertNotNull(sheet.getRow(2));
|
||||
assertNotNull(sheet.getRow(3));
|
||||
assertNull(sheet.getRow(4));
|
||||
assertNull(sheet.getRow(5));
|
||||
assertNotNull(sheet.getRow(6));
|
||||
assertNotNull(sheet.getRow(7));
|
||||
assertNull(sheet.getRow(8));
|
||||
|
||||
assertSame(sheet.getRow(7), getLastRowFromSheet(sheet));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenEmptySheet_whenGetRow_thenReturnNull() throws IOException {
|
||||
Workbook workbook = new XSSFWorkbook(fileLocation);
|
||||
Sheet sheet = workbook.getSheetAt(1);
|
||||
|
||||
assertEquals(-1, sheet.getLastRowNum());
|
||||
assertEquals(0, sheet.getPhysicalNumberOfRows());
|
||||
|
||||
assertNull(sheet.getRow(0));
|
||||
|
||||
assertSame(sheet.getRow(0), getLastRowFromSheet(sheet));
|
||||
}
|
||||
|
||||
public static Row getLastRowFromSheet(Sheet sheet) {
|
||||
Row lastRow = null;
|
||||
int lastRowNum = sheet.getLastRowNum();
|
||||
if (lastRowNum >= 0) {
|
||||
lastRow = sheet.getRow(lastRowNum);
|
||||
}
|
||||
return lastRow;
|
||||
}
|
||||
}
|
|
@ -3,18 +3,19 @@ package com.baeldung.poi.excel.setformula;
|
|||
import org.apache.poi.ss.util.CellReference;
|
||||
import org.apache.poi.xssf.usermodel.XSSFSheet;
|
||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||
import org.junit.Assert;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
class ExcelFormulaUnitTest {
|
||||
private static String FILE_NAME = "com/baeldung/poi/excel/setformula/SetFormulaTest.xlsx";
|
||||
private static final String FILE_NAME = "com/baeldung/poi/excel/setformula/SetFormulaTest.xlsx";
|
||||
|
||||
private String fileLocation;
|
||||
private ExcelFormula excelFormula;
|
||||
|
||||
|
@ -26,7 +27,7 @@ class ExcelFormulaUnitTest {
|
|||
|
||||
@Test
|
||||
void givenExcelData_whenSetFormula_thenSuccess() throws IOException {
|
||||
FileInputStream inputStream = new FileInputStream(new File(fileLocation));
|
||||
FileInputStream inputStream = new FileInputStream(fileLocation);
|
||||
XSSFWorkbook wb = new XSSFWorkbook(inputStream);
|
||||
XSSFSheet sheet = wb.getSheetAt(0);
|
||||
double resultColumnA = 0;
|
||||
|
@ -46,6 +47,6 @@ class ExcelFormulaUnitTest {
|
|||
|
||||
double resultValue = excelFormula.setFormula(fileLocation, wb, sumFormulaForColumnA + "-" + sumFormulaForColumnB);
|
||||
|
||||
Assert.assertEquals(resultColumnA - resultColumnB, resultValue, 0d);
|
||||
assertEquals(resultColumnA - resultColumnB, resultValue, 0d);
|
||||
}
|
||||
}
|
Binary file not shown.
|
@ -1,3 +1,5 @@
|
|||
*.docx
|
||||
temp.xls
|
||||
temp.xlsx
|
||||
|
||||
CellStyleTest_output.xlsx
|
|
@ -8,10 +8,10 @@ This module contains articles about Apache POI.
|
|||
- [Merge Cells in Excel Using Apache POI](https://www.baeldung.com/java-apache-poi-merge-cells)
|
||||
- [Get String Value of Excel Cell with Apache POI](https://www.baeldung.com/java-apache-poi-cell-string-value)
|
||||
- [Read Excel Cell Value Rather Than Formula With Apache POI](https://www.baeldung.com/apache-poi-read-cell-value-formula)
|
||||
- [Setting Formulas in Excel with Apache POI](https://www.baeldung.com/java-apache-poi-set-formulas)
|
||||
- [Insert a Row in Excel Using Apache POI](https://www.baeldung.com/apache-poi-insert-excel-row)
|
||||
- [Multiline Text in Excel Cell Using Apache POI](https://www.baeldung.com/apache-poi-write-multiline-text)
|
||||
- [Set Background Color of a Cell with Apache POI](https://www.baeldung.com/apache-poi-background-color)
|
||||
- [Add Borders to Excel Cells With Apache POI](https://www.baeldung.com/apache-poi-add-borders)
|
||||
- [Reading Values From Excel in Java](https://www.baeldung.com/java-read-dates-excel)
|
||||
- [Change Cell Font Style with Apache POI](https://www.baeldung.com/apache-poi-change-cell-font)
|
||||
- More articles: [[next -->]](../apache-poi-2)
|
||||
|
|
|
@ -32,9 +32,27 @@
|
|||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-resources-plugin</artifactId>
|
||||
<version>${maven.resources.plugin.version}</version>
|
||||
<configuration>
|
||||
<encoding>UTF-8</encoding>
|
||||
<nonFilteredFileExtensions>
|
||||
<nonFilteredFileExtension>xlsx</nonFilteredFileExtension>
|
||||
<nonFilteredFileExtension>xls</nonFilteredFileExtension>
|
||||
</nonFilteredFileExtensions>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<properties>
|
||||
<poi.version>4.1.1</poi.version>
|
||||
<poi.version>5.2.0</poi.version>
|
||||
<jexcel.version>1.0.6</jexcel.version>
|
||||
<maven.resources.plugin.version>3.2.0</maven.resources.plugin.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
|
@ -1,25 +1,24 @@
|
|||
package com.baeldung.poi.excel;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
import org.apache.poi.ss.usermodel.CellType;
|
||||
import org.apache.poi.ss.usermodel.CellStyle;
|
||||
import org.apache.poi.ss.usermodel.DateUtil;
|
||||
import org.apache.poi.ss.usermodel.FillPatternType;
|
||||
import org.apache.poi.ss.usermodel.IndexedColors;
|
||||
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 org.apache.poi.xssf.usermodel.XSSFFont;
|
||||
import org.apache.poi.ss.usermodel.DateUtil;
|
||||
import org.apache.poi.ss.usermodel.FillPatternType;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||
|
||||
public class ExcelPOIHelper {
|
||||
|
||||
|
@ -33,7 +32,7 @@ public class ExcelPOIHelper {
|
|||
for (Row row : sheet) {
|
||||
data.put(i, new ArrayList<String>());
|
||||
for (Cell cell : row) {
|
||||
switch (cell.getCellTypeEnum()) {
|
||||
switch (cell.getCellType()) {
|
||||
case STRING:
|
||||
data.get(i)
|
||||
.add(cell.getRichStringCellValue()
|
||||
|
|
|
@ -44,6 +44,7 @@ public class ExcelUtility {
|
|||
}
|
||||
}
|
||||
inputStream.close();
|
||||
baeuldungWorkBook.close();
|
||||
|
||||
} catch (IOException e) {
|
||||
throw e;
|
||||
|
|
|
@ -1,128 +0,0 @@
|
|||
package com.baeldung.poi.excel;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
import org.apache.poi.ss.usermodel.CellType;
|
||||
import org.apache.poi.ss.usermodel.DateUtil;
|
||||
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;
|
||||
|
||||
public class ExcelUtility {
|
||||
<<<<<<< HEAD
|
||||
private static final String ENDLINE = System.getProperty("line.separator");
|
||||
|
||||
public static String readExcel(String filePath) throws IOException {
|
||||
File file = new File(filePath);
|
||||
FileInputStream inputStream = null;
|
||||
StringBuilder toReturn = new StringBuilder();
|
||||
try {
|
||||
inputStream = new FileInputStream(file);
|
||||
Workbook baeuldungWorkBook = new XSSFWorkbook(inputStream);
|
||||
for (Sheet sheet : baeuldungWorkBook) {
|
||||
toReturn.append("--------------------------------------------------------------------")
|
||||
.append(ENDLINE);
|
||||
toReturn.append("Worksheet :")
|
||||
.append(sheet.getSheetName())
|
||||
.append(ENDLINE);
|
||||
toReturn.append("--------------------------------------------------------------------")
|
||||
.append(ENDLINE);
|
||||
int firstRow = sheet.getFirstRowNum();
|
||||
int lastRow = sheet.getLastRowNum();
|
||||
for (int index = firstRow + 1; index <= lastRow; index++) {
|
||||
Row row = sheet.getRow(index);
|
||||
toReturn.append("|| ");
|
||||
for (int cellIndex = row.getFirstCellNum(); cellIndex < row.getLastCellNum(); cellIndex++) {
|
||||
Cell cell = row.getCell(cellIndex, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK);
|
||||
printCellValue(cell, toReturn);
|
||||
}
|
||||
toReturn.append(" ||")
|
||||
.append(ENDLINE);
|
||||
}
|
||||
}
|
||||
inputStream.close();
|
||||
|
||||
} catch (IOException e) {
|
||||
throw e;
|
||||
}
|
||||
return toReturn.toString();
|
||||
}
|
||||
|
||||
public static void printCellValue(Cell cell, StringBuilder toReturn) {
|
||||
CellType cellType = cell.getCellType()
|
||||
.equals(CellType.FORMULA) ? cell.getCachedFormulaResultType() : cell.getCellType();
|
||||
if (cellType.equals(CellType.STRING)) {
|
||||
toReturn.append(cell.getStringCellValue())
|
||||
.append(" | ");
|
||||
}
|
||||
if (cellType.equals(CellType.NUMERIC)) {
|
||||
if (DateUtil.isCellDateFormatted(cell)) {
|
||||
toReturn.append(cell.getDateCellValue())
|
||||
.append(" | ");
|
||||
} else {
|
||||
toReturn.append(cell.getNumericCellValue())
|
||||
.append(" | ");
|
||||
}
|
||||
}
|
||||
if (cellType.equals(CellType.BOOLEAN)) {
|
||||
toReturn.append(cell.getBooleanCellValue())
|
||||
.append(" | ");
|
||||
}
|
||||
}
|
||||
=======
|
||||
private static final String ENDLINE = System.getProperty("line.separator");
|
||||
|
||||
public static String readExcel(String filePath) throws IOException {
|
||||
File file = new File(filePath);
|
||||
FileInputStream inputStream = null;
|
||||
StringBuilder toReturn = new StringBuilder();
|
||||
try {
|
||||
inputStream = new FileInputStream(file);
|
||||
Workbook baeuldungWorkBook = new XSSFWorkbook(inputStream);
|
||||
for (Sheet sheet : baeuldungWorkBook) {
|
||||
toReturn.append("--------------------------------------------------------------------").append(ENDLINE);
|
||||
toReturn.append("Worksheet :").append(sheet.getSheetName()).append(ENDLINE);
|
||||
toReturn.append("--------------------------------------------------------------------").append(ENDLINE);
|
||||
int firstRow = sheet.getFirstRowNum();
|
||||
int lastRow = sheet.getLastRowNum();
|
||||
for (int index = firstRow + 1; index <= lastRow; index++) {
|
||||
Row row = sheet.getRow(index);
|
||||
toReturn.append("|| ");
|
||||
for (int cellIndex = row.getFirstCellNum(); cellIndex < row.getLastCellNum(); cellIndex++) {
|
||||
Cell cell = row.getCell(cellIndex, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK);
|
||||
printCellValue(cell, toReturn);
|
||||
}
|
||||
toReturn.append(" ||").append(ENDLINE);
|
||||
}
|
||||
}
|
||||
inputStream.close();
|
||||
|
||||
} catch (IOException e) {
|
||||
throw e;
|
||||
}
|
||||
return toReturn.toString();
|
||||
}
|
||||
|
||||
public static void printCellValue(Cell cell, StringBuilder toReturn) {
|
||||
CellType cellType = cell.getCellType().equals(CellType.FORMULA) ? cell.getCachedFormulaResultType()
|
||||
: cell.getCellType();
|
||||
if (cellType.equals(CellType.STRING)) {
|
||||
toReturn.append(cell.getStringCellValue()).append(" | ");
|
||||
}
|
||||
if (cellType.equals(CellType.NUMERIC)) {
|
||||
if (DateUtil.isCellDateFormatted(cell)) {
|
||||
toReturn.append(cell.getDateCellValue()).append(" | ");
|
||||
} else {
|
||||
toReturn.append(cell.getNumericCellValue()).append(" | ");
|
||||
}
|
||||
}
|
||||
if (cellType.equals(CellType.BOOLEAN)) {
|
||||
toReturn.append(cell.getBooleanCellValue()).append(" | ");
|
||||
}
|
||||
}
|
||||
>>>>>>> master
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package com.baeldung.poi.excel.cellstyle;
|
||||
|
||||
import org.apache.poi.hssf.util.HSSFColor.HSSFColorPredefined;
|
||||
import org.apache.poi.ss.usermodel.CellStyle;
|
||||
import org.apache.poi.ss.usermodel.Font;
|
||||
import org.apache.poi.ss.usermodel.HorizontalAlignment;
|
||||
import org.apache.poi.ss.usermodel.VerticalAlignment;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
|
||||
public class CellStyler {
|
||||
public CellStyle createWarningColor(Workbook workbook) {
|
||||
CellStyle style = workbook.createCellStyle();
|
||||
|
||||
Font font = workbook.createFont();
|
||||
font.setFontName("Courier New");
|
||||
font.setBold(true);
|
||||
font.setUnderline(Font.U_SINGLE);
|
||||
font.setColor(HSSFColorPredefined.DARK_RED.getIndex());
|
||||
style.setFont(font);
|
||||
|
||||
style.setAlignment(HorizontalAlignment.CENTER);
|
||||
style.setVerticalAlignment(VerticalAlignment.CENTER);
|
||||
return style;
|
||||
}
|
||||
}
|
Binary file not shown.
Binary file not shown.
|
@ -1,25 +1,18 @@
|
|||
package com.baeldung.jexcel;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import jxl.read.biff.BiffException;
|
||||
import java.util.Map;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.baeldung.jexcel.JExcelHelper;
|
||||
|
||||
import jxl.write.WriteException;
|
||||
import jxl.read.biff.BiffException;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.Before;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import jxl.read.biff.BiffException;
|
||||
import jxl.write.WriteException;
|
||||
|
||||
public class JExcelIntegrationTest {
|
||||
|
||||
|
|
|
@ -1,22 +1,15 @@
|
|||
package com.baeldung.poi.excel;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import jxl.read.biff.BiffException;
|
||||
import java.util.Map;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.baeldung.poi.excel.ExcelPOIHelper;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.Before;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
public class ExcelIntegrationTest {
|
||||
|
||||
|
|
|
@ -1,112 +0,0 @@
|
|||
package com.baeldung.poi.excel;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.file.Paths;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
public class ExcelUtilityUnitTest {
|
||||
<<<<<<< HEAD
|
||||
private static final String FILE_NAME = "baeldung.xlsx";
|
||||
private String fileLocation;
|
||||
private static final String ENDLINE = System.getProperty("line.separator");
|
||||
private StringBuilder output;
|
||||
|
||||
@Before
|
||||
public void setupUnitTest() throws IOException, URISyntaxException, ParseException {
|
||||
output = new StringBuilder();
|
||||
output.append("--------------------------------------------------------------------")
|
||||
.append(ENDLINE);
|
||||
output.append("Worksheet :Sheet1")
|
||||
.append(ENDLINE);
|
||||
output.append("--------------------------------------------------------------------")
|
||||
.append(ENDLINE);
|
||||
output.append("|| Name1 | Surname1 | 3.55696564113E11 | ")
|
||||
.append(new SimpleDateFormat("dd/MM/yyyy").parse("4/11/2021")
|
||||
.toString())
|
||||
.append(" | ‡ | ||")
|
||||
.append(ENDLINE);
|
||||
output.append("|| Name2 | Surname2 | 5.646513512E9 | ")
|
||||
.append(new SimpleDateFormat("dd/MM/yyyy").parse("4/12/2021")
|
||||
.toString())
|
||||
.append(" | false | ||")
|
||||
.append(ENDLINE);
|
||||
output.append("|| Name3 | Surname3 | 3.55696564113E11 | ")
|
||||
.append(new SimpleDateFormat("dd/MM/yyyy").parse("4/11/2021")
|
||||
.toString())
|
||||
.append(" | 7.17039641738E11 | ||")
|
||||
.append(ENDLINE);
|
||||
output.append("--------------------------------------------------------------------")
|
||||
.append(ENDLINE);
|
||||
output.append("Worksheet :Sheet2")
|
||||
.append(ENDLINE);
|
||||
output.append("--------------------------------------------------------------------")
|
||||
.append(ENDLINE);
|
||||
output.append("|| Name4 | Surname4 | 3.55675623232E11 | 13/04/2021 | ||")
|
||||
.append(ENDLINE);
|
||||
|
||||
fileLocation = Paths.get(ClassLoader.getSystemResource(FILE_NAME)
|
||||
.toURI())
|
||||
.toString();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenStringPath_whenReadExcel_thenReturnStringValue() throws IOException {
|
||||
assertEquals(output.toString(), ExcelUtility.readExcel(fileLocation));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenStringPath_whenReadExcel_thenThrowException() {
|
||||
assertThrows(IOException.class, () -> {
|
||||
ExcelUtility.readExcel("baeldung");
|
||||
});
|
||||
}
|
||||
=======
|
||||
private static final String FILE_NAME = "baeldung.xlsx";
|
||||
private String fileLocation;
|
||||
private static final String ENDLINE = System.getProperty("line.separator");
|
||||
private StringBuilder output;
|
||||
|
||||
@Before
|
||||
public void setupUnitTest() throws IOException, URISyntaxException, ParseException {
|
||||
output = new StringBuilder();
|
||||
output.append("--------------------------------------------------------------------").append(ENDLINE);
|
||||
output.append("Worksheet :Sheet1").append(ENDLINE);
|
||||
output.append("--------------------------------------------------------------------").append(ENDLINE);
|
||||
output.append("|| Name1 | Surname1 | 3.55696564113E11 | ").append(new SimpleDateFormat("dd/MM/yyyy").parse("4/11/2021").toString()).append(" | ‡ | ||")
|
||||
.append(ENDLINE);
|
||||
output.append("|| Name2 | Surname2 | 5.646513512E9 | ").append(new SimpleDateFormat("dd/MM/yyyy").parse("4/12/2021").toString()).append(" | false | ||")
|
||||
.append(ENDLINE);
|
||||
output.append("|| Name3 | Surname3 | 3.55696564113E11 | ").append(new SimpleDateFormat("dd/MM/yyyy").parse("4/11/2021").toString()).append(" | 7.17039641738E11 | ||")
|
||||
.append(ENDLINE);
|
||||
output.append("--------------------------------------------------------------------").append(ENDLINE);
|
||||
output.append("Worksheet :Sheet2").append(ENDLINE);
|
||||
output.append("--------------------------------------------------------------------").append(ENDLINE);
|
||||
output.append("|| Name4 | Surname4 | 3.55675623232E11 | 13/04/2021 | ||").append(ENDLINE);
|
||||
|
||||
fileLocation = Paths.get(ClassLoader.getSystemResource(FILE_NAME).toURI()).toString();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenStringPath_whenReadExcel_thenReturnStringValue() throws IOException {
|
||||
assertEquals(output.toString(), ExcelUtility.readExcel(fileLocation));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenStringPath_whenReadExcel_thenThrowException() {
|
||||
assertThrows(IOException.class, () -> {
|
||||
ExcelUtility.readExcel("baeldung");
|
||||
});
|
||||
}
|
||||
>>>>>>> master
|
||||
|
||||
}
|
|
@ -12,7 +12,7 @@ import java.nio.file.Paths;
|
|||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public class CellBorderHandlerUnitTest {
|
||||
private static final String FILE_NAME = "cellstyle/CellStyleHandlerTest.xlsx";
|
||||
private static final String FILE_NAME = "cellstyle/CellStyleBorderHandlerTest.xlsx";
|
||||
private static final int SHEET_INDEX = 0;
|
||||
|
||||
private static CellBordersHandler cellBordersHandler;
|
||||
|
|
|
@ -1,17 +1,19 @@
|
|||
package com.baeldung.poi.excel.cellstyle;
|
||||
|
||||
import org.apache.poi.ss.usermodel.*;
|
||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
import org.apache.poi.ss.usermodel.IndexedColors;
|
||||
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 org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
public class CellStyleHandlerUnitTest {
|
||||
private static final String FILE_NAME = "cellstyle/CellStyleHandlerTest.xlsx";
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
package com.baeldung.poi.excel.cellstyle;
|
||||
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
import org.apache.poi.ss.usermodel.CellStyle;
|
||||
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 org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
public class CellStylerUnitTest {
|
||||
private static String FILE_NAME = "com/baeldung/poi/excel/cellstyle/CellStyle.xlsx";
|
||||
private static final String NEW_FILE_NAME = "CellStyleTest_output.xlsx";
|
||||
private String fileLocation;
|
||||
|
||||
@Before
|
||||
public void setup() throws IOException, URISyntaxException {
|
||||
fileLocation = Paths.get(ClassLoader.getSystemResource(FILE_NAME)
|
||||
.toURI())
|
||||
.toString();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testApplyWarningColor() throws IOException {
|
||||
Workbook workbook = new XSSFWorkbook(fileLocation);
|
||||
Sheet sheet = workbook.getSheetAt(0);
|
||||
Row row1 = sheet.createRow(0);
|
||||
row1.setHeightInPoints((short) 40);
|
||||
|
||||
CellStyler styler = new CellStyler();
|
||||
CellStyle style = styler.createWarningColor(workbook);
|
||||
|
||||
Cell cell1 = row1.createCell(0);
|
||||
cell1.setCellStyle(style);
|
||||
cell1.setCellValue("Hello");
|
||||
|
||||
Cell cell2 = row1.createCell(1);
|
||||
cell2.setCellStyle(style);
|
||||
cell2.setCellValue("world!");
|
||||
|
||||
FileOutputStream outputStream = new FileOutputStream(NEW_FILE_NAME);
|
||||
workbook.write(outputStream);
|
||||
outputStream.close();
|
||||
workbook.close();
|
||||
}
|
||||
}
|
|
@ -47,7 +47,7 @@
|
|||
|
||||
<properties>
|
||||
<apache-shiro-core-version>1.5.3</apache-shiro-core-version>
|
||||
<log4j-version>1.2.17</log4j-version>
|
||||
<log4j.version>2.17.1</log4j.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
|
@ -1,9 +1,9 @@
|
|||
package com.baeldung.differences.rdd;
|
||||
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.spark.SparkConf;
|
||||
import org.apache.spark.api.java.JavaRDD;
|
||||
|
@ -12,12 +12,15 @@ import org.junit.AfterClass;
|
|||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class TransformationsUnitTest {
|
||||
|
||||
|
||||
public static final String COMMA_DELIMITER = ",(?=([^\"]*\"[^\"]*\")*[^\"]*$)";
|
||||
|
||||
private static JavaSparkContext sc;
|
||||
private static JavaRDD<String> tourists;
|
||||
|
||||
|
||||
@BeforeClass
|
||||
public static void init() {
|
||||
SparkConf conf = new SparkConf().setAppName("uppercaseCountries")
|
||||
|
@ -25,8 +28,11 @@ public class TransformationsUnitTest {
|
|||
sc = new JavaSparkContext(conf);
|
||||
tourists = sc.textFile("data/Tourist.csv")
|
||||
.filter(line -> !line.startsWith("Region")); //filter header row
|
||||
|
||||
// delete previous output dir and files
|
||||
FileUtils.deleteQuietly(new File("data/output"));
|
||||
}
|
||||
|
||||
|
||||
@AfterClass
|
||||
public static void cleanup() {
|
||||
sc.close();
|
||||
|
@ -39,9 +45,9 @@ public class TransformationsUnitTest {
|
|||
return columns[1].toUpperCase();
|
||||
})
|
||||
.distinct();
|
||||
|
||||
|
||||
upperCaseCountries.saveAsTextFile("data/output/uppercase.txt");
|
||||
|
||||
|
||||
upperCaseCountries.foreach(country -> {
|
||||
//replace non alphanumerical characters
|
||||
country = country.replaceAll("[^a-zA-Z]", "");
|
||||
|
@ -52,9 +58,9 @@ public class TransformationsUnitTest {
|
|||
@Test
|
||||
public void whenFilterByCountry_thenShowRequestedCountryRecords() {
|
||||
JavaRDD<String> touristsInMexico = tourists.filter(line -> line.split(COMMA_DELIMITER)[1].equals("Mexico"));
|
||||
|
||||
|
||||
touristsInMexico.saveAsTextFile("data/output/touristInMexico.txt");
|
||||
|
||||
|
||||
touristsInMexico.foreach(record -> {
|
||||
assertEquals("Mexico", record.split(COMMA_DELIMITER)[1]);
|
||||
});
|
||||
|
|
|
@ -4,4 +4,5 @@ This module contains articles about Java 15.
|
|||
|
||||
### Relevant articles
|
||||
|
||||
- [Hidden Classes in Java 15](https://www.baeldung.com/java-hidden-classes)
|
||||
- [Sealed Classes and Interfaces in Java 15](https://www.baeldung.com/java-sealed-classes-interfaces)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
### Relevant articles:
|
||||
|
||||
- [An Introduction to InstantSource in Java 17](https://www.baeldung.com/java-instantsource)
|
||||
- [Pattern Matching for Switch](https://www.baeldung.com/java-switch-pattern-matching)
|
||||
- [Introduction to HexFormat in Java 17](https://www.baeldung.com/java-hexformat)
|
||||
- [New Features in Java 17](https://www.baeldung.com/java-17-new-features)
|
||||
|
|
|
@ -8,4 +8,6 @@ This module contains articles about Java 8 core features
|
|||
- [Java 8 Stream skip() vs limit()](https://www.baeldung.com/java-stream-skip-vs-limit)
|
||||
- [Guide to Java BiFunction Interface](https://www.baeldung.com/java-bifunction-interface)
|
||||
- [Interface With Default Methods vs Abstract Class](https://www.baeldung.com/java-interface-default-method-vs-abstract-class)
|
||||
- [Convert Between Byte Array and UUID in Java](https://www.baeldung.com/java-byte-array-to-uuid)
|
||||
- [Create a Simple “Rock-Paper-Scissors” Game in Java](https://www.baeldung.com/java-rock-paper-scissors)
|
||||
- [[<-- Prev]](/core-java-modules/core-java-8)
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
package com.baeldung.game;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
class RockPaperScissorsGame {
|
||||
|
||||
enum Move {
|
||||
ROCK("rock"),
|
||||
PAPER("paper"),
|
||||
SCISSORS("scissors");
|
||||
|
||||
private String value;
|
||||
|
||||
Move(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
Scanner scanner = new Scanner(System.in);
|
||||
int wins = 0;
|
||||
int losses = 0;
|
||||
|
||||
System.out.println("Welcome to Rock-Paper-Scissors! Please enter \"rock\", \"paper\", \"scissors\", or \"quit\" to exit.");
|
||||
|
||||
while (true) {
|
||||
System.out.println("-------------------------");
|
||||
System.out.print("Enter your move: ");
|
||||
String playerMove = scanner.nextLine();
|
||||
|
||||
if (playerMove.equals("quit")) {
|
||||
System.out.println("You won " + wins + " times and lost " + losses + " times.");
|
||||
System.out.println("Thanks for playing! See you again.");
|
||||
break;
|
||||
}
|
||||
|
||||
if (Arrays.stream(Move.values()).noneMatch(x -> x.getValue().equals(playerMove))) {
|
||||
System.out.println("Your move isn't valid!");
|
||||
continue;
|
||||
}
|
||||
|
||||
String computerMove = getComputerMove();
|
||||
|
||||
if (playerMove.equals(computerMove)) {
|
||||
System.out.println("It's a tie!");
|
||||
} else if (isPlayerWin(playerMove, computerMove)) {
|
||||
System.out.println("You won!");
|
||||
wins++;
|
||||
} else {
|
||||
System.out.println("You lost!");
|
||||
losses++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isPlayerWin(String playerMove, String computerMove) {
|
||||
return playerMove.equals(Move.ROCK.value) && computerMove.equals(Move.SCISSORS.value)
|
||||
|| (playerMove.equals(Move.SCISSORS.value) && computerMove.equals(Move.PAPER.value))
|
||||
|| (playerMove.equals(Move.PAPER.value) && computerMove.equals(Move.ROCK.value));
|
||||
}
|
||||
|
||||
private static String getComputerMove() {
|
||||
Random random = new Random();
|
||||
int randomNumber = random.nextInt(3);
|
||||
String computerMove = Move.values()[randomNumber].getValue();
|
||||
System.out.println("Computer move: " + computerMove);
|
||||
return computerMove;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package com.baeldung.uuid;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Arrays;
|
||||
import java.util.UUID;
|
||||
|
||||
public class UuidHelper {
|
||||
|
||||
public static byte[] convertUUIDToBytes(UUID uuid) {
|
||||
ByteBuffer bb = ByteBuffer.wrap(new byte[16]);
|
||||
bb.putLong(uuid.getMostSignificantBits());
|
||||
bb.putLong(uuid.getLeastSignificantBits());
|
||||
return bb.array();
|
||||
}
|
||||
|
||||
public static UUID convertBytesToUUID(byte[] bytes) {
|
||||
ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
|
||||
long high = byteBuffer.getLong();
|
||||
long low = byteBuffer.getLong();
|
||||
return new UUID(high, low);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
UUID uuid = UUID.randomUUID();
|
||||
System.out.println("Original UUID: " + uuid);
|
||||
|
||||
byte[] bytes = convertUUIDToBytes(uuid);
|
||||
System.out.println("Converted byte array: " + Arrays.toString(bytes));
|
||||
|
||||
UUID uuidNew = convertBytesToUUID(bytes);
|
||||
System.out.println("Converted UUID: " + uuidNew);
|
||||
}
|
||||
}
|
|
@ -22,6 +22,6 @@ class RandomDatesUnitTest {
|
|||
LocalDate end = LocalDate.now();
|
||||
|
||||
LocalDate random = RandomDates.between(start, end);
|
||||
assertThat(random).isAfter(start).isBefore(end);
|
||||
assertThat(random).isAfterOrEqualTo(start).isBefore(end);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,6 +34,28 @@
|
|||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<finalName>core-java-9-new-features</finalName>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>${maven-compiler-plugin.version}</version>
|
||||
<configuration>
|
||||
<source>${maven.compiler.source}</source>
|
||||
<target>${maven.compiler.target}</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<pluginRepositories>
|
||||
<pluginRepository>
|
||||
<id>apache.snapshots</id>
|
||||
<url>https://repository.apache.org/snapshots/</url>
|
||||
</pluginRepository>
|
||||
</pluginRepositories>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>incubator-features</id>
|
||||
|
@ -126,28 +148,6 @@
|
|||
</profile>
|
||||
</profiles>
|
||||
|
||||
<build>
|
||||
<finalName>core-java-9-new-features</finalName>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>${maven-compiler-plugin.version}</version>
|
||||
<configuration>
|
||||
<source>${maven.compiler.source}</source>
|
||||
<target>${maven.compiler.target}</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<pluginRepositories>
|
||||
<pluginRepository>
|
||||
<id>apache.snapshots</id>
|
||||
<url>https://repository.apache.org/snapshots/</url>
|
||||
</pluginRepository>
|
||||
</pluginRepositories>
|
||||
|
||||
<properties>
|
||||
<rxjava.version>3.0.0</rxjava.version>
|
||||
<awaitility.version>4.0.2</awaitility.version>
|
||||
|
|
|
@ -1,17 +1,16 @@
|
|||
package com.baeldung.collections.iterators;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* Source code https://github.com/eugenp/tutorials
|
||||
*
|
||||
* @author Santosh Thakur
|
||||
*/
|
||||
|
||||
public class Iterators {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(Iterators.class);
|
||||
|
||||
public static int failFast1() {
|
||||
ArrayList<Integer> numbers = new ArrayList<>();
|
||||
|
||||
|
@ -44,7 +43,7 @@ public class Iterators {
|
|||
}
|
||||
}
|
||||
|
||||
System.out.println("using iterator's remove method = " + numbers);
|
||||
LOG.debug("using iterator's remove method = {}", numbers);
|
||||
|
||||
iterator = numbers.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
|
|
|
@ -3,6 +3,8 @@ package com.baeldung.collections.bitset;
|
|||
import org.junit.Test;
|
||||
import org.openjdk.jol.info.ClassLayout;
|
||||
import org.openjdk.jol.info.GraphLayout;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.BitSet;
|
||||
|
||||
|
@ -10,18 +12,20 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||
|
||||
public class BitSetUnitTest {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(BitSetUnitTest.class);
|
||||
|
||||
@Test
|
||||
public void givenBoolArray_whenMemoryLayout_thenConsumeMoreThanOneBit() {
|
||||
boolean[] bits = new boolean[1024 * 1024];
|
||||
|
||||
System.out.println(ClassLayout.parseInstance(bits).toPrintable());
|
||||
LOG.debug(ClassLayout.parseInstance(bits).toPrintable());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenBitSet_whenMemoryLayout_thenConsumeOneBitPerFlag() {
|
||||
BitSet bitSet = new BitSet(1024 * 1024);
|
||||
|
||||
System.out.println(GraphLayout.parseInstance(bitSet).toPrintable());
|
||||
LOG.debug(GraphLayout.parseInstance(bitSet).toPrintable());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -157,7 +161,7 @@ public class BitSetUnitTest {
|
|||
BitSet bitSet = new BitSet();
|
||||
bitSet.set(15, 25);
|
||||
|
||||
bitSet.stream().forEach(System.out::println);
|
||||
bitSet.stream().forEach(bit -> LOG.debug(String.valueOf(bit)));
|
||||
assertThat(bitSet.stream().count()).isEqualTo(10);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
|
||||
</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<root level="INFO">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</root>
|
||||
</configuration>
|
|
@ -7,3 +7,4 @@
|
|||
- [ArrayList vs. LinkedList vs. HashMap in Java](https://www.baeldung.com/java-arraylist-vs-linkedlist-vs-hashmap)
|
||||
- [Java Deque vs. Stack](https://www.baeldung.com/java-deque-vs-stack)
|
||||
- [Collection.toArray(new T[0]) or .toArray(new T[size])](https://www.baeldung.com/java-collection-toarray-methods)
|
||||
- [Create an Empty Map in Java](https://www.baeldung.com/java-create-empty-map)
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
package com.baeldung.maps.initialize;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Maps;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.NavigableMap;
|
||||
import java.util.SortedMap;
|
||||
import java.util.TreeMap;
|
||||
|
||||
public class EmptyMapInitializer {
|
||||
|
||||
public static Map<String, String> articleMap;
|
||||
static {
|
||||
articleMap = new HashMap<>();
|
||||
}
|
||||
|
||||
public static Map<String, String> createEmptyMap() {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
public void createMapUsingConstructors() {
|
||||
Map hashMap = new HashMap();
|
||||
Map linkedHashMap = new LinkedHashMap();
|
||||
Map treeMap = new TreeMap();
|
||||
}
|
||||
|
||||
public Map<String, String> createEmptyMapUsingMapsObject() {
|
||||
Map<String, String> emptyMap = Maps.newHashMap();
|
||||
return emptyMap;
|
||||
}
|
||||
|
||||
public Map createGenericEmptyMapUsingMapsObject() {
|
||||
Map genericEmptyMap = Maps.<String, Integer>newHashMap();
|
||||
return genericEmptyMap;
|
||||
}
|
||||
|
||||
public static Map<String, String> createMapUsingGuava() {
|
||||
Map<String, String> emptyMapUsingGuava =
|
||||
Maps.newHashMap(ImmutableMap.of());
|
||||
return emptyMapUsingGuava;
|
||||
}
|
||||
|
||||
public SortedMap<String, String> createEmptySortedMap() {
|
||||
SortedMap<String, String> sortedMap = Collections.emptySortedMap();
|
||||
return sortedMap;
|
||||
}
|
||||
|
||||
public NavigableMap<String, String> createEmptyNavigableMap() {
|
||||
NavigableMap<String, String> navigableMap = Collections.emptyNavigableMap();
|
||||
return navigableMap;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
package com.baeldung.maps.initialize;
|
||||
|
||||
import java.util.Map;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
public class EmptyMapInitializerUnitTest {
|
||||
|
||||
@Test(expected=UnsupportedOperationException.class)
|
||||
public void givenEmptyMap_whenAddingEntries_throwsException() {
|
||||
Map<String, String> map = EmptyMapInitializer.createEmptyMap();
|
||||
map.put("key", "value");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenEmptyMap_whenChecked_returnsTrue() {
|
||||
assertTrue(EmptyMapInitializer.articleMap.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenEmptyMap_whenCreatedUsingGuava_returnsEmptyOrNot() {
|
||||
Map<String, String> emptyMapUsingGuava =
|
||||
EmptyMapInitializer.createMapUsingGuava();
|
||||
assertTrue(emptyMapUsingGuava.isEmpty());
|
||||
emptyMapUsingGuava.put("key", "value");
|
||||
assertFalse(emptyMapUsingGuava.isEmpty());
|
||||
}
|
||||
|
||||
}
|
|
@ -6,3 +6,5 @@ This module contains articles about Map data structures in Java.
|
|||
- [Using a Custom Class as a Key in a Java HashMap](https://www.baeldung.com/java-custom-class-map-key)
|
||||
- [Nested HashMaps Examples in Java](https://www.baeldung.com/java-nested-hashmaps)
|
||||
- [Java HashMap With Different Value Types](https://www.baeldung.com/java-hashmap-different-value-types)
|
||||
- [Difference Between Map and HashMap in Java](https://www.baeldung.com/java-map-vs-hashmap)
|
||||
- [How to Create a New Entry in a Map](https://www.baeldung.com/java-map-new-entry)
|
||||
|
|
|
@ -15,6 +15,16 @@
|
|||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-collections4</artifactId>
|
||||
<version>${commons-collections4.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>${guava.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
|
@ -37,12 +47,23 @@
|
|||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>${maven-compiler-plugin.version}</version>
|
||||
<configuration>
|
||||
<source>${maven.compiler.source}</source>
|
||||
<target>${maven.compiler.target}</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<maven.compiler.source>1.8</maven.compiler.source>
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
<maven.compiler.source>1.9</maven.compiler.source>
|
||||
<maven.compiler.target>1.9</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,53 @@
|
|||
package com.baeldung.entries;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.StringJoiner;
|
||||
|
||||
public class SimpleCustomKeyValue<K, V> implements Map.Entry<K, V> {
|
||||
|
||||
private final K key;
|
||||
private V value;
|
||||
|
||||
public SimpleCustomKeyValue(K key, V value) {
|
||||
this.key = key;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public K getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
@Override
|
||||
public V getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public V setValue(V value) {
|
||||
return this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
SimpleCustomKeyValue<?, ?> that = (SimpleCustomKeyValue<?, ?>) o;
|
||||
return Objects.equals(key, that.key) && Objects.equals(value, that.value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new StringJoiner(", ", SimpleCustomKeyValue.class.getSimpleName() + "[", "]").add("key=" + key).add("value=" + value).toString();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package com.baeldung.mapandhashmap;
|
||||
|
||||
import com.baeldung.mapandhashmap.printer.HashMapPrinter;
|
||||
import com.baeldung.mapandhashmap.printer.MapPrinter;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
Map<String, String> map = new HashMap<>();
|
||||
HashMap<String, String> hashMap = new HashMap<>();
|
||||
TreeMap<String, String> treeMap = new TreeMap<>();
|
||||
|
||||
HashMapPrinter hashMapPrinter = new HashMapPrinter();
|
||||
hashMapPrinter.printMap(hashMap);
|
||||
// hashMapPrinter.printMap(treeMap); Compile time error
|
||||
// hashMapPrinter.printMap(map); Compile time error
|
||||
|
||||
MapPrinter mapPrinter = new MapPrinter();
|
||||
mapPrinter.printMap(hashMap);
|
||||
mapPrinter.printMap(treeMap);
|
||||
mapPrinter.printMap(map);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package com.baeldung.mapandhashmap.printer;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
public class HashMapPrinter {
|
||||
|
||||
public void printMap(final HashMap<?, ?> map) {
|
||||
for (final Entry<?, ?> entry : map.entrySet()) {
|
||||
System.out.println(entry.getKey() + " " + entry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package com.baeldung.mapandhashmap.printer;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
public class MapPrinter {
|
||||
|
||||
public void printMap(final Map<?, ?> map) {
|
||||
for (final Entry<?, ?> entry : map.entrySet()) {
|
||||
System.out.println(entry.getKey() + " " + entry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package com.baeldung.mapandhashmap.printer;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
public class MapReporter {
|
||||
|
||||
private final Map<?, ?> map;
|
||||
|
||||
public MapReporter(final Map<?, ?> map) {
|
||||
this.map = map;
|
||||
}
|
||||
|
||||
public void printMap() {
|
||||
for (final Entry<?, ?> entry : this.map.entrySet()) {
|
||||
System.out.println(entry.getKey() + " " + entry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,113 @@
|
|||
package com.baeldung.entries;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import org.apache.commons.collections4.KeyValue;
|
||||
import org.apache.commons.collections4.keyvalue.DefaultMapEntry;
|
||||
import org.apache.commons.collections4.keyvalue.UnmodifiableMapEntry;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.AbstractMap;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.tuple;
|
||||
|
||||
public class EntriesExampleUnitTest {
|
||||
|
||||
@Test
|
||||
public void givenEntries_whenVerifying_thenShouldContainKeyValues() {
|
||||
AbstractMap.SimpleEntry<String, String> firstEntry = new AbstractMap.SimpleEntry<>("key1", "value1");
|
||||
AbstractMap.SimpleEntry<String, String> secondEntry = new AbstractMap.SimpleEntry<>("key2", "value2");
|
||||
AbstractMap.SimpleEntry<String, String> thirdEntry = new AbstractMap.SimpleEntry<>(firstEntry);
|
||||
thirdEntry.setValue("a different value");
|
||||
|
||||
assertThat(Stream.of(firstEntry, secondEntry, thirdEntry))
|
||||
.extracting("key", "value")
|
||||
.containsExactly(
|
||||
tuple("key1", "value1"),
|
||||
tuple("key2", "value2"),
|
||||
tuple("key1", "a different value"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenImmutableEntries_whenVerifying_thenShouldContainKeyValues() {
|
||||
AbstractMap.SimpleImmutableEntry<String, String> firstEntry = new AbstractMap.SimpleImmutableEntry<>("key1", "value1");
|
||||
AbstractMap.SimpleImmutableEntry<String, String> secondEntry = new AbstractMap.SimpleImmutableEntry<>("key2", "value2");
|
||||
AbstractMap.SimpleImmutableEntry<String, String> thirdEntry = new AbstractMap.SimpleImmutableEntry<>(firstEntry);
|
||||
|
||||
assertThat(Stream.of(firstEntry, secondEntry, thirdEntry))
|
||||
.extracting("key", "value")
|
||||
.containsExactly(
|
||||
tuple("key1", "value1"),
|
||||
tuple("key2", "value2"),
|
||||
tuple("key1", "value1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenImmutableEntryUsingJava9_whenVerifying_thenShouldContainKeyValues() {
|
||||
Map.Entry<String, String> entry = Map.entry("key", "value");
|
||||
|
||||
assertThat(entry.getKey())
|
||||
.isEqualTo("key");
|
||||
assertThat(entry.getValue())
|
||||
.isEqualTo("value");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void givenEntriesWithApacheCommons_whenVerifying_thenShouldContainKeyValues() {
|
||||
Map.Entry<String, String> firstEntry = new DefaultMapEntry<>("key1", "value1");
|
||||
KeyValue<String, String> secondEntry = new DefaultMapEntry<>("key2", "value2");
|
||||
|
||||
KeyValue<String, String> thirdEntry = new DefaultMapEntry<>(firstEntry);
|
||||
KeyValue<String, String> fourthEntry = new DefaultMapEntry<>(secondEntry);
|
||||
|
||||
firstEntry.setValue("a different value");
|
||||
|
||||
assertThat(firstEntry)
|
||||
.extracting("key", "value")
|
||||
.containsExactly("key1", "a different value");
|
||||
|
||||
assertThat(Stream.of(secondEntry, thirdEntry, fourthEntry))
|
||||
.extracting("key", "value")
|
||||
.containsExactly(
|
||||
tuple("key2", "value2"),
|
||||
tuple("key1", "value1"),
|
||||
tuple("key2", "value2"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenImmutableEntriesWithApacheCommons_whenVerifying_thenShouldContainKeyValues() {
|
||||
Map.Entry<String, String> firstEntry = new UnmodifiableMapEntry<>("key1", "value1");
|
||||
KeyValue<String, String> secondEntry = new UnmodifiableMapEntry<>("key2", "value2");
|
||||
|
||||
KeyValue<String, String> thirdEntry = new UnmodifiableMapEntry<>(firstEntry);
|
||||
KeyValue<String, String> fourthEntry = new UnmodifiableMapEntry<>(secondEntry);
|
||||
|
||||
assertThat(firstEntry)
|
||||
.extracting("key", "value")
|
||||
.containsExactly("key1", "value1");
|
||||
|
||||
assertThat(Stream.of(secondEntry, thirdEntry, fourthEntry))
|
||||
.extracting("key", "value")
|
||||
.containsExactly(
|
||||
tuple("key2", "value2"),
|
||||
tuple("key1", "value1"),
|
||||
tuple("key2", "value2"));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void givenImmutableEntriesWithGuava_whenVerifying_thenShouldContainKeyValues() {
|
||||
Map.Entry<String, String> firstEntry = Maps.immutableEntry("key1", "value1");
|
||||
Map.Entry<String, String> secondEntry = Maps.immutableEntry("key2", "value2");
|
||||
|
||||
assertThat(Stream.of(firstEntry, secondEntry))
|
||||
.extracting("key", "value")
|
||||
.containsExactly(
|
||||
tuple("key1", "value1"),
|
||||
tuple("key2", "value2"));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
package com.baeldung.entries;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.tuple;
|
||||
|
||||
class SimpleCustomKeyValueUnitTest {
|
||||
|
||||
|
||||
@Test
|
||||
public void givenModifiableEntries_whenVerifying_thenShouldContainKeyValues() {
|
||||
Map.Entry<String, String> firstEntry = new SimpleCustomKeyValue<>("key1", "value1");
|
||||
|
||||
Map.Entry<String, String> secondEntry = new SimpleCustomKeyValue<>("key2", "value2");
|
||||
secondEntry.setValue("different value");
|
||||
|
||||
Map<String, String> map = Map.ofEntries(firstEntry, secondEntry);
|
||||
|
||||
assertThat(map)
|
||||
.isEqualTo(ImmutableMap.<String,String>builder()
|
||||
.put("key1", "value1")
|
||||
.put("key2", "different value")
|
||||
.build());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
package com.baeldung.mapandhashmap.printer;
|
||||
|
||||
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class HashMapPrinterUnitTest {
|
||||
|
||||
private final HashMapPrinter mapPrinter = new HashMapPrinter();
|
||||
private final ByteArrayOutputStream outputStreamCaptor = new ByteArrayOutputStream();
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
System.setOut(new PrintStream(outputStreamCaptor));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test hash map printer with HashMap")
|
||||
void testPrintHashMap() {
|
||||
// given
|
||||
String key = "HashMap";
|
||||
String value = "Main default implementation for the Map interface";
|
||||
String expected = key + " " + value;
|
||||
HashMap<String, String> map = new HashMap<>();
|
||||
map.put(key, value);
|
||||
// when
|
||||
mapPrinter.printMap(map);
|
||||
// then
|
||||
String actual = outputStreamCaptor.toString().trim();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test hash map printer with LinkedHash")
|
||||
void testPrintLinkedHashMap() {
|
||||
// given
|
||||
String key = "LinkedHashMap";
|
||||
String value = "Use this implementation if you need keep the order of elements";
|
||||
String expected = key + " " + value;
|
||||
LinkedHashMap<String, String> map = new LinkedHashMap<>();
|
||||
map.put(key, value);
|
||||
// when
|
||||
mapPrinter.printMap(map);
|
||||
// then
|
||||
String actual = outputStreamCaptor.toString().trim();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
package com.baeldung.mapandhashmap.printer;
|
||||
|
||||
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.TreeMap;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class MapPrinterUnitTest {
|
||||
|
||||
private final MapPrinter mapPrinter = new MapPrinter();
|
||||
private final ByteArrayOutputStream outputStreamCaptor = new ByteArrayOutputStream();
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
System.setOut(new PrintStream(outputStreamCaptor));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test printer with TreeMap")
|
||||
void testPrintTreeMap() {
|
||||
// given
|
||||
String key = "TreeMap";
|
||||
String value = "Used when sorting is needed";
|
||||
String expected = key + " " + value;
|
||||
TreeMap<String, String> map = new TreeMap<>();
|
||||
map.put(key, value);
|
||||
// when
|
||||
mapPrinter.printMap(map);
|
||||
// then
|
||||
String actual = outputStreamCaptor.toString().trim();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test printer with HashMap")
|
||||
void testPrintHashMap() {
|
||||
// given
|
||||
String key = "HashMap";
|
||||
String value = "Main default implementation for the Map interface";
|
||||
String expected = key + " " + value;
|
||||
HashMap<String, String> map = new HashMap<>();
|
||||
map.put(key, value);
|
||||
// when
|
||||
mapPrinter.printMap(map);
|
||||
// then
|
||||
String actual = outputStreamCaptor.toString().trim();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test printer with LinkedHash")
|
||||
void testPrintLinkedHashMap() {
|
||||
// given
|
||||
String key = "LinkedHashMap";
|
||||
String value = "Use this implementation if you need keep the order of elements";
|
||||
String expected = key + " " + value;
|
||||
LinkedHashMap<String, String> map = new LinkedHashMap<>();
|
||||
map.put(key, value);
|
||||
// when
|
||||
mapPrinter.printMap(map);
|
||||
// then
|
||||
String actual = outputStreamCaptor.toString().trim();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
package com.baeldung.mapandhashmap.printer;
|
||||
|
||||
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.TreeMap;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class MapReporterUnitTest {
|
||||
|
||||
private final ByteArrayOutputStream outputStreamCaptor = new ByteArrayOutputStream();
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
System.setOut(new PrintStream(outputStreamCaptor));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test reporter with TreeMap")
|
||||
void testPrintTreeMap() {
|
||||
// given
|
||||
String key = "TreeMap";
|
||||
String value = "Used when sorting is needed";
|
||||
String expected = key + " " + value;
|
||||
TreeMap<String, String> map = new TreeMap<>();
|
||||
map.put(key, value);
|
||||
// when
|
||||
MapReporter mapReporter = new MapReporter(map);
|
||||
mapReporter.printMap();
|
||||
// then
|
||||
String actual = outputStreamCaptor.toString().trim();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test reporter with HashMap")
|
||||
void testPrintHashMap() {
|
||||
// given
|
||||
String key = "HashMap";
|
||||
String value = "Main default implementation for the Map interface";
|
||||
String expected = key + " " + value;
|
||||
HashMap<String, String> map = new HashMap<>();
|
||||
map.put(key, value);
|
||||
// when
|
||||
MapReporter mapReporter = new MapReporter(map);
|
||||
mapReporter.printMap();
|
||||
// then
|
||||
String actual = outputStreamCaptor.toString().trim();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test reporter with LinkedHash")
|
||||
void testPrintLinkedHashMap() {
|
||||
// given
|
||||
String key = "LinkedHashMap";
|
||||
String value = "Use this implementation if you need keep the order of elements";
|
||||
String expected = key + " " + value;
|
||||
LinkedHashMap<String, String> map = new LinkedHashMap<>();
|
||||
map.put(key, value);
|
||||
// when
|
||||
MapReporter mapReporter = new MapReporter(map);
|
||||
mapReporter.printMap();
|
||||
// then
|
||||
String actual = outputStreamCaptor.toString().trim();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,9 +1,15 @@
|
|||
package com.baeldung.concurrent.prioritytaskexecution;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class Job implements Runnable {
|
||||
private String jobName;
|
||||
private JobPriority jobPriority;
|
||||
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(Job.class);
|
||||
|
||||
private final String jobName;
|
||||
private final JobPriority jobPriority;
|
||||
|
||||
public Job(String jobName, JobPriority jobPriority) {
|
||||
this.jobName = jobName;
|
||||
this.jobPriority = jobPriority != null ? jobPriority : JobPriority.MEDIUM;
|
||||
|
@ -16,8 +22,7 @@ public class Job implements Runnable {
|
|||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
System.out.println("Job:" + jobName +
|
||||
" Priority:" + jobPriority);
|
||||
LOGGER.debug("Job:{} Priority:{}", jobName, jobPriority);
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException ignored) {
|
||||
}
|
||||
|
|
|
@ -1,19 +1,21 @@
|
|||
package com.baeldung.forkjoin;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ForkJoinTask;
|
||||
import java.util.concurrent.RecursiveAction;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class CustomRecursiveAction extends RecursiveAction {
|
||||
|
||||
final Logger logger = LoggerFactory.getLogger(CustomRecursiveAction.class);
|
||||
|
||||
private String workLoad = "";
|
||||
private static final int THRESHOLD = 4;
|
||||
|
||||
private static Logger logger = Logger.getAnonymousLogger();
|
||||
|
||||
public CustomRecursiveAction(String workLoad) {
|
||||
this.workLoad = workLoad;
|
||||
}
|
||||
|
@ -43,7 +45,7 @@ public class CustomRecursiveAction extends RecursiveAction {
|
|||
|
||||
private void processing(String work) {
|
||||
String result = work.toUpperCase();
|
||||
logger.info("This result - (" + result + ") - was processed by " + Thread.currentThread()
|
||||
logger.debug("This result - (" + result + ") - was processed by " + Thread.currentThread()
|
||||
.getName());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,9 +3,9 @@ package com.baeldung.concurrent.prioritytaskexecution;
|
|||
import org.junit.Test;
|
||||
|
||||
public class PriorityJobSchedulerUnitTest {
|
||||
private static int POOL_SIZE = 1;
|
||||
private static int QUEUE_SIZE = 10;
|
||||
|
||||
private static final int POOL_SIZE = 1;
|
||||
private static final int QUEUE_SIZE = 10;
|
||||
|
||||
@Test
|
||||
public void whenMultiplePriorityJobsQueued_thenHighestPriorityJobIsPicked() {
|
||||
Job job1 = new Job("Job1", JobPriority.LOW);
|
||||
|
@ -14,19 +14,19 @@ public class PriorityJobSchedulerUnitTest {
|
|||
Job job4 = new Job("Job4", JobPriority.MEDIUM);
|
||||
Job job5 = new Job("Job5", JobPriority.LOW);
|
||||
Job job6 = new Job("Job6", JobPriority.HIGH);
|
||||
|
||||
|
||||
PriorityJobScheduler pjs = new PriorityJobScheduler(POOL_SIZE, QUEUE_SIZE);
|
||||
|
||||
|
||||
pjs.scheduleJob(job1);
|
||||
pjs.scheduleJob(job2);
|
||||
pjs.scheduleJob(job3);
|
||||
pjs.scheduleJob(job4);
|
||||
pjs.scheduleJob(job5);
|
||||
pjs.scheduleJob(job6);
|
||||
|
||||
|
||||
// ensure no tasks is pending before closing the scheduler
|
||||
while (pjs.getQueuedTaskCount() != 0);
|
||||
|
||||
|
||||
// delay to avoid job sleep (added for demo) being interrupted
|
||||
try {
|
||||
Thread.sleep(2000);
|
||||
|
@ -34,7 +34,7 @@ public class PriorityJobSchedulerUnitTest {
|
|||
Thread.currentThread().interrupt();
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
|
||||
pjs.closeScheduler();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,18 +1,15 @@
|
|||
package com.baeldung.forkjoin;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import com.baeldung.forkjoin.util.PoolUtil;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.ForkJoinPool;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.baeldung.forkjoin.CustomRecursiveAction;
|
||||
import com.baeldung.forkjoin.CustomRecursiveTask;
|
||||
import com.baeldung.forkjoin.util.PoolUtil;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class Java8ForkJoinIntegrationTest {
|
||||
|
||||
|
@ -63,11 +60,11 @@ public class Java8ForkJoinIntegrationTest {
|
|||
ForkJoinPool forkJoinPool = ForkJoinPool.commonPool();
|
||||
|
||||
forkJoinPool.execute(customRecursiveTask);
|
||||
int result = customRecursiveTask.join();
|
||||
customRecursiveTask.join();
|
||||
assertTrue(customRecursiveTask.isDone());
|
||||
|
||||
forkJoinPool.submit(customRecursiveTask);
|
||||
int resultTwo = customRecursiveTask.join();
|
||||
customRecursiveTask.join();
|
||||
assertTrue(customRecursiveTask.isDone());
|
||||
}
|
||||
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
package com.baeldung.thread.join;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* Demonstrates Thread.join behavior.
|
||||
|
@ -14,55 +14,55 @@ import org.junit.Test;
|
|||
*/
|
||||
public class ThreadJoinUnitTest {
|
||||
|
||||
final static Logger LOGGER = Logger.getLogger(ThreadJoinUnitTest.class.getName());
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(ThreadJoinUnitTest.class);
|
||||
|
||||
class SampleThread extends Thread {
|
||||
public int processingCount = 0;
|
||||
static class SampleThread extends Thread {
|
||||
public int processingCount;
|
||||
|
||||
SampleThread(int processingCount) {
|
||||
this.processingCount = processingCount;
|
||||
LOGGER.info("Thread " + this.getName() + " created");
|
||||
LOGGER.debug("Thread " + this.getName() + " created");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
LOGGER.info("Thread " + this.getName() + " started");
|
||||
LOGGER.debug("Thread " + this.getName() + " started");
|
||||
while (processingCount > 0) {
|
||||
try {
|
||||
Thread.sleep(1000); // Simulate some work being done by thread
|
||||
} catch (InterruptedException e) {
|
||||
LOGGER.info("Thread " + this.getName() + " interrupted.");
|
||||
LOGGER.debug("Thread " + this.getName() + " interrupted.");
|
||||
}
|
||||
processingCount--;
|
||||
LOGGER.info("Inside Thread " + this.getName() + ", processingCount = " + processingCount);
|
||||
LOGGER.debug("Inside Thread " + this.getName() + ", processingCount = " + processingCount);
|
||||
}
|
||||
LOGGER.info("Thread " + this.getName() + " exiting");
|
||||
LOGGER.debug("Thread " + this.getName() + " exiting");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenNewThread_whenJoinCalled_returnsImmediately() throws InterruptedException {
|
||||
Thread t1 = new SampleThread(0);
|
||||
LOGGER.info("Invoking join.");
|
||||
LOGGER.debug("Invoking join.");
|
||||
t1.join();
|
||||
LOGGER.info("Returned from join");
|
||||
LOGGER.info("Thread state is" + t1.getState());
|
||||
LOGGER.debug("Returned from join");
|
||||
LOGGER.debug("Thread state is" + t1.getState());
|
||||
assertFalse(t1.isAlive());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenStartedThread_whenJoinCalled_waitsTillCompletion()
|
||||
public void givenStartedThread_whenJoinCalled_waitsTillCompletion()
|
||||
throws InterruptedException {
|
||||
Thread t2 = new SampleThread(1);
|
||||
t2.start();
|
||||
LOGGER.info("Invoking join.");
|
||||
LOGGER.debug("Invoking join.");
|
||||
t2.join();
|
||||
LOGGER.info("Returned from join");
|
||||
LOGGER.debug("Returned from join");
|
||||
assertFalse(t2.isAlive());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenStartedThread_whenTimedJoinCalled_waitsUntilTimedout()
|
||||
public void givenStartedThread_whenTimedJoinCalled_waitsUntilTimedout()
|
||||
throws InterruptedException {
|
||||
Thread t3 = new SampleThread(10);
|
||||
t3.start();
|
||||
|
@ -72,18 +72,18 @@ public class ThreadJoinUnitTest {
|
|||
|
||||
@Test
|
||||
@Ignore
|
||||
public void givenThreadTerminated_checkForEffect_notGuaranteed()
|
||||
public void givenThreadTerminated_checkForEffect_notGuaranteed()
|
||||
throws InterruptedException {
|
||||
SampleThread t4 = new SampleThread(10);
|
||||
t4.start();
|
||||
//not guaranteed to stop even if t4 finishes.
|
||||
do {
|
||||
|
||||
} while (t4.processingCount > 0);
|
||||
|
||||
} while (t4.processingCount > 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenJoinWithTerminatedThread_checkForEffect_guaranteed()
|
||||
public void givenJoinWithTerminatedThread_checkForEffect_guaranteed()
|
||||
throws InterruptedException {
|
||||
SampleThread t4 = new SampleThread(10);
|
||||
t4.start();
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
|
||||
</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<root level="INFO">
|
||||
<appender-ref ref="STDOUT"/>
|
||||
</root>
|
||||
</configuration>
|
|
@ -1,25 +1,22 @@
|
|||
package com.baeldung.atomicstampedreference;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicStampedReference;
|
||||
|
||||
public class StampedAccount {
|
||||
|
||||
private AtomicInteger stamp = new AtomicInteger(0);
|
||||
private AtomicStampedReference<Integer> account = new AtomicStampedReference<>(0, 0);
|
||||
|
||||
public int getBalance() {
|
||||
return account.getReference();
|
||||
}
|
||||
|
||||
public int getStamp() {
|
||||
return account.getStamp();
|
||||
}
|
||||
private final AtomicInteger stamp = new AtomicInteger(0);
|
||||
private final AtomicStampedReference<Integer> account = new AtomicStampedReference<>(0, 0);
|
||||
|
||||
public boolean deposit(int funds) {
|
||||
int[] stamps = new int[1];
|
||||
int current = this.account.get(stamps);
|
||||
int newStamp = this.stamp.incrementAndGet();
|
||||
|
||||
// Thread is paused here to allow other threads to update the stamp and amount (for testing only)
|
||||
sleep();
|
||||
|
||||
return this.account.compareAndSet(current, current + funds, stamps[0], newStamp);
|
||||
}
|
||||
|
||||
|
@ -29,4 +26,19 @@ public class StampedAccount {
|
|||
int newStamp = this.stamp.incrementAndGet();
|
||||
return this.account.compareAndSet(current, current - funds, stamps[0], newStamp);
|
||||
}
|
||||
|
||||
public int getBalance() {
|
||||
return account.getReference();
|
||||
}
|
||||
|
||||
public int getStamp() {
|
||||
return account.getStamp();
|
||||
}
|
||||
|
||||
private static void sleep() {
|
||||
try {
|
||||
TimeUnit.SECONDS.sleep(1);
|
||||
} catch (InterruptedException ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,21 +1,38 @@
|
|||
package com.baeldung.atomicstampedreference;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class ThreadStampedAccountUnitTest {
|
||||
|
||||
@Test
|
||||
public void givenMultiThread_whenStampedAccount_thenSetBalance() throws InterruptedException {
|
||||
StampedAccount account = new StampedAccount();
|
||||
|
||||
Thread t = new Thread(() -> {
|
||||
while (!account.withdrawal(100))
|
||||
while (!account.deposit(100)) {
|
||||
Thread.yield();
|
||||
}
|
||||
});
|
||||
t.start();
|
||||
Assert.assertTrue(account.deposit(100));
|
||||
t.join(1_000);
|
||||
Assert.assertFalse(t.isAlive());
|
||||
Assert.assertSame(0, account.getBalance());
|
||||
|
||||
Thread t2 = new Thread(() -> {
|
||||
while (!account.withdrawal(100)) {
|
||||
Thread.yield();
|
||||
}
|
||||
});
|
||||
t2.start();
|
||||
|
||||
t.join(10_000);
|
||||
t2.join(10_000);
|
||||
|
||||
assertFalse(t.isAlive());
|
||||
assertFalse(t2.isAlive());
|
||||
|
||||
assertEquals(0, account.getBalance());
|
||||
assertTrue(account.getStamp() > 0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,3 +4,4 @@
|
|||
- [Bad Practices With Synchronization](https://www.baeldung.com/java-synchronization-bad-practices)
|
||||
- [Start Two Threads at the Exact Same Time in Java](https://www.baeldung.com/java-start-two-threads-at-same-time)
|
||||
- [Volatile Variables and Thread Safety](https://www.baeldung.com/java-volatile-variables-thread-safety)
|
||||
- [Producer-Consumer Problem With Example in Java](https://www.baeldung.com/java-producer-consumer-problem)
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
package com.baeldung.lockbykey;
|
||||
|
||||
/**
|
||||
* This class shows examples of how you should use the lock
|
||||
*
|
||||
*/
|
||||
public class ExampleUsage {
|
||||
|
||||
void doWithSimpleExclusiveLock(String key) {
|
||||
SimpleExclusiveLockByKey simpleExclusiveLockByKey = new SimpleExclusiveLockByKey();
|
||||
if (simpleExclusiveLockByKey.tryLock(key)) {
|
||||
try {
|
||||
// do stuff
|
||||
} finally {
|
||||
// it is very important to unlock in the finally block to avoid locking keys forever
|
||||
simpleExclusiveLockByKey.unlock(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// A concrete example can be found in the unit tests
|
||||
void doWithLock(String key) {
|
||||
LockByKey lockByKey = new LockByKey();
|
||||
lockByKey.lock(key);
|
||||
try {
|
||||
// do stuff
|
||||
} finally {
|
||||
lockByKey.unlock(key);
|
||||
}
|
||||
}
|
||||
|
||||
// It works exactly the same as with locks
|
||||
void doWithSemaphore(String key) {
|
||||
SimultaneousEntriesLockByKey lockByKey = new SimultaneousEntriesLockByKey();
|
||||
lockByKey.lock(key);
|
||||
try {
|
||||
// do stuff
|
||||
} finally {
|
||||
lockByKey.unlock(key);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
package com.baeldung.lockbykey;
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
public class LockByKey {
|
||||
|
||||
private static class LockWrapper {
|
||||
private final Lock lock = new ReentrantLock();
|
||||
private final AtomicInteger numberOfThreadsInQueue = new AtomicInteger(1);
|
||||
|
||||
private LockWrapper addThreadInQueue() {
|
||||
numberOfThreadsInQueue.incrementAndGet();
|
||||
return this;
|
||||
}
|
||||
|
||||
private int removeThreadFromQueue() {
|
||||
return numberOfThreadsInQueue.decrementAndGet();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static ConcurrentHashMap<String, LockWrapper> locks = new ConcurrentHashMap<String, LockWrapper>();
|
||||
|
||||
public void lock(String key) {
|
||||
LockWrapper lockWrapper = locks.compute(key, (k, v) -> v == null ? new LockWrapper() : v.addThreadInQueue());
|
||||
lockWrapper.lock.lock();
|
||||
}
|
||||
|
||||
public void unlock(String key) {
|
||||
LockWrapper lockWrapper = locks.get(key);
|
||||
lockWrapper.lock.unlock();
|
||||
if (lockWrapper.removeThreadFromQueue() == 0) {
|
||||
// NB : We pass in the specific value to remove to handle the case where another thread would queue right before the removal
|
||||
locks.remove(key, lockWrapper);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
package com.baeldung.lockbykey;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class SimpleExclusiveLockByKey {
|
||||
|
||||
private static Set<String> usedKeys= ConcurrentHashMap.newKeySet();
|
||||
|
||||
public boolean tryLock(String key) {
|
||||
return usedKeys.add(key);
|
||||
}
|
||||
|
||||
public void unlock(String key) {
|
||||
usedKeys.remove(key);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package com.baeldung.lockbykey;
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.Semaphore;
|
||||
|
||||
public class SimultaneousEntriesLockByKey {
|
||||
|
||||
private static final int ALLOWED_THREADS = 2;
|
||||
|
||||
private static ConcurrentHashMap<String, Semaphore> semaphores = new ConcurrentHashMap<String, Semaphore>();
|
||||
|
||||
public void lock(String key) {
|
||||
Semaphore semaphore = semaphores.compute(key, (k, v) -> v == null ? new Semaphore(ALLOWED_THREADS) : v);
|
||||
semaphore.acquireUninterruptibly();
|
||||
}
|
||||
|
||||
public void unlock(String key) {
|
||||
Semaphore semaphore = semaphores.get(key);
|
||||
semaphore.release();
|
||||
if (semaphore.availablePermits() == ALLOWED_THREADS) {
|
||||
semaphores.remove(key, semaphore);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,106 @@
|
|||
package com.baeldung.lockbykey;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class LockByKeyUnitTest {
|
||||
|
||||
@Test
|
||||
void givenNoLockedKey_WhenLock_ThenSuccess() throws InterruptedException {
|
||||
AtomicBoolean threadWasExecuted = new AtomicBoolean(false);
|
||||
Thread thread = new Thread(() -> {
|
||||
String key = "key";
|
||||
LockByKey lockByKey = new LockByKey();
|
||||
lockByKey.lock(key);
|
||||
try {
|
||||
threadWasExecuted.set(true);
|
||||
} finally {
|
||||
lockByKey.unlock(key);
|
||||
}
|
||||
});
|
||||
try {
|
||||
thread.start();
|
||||
Thread.sleep(100);
|
||||
} finally {
|
||||
assertTrue(threadWasExecuted.get());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenLockedKey_WhenLock_ThenFailure() throws InterruptedException {
|
||||
String key = "key";
|
||||
LockByKey lockByKey = new LockByKey();
|
||||
lockByKey.lock(key);
|
||||
AtomicBoolean anotherThreadWasExecuted = new AtomicBoolean(false);
|
||||
Thread threadLockingOnAnotherKey = new Thread(() -> {
|
||||
LockByKey otherLockByKey = new LockByKey();
|
||||
otherLockByKey.lock(key);
|
||||
try {
|
||||
anotherThreadWasExecuted.set(true);
|
||||
} finally {
|
||||
otherLockByKey.unlock(key);
|
||||
}
|
||||
});
|
||||
try {
|
||||
threadLockingOnAnotherKey.start();
|
||||
Thread.sleep(100);
|
||||
} finally {
|
||||
assertFalse(anotherThreadWasExecuted.get());
|
||||
lockByKey.unlock(key);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenAnotherKeyLocked_WhenLock_ThenSuccess() throws InterruptedException {
|
||||
String key = "key";
|
||||
LockByKey lockByKey = new LockByKey();
|
||||
lockByKey.lock(key);
|
||||
AtomicBoolean anotherThreadWasExecuted = new AtomicBoolean(false);
|
||||
Thread threadLockingOnAnotherKey = new Thread(() -> {
|
||||
String anotherKey = "anotherKey";
|
||||
LockByKey otherLockByKey = new LockByKey();
|
||||
otherLockByKey.lock(anotherKey);
|
||||
try {
|
||||
anotherThreadWasExecuted.set(true);
|
||||
} finally {
|
||||
otherLockByKey.unlock(anotherKey);
|
||||
}
|
||||
});
|
||||
try {
|
||||
threadLockingOnAnotherKey.start();
|
||||
Thread.sleep(100);
|
||||
} finally {
|
||||
assertTrue(anotherThreadWasExecuted.get());
|
||||
lockByKey.unlock(key);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenUnlockedKey_WhenLock_ThenSuccess() throws InterruptedException {
|
||||
String key = "key";
|
||||
LockByKey lockByKey = new LockByKey();
|
||||
lockByKey.lock(key);
|
||||
AtomicBoolean anotherThreadWasExecuted = new AtomicBoolean(false);
|
||||
Thread threadLockingOnAnotherKey = new Thread(() -> {
|
||||
LockByKey otherLockByKey = new LockByKey();
|
||||
otherLockByKey.lock(key);
|
||||
try {
|
||||
anotherThreadWasExecuted.set(true);
|
||||
} finally {
|
||||
otherLockByKey.unlock(key);
|
||||
}
|
||||
});
|
||||
try {
|
||||
lockByKey.unlock(key);
|
||||
threadLockingOnAnotherKey.start();
|
||||
Thread.sleep(100);
|
||||
} finally {
|
||||
assertTrue(anotherThreadWasExecuted.get());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
package com.baeldung.lockbykey;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class SimpleExclusiveLockByKeyUnitTest {
|
||||
|
||||
@BeforeEach
|
||||
void cleanUpLocks() throws Exception {
|
||||
Field field = SimpleExclusiveLockByKey.class.getDeclaredField("usedKeys");
|
||||
field.setAccessible(true);
|
||||
field.set(null, ConcurrentHashMap.newKeySet());
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenNoLockedKey_WhenTryLock_ThenSuccess() {
|
||||
SimpleExclusiveLockByKey lockByKey = new SimpleExclusiveLockByKey();
|
||||
assertTrue(lockByKey.tryLock("key"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenLockedKey_WhenTryLock_ThenFailure() {
|
||||
String key = "key";
|
||||
SimpleExclusiveLockByKey lockByKey = new SimpleExclusiveLockByKey();
|
||||
lockByKey.tryLock(key);
|
||||
assertFalse(lockByKey.tryLock(key));
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenAnotherKeyLocked_WhenTryLock_ThenSuccess() {
|
||||
SimpleExclusiveLockByKey lockByKey = new SimpleExclusiveLockByKey();
|
||||
lockByKey.tryLock("other");
|
||||
assertTrue(lockByKey.tryLock("key"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenUnlockedKey_WhenTryLock_ThenSuccess() {
|
||||
String key = "key";
|
||||
SimpleExclusiveLockByKey lockByKey = new SimpleExclusiveLockByKey();
|
||||
lockByKey.tryLock(key);
|
||||
lockByKey.unlock(key);
|
||||
assertTrue(lockByKey.tryLock(key));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,146 @@
|
|||
package com.baeldung.lockbykey;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class SimultaneousEntriesLockByKeyUnitTest {
|
||||
|
||||
@Test
|
||||
void givenNoKeyUsed_WhenLock_ThenSuccess() throws InterruptedException {
|
||||
AtomicBoolean threadWasExecuted = new AtomicBoolean(false);
|
||||
Thread thread = new Thread(() -> {
|
||||
String key = "key";
|
||||
SimultaneousEntriesLockByKey lockByKey = new SimultaneousEntriesLockByKey();
|
||||
lockByKey.lock(key);
|
||||
try {
|
||||
threadWasExecuted.set(true);
|
||||
} finally {
|
||||
lockByKey.unlock(key);
|
||||
}
|
||||
});
|
||||
try {
|
||||
thread.start();
|
||||
Thread.sleep(100);
|
||||
} finally {
|
||||
assertTrue(threadWasExecuted.get());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenKeyLockedWithRemainingPermits_WhenLock_ThenSuccess() throws InterruptedException {
|
||||
String key = "key";
|
||||
SimultaneousEntriesLockByKey lockByKey = new SimultaneousEntriesLockByKey();
|
||||
lockByKey.lock(key);
|
||||
AtomicBoolean anotherThreadWasExecuted = new AtomicBoolean(false);
|
||||
Thread threadLockingOnAnotherKey = new Thread(() -> {
|
||||
SimultaneousEntriesLockByKey otherLockByKeyWithSemaphore = new SimultaneousEntriesLockByKey();
|
||||
otherLockByKeyWithSemaphore.lock(key);
|
||||
try {
|
||||
anotherThreadWasExecuted.set(true);
|
||||
} finally {
|
||||
otherLockByKeyWithSemaphore.unlock(key);
|
||||
}
|
||||
});
|
||||
try {
|
||||
threadLockingOnAnotherKey.start();
|
||||
Thread.sleep(100);
|
||||
} finally {
|
||||
assertTrue(anotherThreadWasExecuted.get());
|
||||
lockByKey.unlock(key);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenKeyLockedWithNoRemainingPermits_WhenLock_ThenFailure() throws InterruptedException {
|
||||
String key = "key";
|
||||
SimultaneousEntriesLockByKey lockByKey = new SimultaneousEntriesLockByKey();
|
||||
lockByKey.lock(key);
|
||||
AtomicBoolean anotherThreadWasExecuted = new AtomicBoolean(false);
|
||||
Thread threadLockingOnAnotherKey1 = new Thread(() -> {
|
||||
SimultaneousEntriesLockByKey otherLockByKeyWithSemaphore = new SimultaneousEntriesLockByKey();
|
||||
otherLockByKeyWithSemaphore.lock(key);
|
||||
try {
|
||||
Thread.sleep(200); // make sure this thread will release the lock after the assertion
|
||||
} catch (InterruptedException e) {
|
||||
|
||||
} finally {
|
||||
otherLockByKeyWithSemaphore.unlock(key);
|
||||
}
|
||||
});
|
||||
Thread threadLockingOnAnotherKey2 = new Thread(() -> {
|
||||
SimultaneousEntriesLockByKey otherLockByKey = new SimultaneousEntriesLockByKey();
|
||||
try {
|
||||
Thread.sleep(50); // make sure thread1 will acquire the key first
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
otherLockByKey.lock(key);
|
||||
try {
|
||||
anotherThreadWasExecuted.set(true);
|
||||
} finally {
|
||||
otherLockByKey.unlock(key);
|
||||
}
|
||||
});
|
||||
try {
|
||||
threadLockingOnAnotherKey1.start();
|
||||
threadLockingOnAnotherKey2.start();
|
||||
Thread.sleep(100);
|
||||
} finally {
|
||||
assertFalse(anotherThreadWasExecuted.get());
|
||||
lockByKey.unlock(key);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenAnotherKeyLocked_WhenLock_ThenSuccess() throws InterruptedException {
|
||||
String key = "key";
|
||||
SimultaneousEntriesLockByKey lockByKey = new SimultaneousEntriesLockByKey();
|
||||
lockByKey.lock(key);
|
||||
AtomicBoolean anotherThreadWasExecuted = new AtomicBoolean(false);
|
||||
Thread threadLockingOnAnotherKey = new Thread(() -> {
|
||||
String anotherKey = "anotherKey";
|
||||
SimultaneousEntriesLockByKey otherLockByKey = new SimultaneousEntriesLockByKey();
|
||||
otherLockByKey.lock(anotherKey);
|
||||
try {
|
||||
anotherThreadWasExecuted.set(true);
|
||||
} finally {
|
||||
otherLockByKey.unlock(anotherKey);
|
||||
}
|
||||
});
|
||||
try {
|
||||
threadLockingOnAnotherKey.start();
|
||||
Thread.sleep(100);
|
||||
} finally {
|
||||
assertTrue(anotherThreadWasExecuted.get());
|
||||
lockByKey.unlock(key);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenUnlockedKey_WhenLock_ThenSuccess() throws InterruptedException {
|
||||
String key = "key";
|
||||
SimultaneousEntriesLockByKey lockByKey = new SimultaneousEntriesLockByKey();
|
||||
lockByKey.lock(key);
|
||||
AtomicBoolean anotherThreadWasExecuted = new AtomicBoolean(false);
|
||||
Thread threadLockingOnAnotherKey = new Thread(() -> {
|
||||
SimultaneousEntriesLockByKey otherLockByKey = new SimultaneousEntriesLockByKey();
|
||||
otherLockByKey.lock(key);
|
||||
try {
|
||||
anotherThreadWasExecuted.set(true);
|
||||
} finally {
|
||||
otherLockByKey.unlock(key);
|
||||
}
|
||||
});
|
||||
try {
|
||||
lockByKey.unlock(key);
|
||||
threadLockingOnAnotherKey.start();
|
||||
Thread.sleep(100);
|
||||
} finally {
|
||||
assertTrue(anotherThreadWasExecuted.get());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -16,12 +16,17 @@ class LongRunningAction implements Runnable {
|
|||
public void run() {
|
||||
System.out.println("This is phase " + ph.getPhase());
|
||||
System.out.println("Thread " + threadName + " before long running action");
|
||||
ph.arriveAndAwaitAdvance();
|
||||
|
||||
try {
|
||||
Thread.sleep(20);
|
||||
Thread.sleep(2000);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
System.out.println("Thread " + threadName + " action completed and waiting for others");
|
||||
ph.arriveAndAwaitAdvance();
|
||||
System.out.println("Thread " + threadName + " proceeding in phase " + ph.getPhase());
|
||||
|
||||
ph.arriveAndDeregister();
|
||||
}
|
||||
}
|
|
@ -26,13 +26,20 @@ public class PhaserUnitTest {
|
|||
executorService.submit(new LongRunningAction("thread-3", ph));
|
||||
|
||||
//then
|
||||
System.out.println("Thread " + Thread.currentThread().getName() + " waiting for others");
|
||||
ph.arriveAndAwaitAdvance();
|
||||
System.out.println("Thread " + Thread.currentThread().getName() + " proceeding in phase " + ph.getPhase());
|
||||
|
||||
assertEquals(1, ph.getPhase());
|
||||
|
||||
//and
|
||||
executorService.submit(new LongRunningAction("thread-4", ph));
|
||||
executorService.submit(new LongRunningAction("thread-5", ph));
|
||||
|
||||
System.out.println("Thread " + Thread.currentThread().getName() + " waiting for others");
|
||||
ph.arriveAndAwaitAdvance();
|
||||
System.out.println("Thread " + Thread.currentThread().getName() + " proceeding in phase " + ph.getPhase());
|
||||
|
||||
assertEquals(2, ph.getPhase());
|
||||
|
||||
|
||||
|
|
|
@ -12,7 +12,6 @@ This module contains articles about basic Java concurrency
|
|||
- [Guide to AtomicMarkableReference](https://www.baeldung.com/java-atomicmarkablereference)
|
||||
- [Why are Local Variables Thread-Safe in Java](https://www.baeldung.com/java-local-variables-thread-safe)
|
||||
- [How to Stop Execution After a Certain Time in Java](https://www.baeldung.com/java-stop-execution-after-certain-time)
|
||||
- [How to Handle InterruptedException in Java](https://www.baeldung.com/java-interrupted-exception)
|
||||
- [How to Get the Number of Threads in a Java Process](https://www.baeldung.com/java-get-number-of-threads)
|
||||
- [Set the Name of a Thread in Java](https://www.baeldung.com/java-set-thread-name)
|
||||
- [[<-- Prev]](/core-java-modules/core-java-concurrency-basic)
|
||||
- [[<-- Prev]](../core-java-concurrency-basic)[[Next -->]](../core-java-concurrency-basic-3)
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
package com.baeldung.concurrent.threads.name;
|
||||
|
||||
public class CustomThreadName {
|
||||
|
||||
public int currentNumber = 1;
|
||||
|
||||
public int N = 5;
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
CustomThreadName test = new CustomThreadName();
|
||||
|
||||
Thread oddThread = new Thread(() -> {
|
||||
test.printOddNumber();
|
||||
// Uncomment below to set thread name using setName() Method
|
||||
// Thread.currentThread().setName("ODD");
|
||||
}, "ODD");
|
||||
// or Uncomment below to set thread name using setName() Method
|
||||
// oddThread.setName("ODD");
|
||||
|
||||
Thread evenThread = new Thread(() -> {
|
||||
test.printEvenNumber();
|
||||
// Uncomment below to set thread name using setName() Method
|
||||
// Thread.currentThread().setName("EVEN");
|
||||
}, "EVEN");
|
||||
|
||||
// evenThread.setName("EVEN");
|
||||
|
||||
evenThread.start();
|
||||
oddThread.start();
|
||||
|
||||
}
|
||||
|
||||
public void printEvenNumber() {
|
||||
synchronized (this) {
|
||||
while (currentNumber < N) {
|
||||
while (currentNumber % 2 == 1) {
|
||||
try {
|
||||
wait();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
System.out.println(Thread.currentThread()
|
||||
.getName() + " --> " + currentNumber);
|
||||
currentNumber++;
|
||||
notify();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void printOddNumber() {
|
||||
synchronized (this) {
|
||||
while (currentNumber < N) {
|
||||
while (currentNumber % 2 == 0) {
|
||||
try {
|
||||
wait();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
System.out.println(Thread.currentThread()
|
||||
.getName() + " --> " + currentNumber);
|
||||
currentNumber++;
|
||||
notify();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -7,12 +7,6 @@
|
|||
</encoder>
|
||||
</appender>
|
||||
|
||||
<logger name="org.springframework" level="WARN" />
|
||||
<logger name="org.springframework.transaction" level="WARN" />
|
||||
|
||||
<!-- in order to debug some marshalling issues, this needs to be TRACE -->
|
||||
<logger name="org.springframework.web.servlet.mvc" level="WARN" />
|
||||
|
||||
<root level="INFO">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</root>
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
## Core Java Concurrency Basic
|
||||
|
||||
This module contains articles about basic Java concurrency.
|
||||
|
||||
### Relevant Articles:
|
||||
|
||||
- [How to Handle InterruptedException in Java](https://www.baeldung.com/java-interrupted-exception)
|
||||
- [[<-- Prev]](../core-java-concurrency-basic-2)
|
|
@ -0,0 +1,27 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>core-java-concurrency-basic-3</artifactId>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
<name>core-java-concurrency-basic-3</name>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung.core-java-modules</groupId>
|
||||
<artifactId>core-java-modules</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<build>
|
||||
<finalName>core-java-concurrency-basic-3</finalName>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<filtering>true</filtering>
|
||||
</resource>
|
||||
</resources>
|
||||
</build>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
|
||||
</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<root level="INFO">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</root>
|
||||
</configuration>
|
|
@ -1,7 +1,7 @@
|
|||
package com.baeldung.concurrent.interrupt;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
|
@ -9,23 +9,23 @@ public class InterruptExampleUnitTest {
|
|||
|
||||
@Test
|
||||
public void whenPropagateException_thenThrowsInterruptedException() {
|
||||
assertThrows(InterruptedException.class, () -> InterruptExample.propagateException());
|
||||
assertThrows(InterruptedException.class, InterruptExample::propagateException);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenRestoreTheState_thenReturnsTrue() {
|
||||
assertTrue(InterruptExample.restoreTheState());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void whenThrowCustomException_thenContainsExpectedMessage() {
|
||||
Exception exception = assertThrows(CustomInterruptedException.class, () -> InterruptExample.throwCustomException());
|
||||
Exception exception = assertThrows(CustomInterruptedException.class, InterruptExample::throwCustomException);
|
||||
String expectedMessage = "This thread was interrupted";
|
||||
String actualMessage = exception.getMessage();
|
||||
|
||||
assertTrue(actualMessage.contains(expectedMessage));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void whenHandleWithCustomException_thenReturnsTrue() throws CustomInterruptedException{
|
||||
assertTrue(InterruptExample.handleWithCustomException());
|
|
@ -2,4 +2,5 @@
|
|||
|
||||
- [Introduction to Lock Striping](https://www.baeldung.com/java-lock-stripping)
|
||||
- [Guide to the Java TransferQueue](http://www.baeldung.com/java-transfer-queue)
|
||||
- [Java Concurrent HashSet Equivalent to ConcurrentHashMap](https://www.baeldung.com/java-concurrent-hashset-concurrenthashmap)
|
||||
- [[<-- Prev]](/core-java-modules/core-java-concurrency-collections)
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
<artifactId>commons-lang3</artifactId>
|
||||
<version>${commons-lang3.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.darwinsys</groupId>
|
||||
<artifactId>hirondelle-date4j</artifactId>
|
||||
|
|
|
@ -7,7 +7,12 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
|
|||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class IllegalMonitorStateExceptionUnitTest {
|
||||
/**
|
||||
* Needs to be run manually in order to demonstrate the IllegalMonitorStateException scenarios.
|
||||
*
|
||||
* There are some intermittent test failures in Jenkins that require further investigation.
|
||||
*/
|
||||
public class IllegalMonitorStateExceptionManualTest {
|
||||
|
||||
@Test
|
||||
void whenSyncSenderAndSyncReceiverAreUsed_thenIllegalMonitorExceptionShouldNotBeThrown() throws InterruptedException {
|
|
@ -0,0 +1,4 @@
|
|||
### Relevant Articles:
|
||||
|
||||
- [Java ArrayIndexOutOfBoundsException](https://www.baeldung.com/java-arrayindexoutofboundsexception)
|
||||
- [Java Missing Return Statement](https://www.baeldung.com/java-missing-return-statement)
|
|
@ -0,0 +1,47 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.baeldung.exceptions</groupId>
|
||||
<artifactId>core-java-exceptions-4</artifactId>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
<name>core-java-exceptions-4</name>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung.core-java-modules</groupId>
|
||||
<artifactId>core-java-modules</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
<version>${h2.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.8.1</version>
|
||||
<configuration>
|
||||
<compilerArgs>
|
||||
<!-- Comment the arg below to print complete stack trace information -->
|
||||
<!-- <arg>-g:none</arg>-->
|
||||
</compilerArgs>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<properties>
|
||||
<h2.version>1.4.191</h2.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,31 @@
|
|||
package com.baeldung.exception.arrayindexoutofbounds;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class ArrayIndexOutOfBoundsExceptionDemo {
|
||||
|
||||
public static void main(String[] args) {
|
||||
int[] numbers = new int[] { 1, 2, 3, 4, 5 };
|
||||
|
||||
getArrayElementAtIndex(numbers, 5);
|
||||
getListElementAtIndex(5);
|
||||
addArrayElementsUsingLoop(numbers);
|
||||
}
|
||||
|
||||
public static void addArrayElementsUsingLoop(int[] numbers) {
|
||||
int sum = 0;
|
||||
for (int i = 0; i <= numbers.length; i++) {
|
||||
sum += numbers[i];
|
||||
}
|
||||
}
|
||||
|
||||
public static int getListElementAtIndex(int index) {
|
||||
List<Integer> numbersList = Arrays.asList(1, 2, 3, 4, 5);
|
||||
return numbersList.get(index);
|
||||
}
|
||||
|
||||
public static int getArrayElementAtIndex(int[] numbers, int index) {
|
||||
return numbers[index];
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue