pull from master

This commit is contained in:
@hangga
2023-11-12 18:23:58 +07:00
196 changed files with 2821 additions and 2009 deletions
@@ -0,0 +1,113 @@
package com.baeldung.rounddate;
import java.time.DayOfWeek;
import java.time.temporal.ChronoField;
import java.time.temporal.TemporalAdjusters;
import java.util.Calendar;
import java.util.Date;
import java.time.LocalDateTime;
import java.time.ZonedDateTime;
public class RoundDate {
public static Date getDate(int year, int month, int day, int hour, int minute) {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.YEAR, year);
calendar.set(Calendar.MONTH, month);
calendar.set(Calendar.DAY_OF_MONTH, day);
calendar.set(Calendar.HOUR_OF_DAY, hour);
calendar.set(Calendar.MINUTE, minute);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
return calendar.getTime();
}
public static Date roundToDay(Date date) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
return calendar.getTime();
}
public static Date roundToNearestUnit(Date date, int unit) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
switch (unit) {
case Calendar.HOUR:
int minute = calendar.get(Calendar.MINUTE);
if (minute >= 0 && minute < 15) {
calendar.set(Calendar.MINUTE, 0);
} else if (minute >= 15 && minute < 45) {
calendar.set(Calendar.MINUTE, 30);
} else {
calendar.set(Calendar.MINUTE, 0);
calendar.add(Calendar.HOUR_OF_DAY, 1);
}
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
break;
case Calendar.DAY_OF_MONTH:
int hour = calendar.get(Calendar.HOUR_OF_DAY);
if (hour >= 12) {
calendar.add(Calendar.DAY_OF_MONTH, 1);
}
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
break;
case Calendar.MONTH:
int day = calendar.get(Calendar.DAY_OF_MONTH);
if (day >= 15) {
calendar.add(Calendar.MONTH, 1);
}
calendar.set(Calendar.DAY_OF_MONTH, 1);
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
break;
}
return calendar.getTime();
}
public static LocalDateTime roundToStartOfMonthUsingLocalDateTime(LocalDateTime dateTime) {
return dateTime.withDayOfMonth(1).withHour(0).withMinute(0).withSecond(0).withNano(0);
}
public static LocalDateTime roundToEndOfWeekUsingLocalDateTime(LocalDateTime dateTime) {
return dateTime.with(TemporalAdjusters.next(DayOfWeek.SATURDAY))
.withHour(23)
.withMinute(59)
.withSecond(59)
.withNano(999);
}
public static ZonedDateTime roundToStartOfMonthUsingZonedDateTime(ZonedDateTime dateTime) {
return dateTime.withDayOfMonth(1)
.withHour(0)
.withMinute(0)
.withSecond(0)
.with(ChronoField.MILLI_OF_SECOND, 0)
.with(ChronoField.MICRO_OF_SECOND, 0)
.with(ChronoField.NANO_OF_SECOND, 0);
}
public static ZonedDateTime roundToEndOfWeekUsingZonedDateTime(ZonedDateTime dateTime) {
return dateTime.with(TemporalAdjusters.next(DayOfWeek.SATURDAY))
.withHour(23)
.withMinute(59)
.withSecond(59)
.with(ChronoField.MILLI_OF_SECOND, 999)
.with(ChronoField.MICRO_OF_SECOND, 999)
.with(ChronoField.NANO_OF_SECOND, 999);
}
}
@@ -0,0 +1,63 @@
package com.baeldung.rounddate;
import org.junit.Test;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Calendar;
import java.util.Date;
import static org.junit.Assert.assertEquals;
public class DateRoundingUnitTest {
@Test
public void givenDate_whenRoundToDay_thenBeginningOfDay() {
Date date = RoundDate.getDate(2023, Calendar.JANUARY, 27, 14, 30);
Date result = RoundDate.roundToDay(date);
assertEquals(RoundDate.getDate(2023, Calendar.JANUARY, 27, 0, 0), result);
}
@Test
public void givenDate_whenRoundToNearestUnit_thenNearestUnit() {
Date date = RoundDate.getDate(2023, Calendar.JANUARY, 27, 14, 12);
Date result = RoundDate.roundToNearestUnit(date, Calendar.DAY_OF_MONTH);
Date expected = RoundDate.getDate(2023, Calendar.JANUARY, 28, 0, 0);
assertEquals(expected, result);
}
@Test
public void givenLocalDateTime_whenRoundToStartOfMonth_thenStartOfMonth() {
LocalDateTime dateTime = LocalDateTime.of(2023, 1, 27, 14, 12);
LocalDateTime result = RoundDate.roundToStartOfMonthUsingLocalDateTime(dateTime);
LocalDateTime expected = LocalDateTime.of(2023, 1, 1, 0, 0, 0);
assertEquals(expected, result);
}
@Test
public void givenZonedDateTime_whenRoundToStartOfMonth_thenStartOfMonth() {
ZonedDateTime dateTime = ZonedDateTime.of(2023, 1, 27, 14, 12, 0, 0, ZoneId.systemDefault());
ZonedDateTime result = RoundDate.roundToStartOfMonthUsingZonedDateTime(dateTime);
ZonedDateTime expected = ZonedDateTime.of(2023, 1, 1, 0, 0, 0, 0, ZoneId.systemDefault());
assertEquals(expected, result);
}
@Test
public void givenLocalDateTime_whenRoundToEndOfWeek_thenEndOfWeek() {
LocalDateTime dateTime = LocalDateTime.of(2023, 1, 27, 14, 12);
LocalDateTime result = RoundDate.roundToEndOfWeekUsingLocalDateTime(dateTime);
LocalDateTime expected = LocalDateTime.of(2023, 1, 28, 23, 59, 59, 999);
assertEquals(expected, result);
}
@Test
public void givenZonedDateTime_whenRoundToEndOfWeek_thenEndOfWeek() {
ZonedDateTime dateTime = ZonedDateTime.of(2023, 1, 27, 14, 12, 0, 0, ZoneId.systemDefault());
ZonedDateTime result = RoundDate.roundToEndOfWeekUsingZonedDateTime(dateTime);
ZonedDateTime expected = ZonedDateTime.of(2023, 1, 28, 23, 59, 59, 999, ZoneId.systemDefault());
assertEquals(expected, result);
}
}
@@ -0,0 +1,48 @@
package com.baeldung.spliterator;
import java.util.List;
import java.util.Spliterator;
import java.util.function.Consumer;
public class CustomSpliterator implements Spliterator<Integer> {
private final List<Integer> elements;
private int currentIndex;
public CustomSpliterator(List<Integer> elements) {
this.elements = elements;
this.currentIndex = 0;
}
@Override
public boolean tryAdvance(Consumer<? super Integer> action) {
if (currentIndex < elements.size()) {
action.accept(elements.get(currentIndex));
currentIndex++;
return true;
}
return false;
}
@Override
public Spliterator<Integer> trySplit() {
int currentSize = elements.size() - currentIndex;
if (currentSize < 2) {
return null;
}
int splitIndex = currentIndex + currentSize / 2;
CustomSpliterator newSpliterator = new CustomSpliterator(elements.subList(currentIndex, splitIndex));
currentIndex = splitIndex;
return newSpliterator;
}
@Override
public long estimateSize() {
return elements.size() - currentIndex;
}
@Override
public int characteristics() {
return ORDERED | SIZED | SUBSIZED | NONNULL;
}
}
@@ -1,12 +0,0 @@
package com.baeldung.spliterator;
import java.util.stream.Stream;
public class Executor {
public static int countAutors(Stream<Author> stream) {
RelatedAuthorCounter wordCounter = stream.reduce(new RelatedAuthorCounter(0, true),
RelatedAuthorCounter::accumulate, RelatedAuthorCounter::combine);
return wordCounter.getCounter();
}
}
@@ -1,27 +0,0 @@
package com.baeldung.spliterator;
public class RelatedAuthorCounter {
private final int counter;
private final boolean isRelated;
public RelatedAuthorCounter(int counter, boolean isRelated) {
this.counter = counter;
this.isRelated = isRelated;
}
public RelatedAuthorCounter accumulate(Author author) {
if (author.getRelatedArticleId() == 0) {
return isRelated ? this : new RelatedAuthorCounter(counter, true);
} else {
return isRelated ? new RelatedAuthorCounter(counter + 1, false) : this;
}
}
public RelatedAuthorCounter combine(RelatedAuthorCounter RelatedAuthorCounter) {
return new RelatedAuthorCounter(counter + RelatedAuthorCounter.counter, RelatedAuthorCounter.isRelated);
}
public int getCounter() {
return counter;
}
}
@@ -1,49 +0,0 @@
package com.baeldung.spliterator;
import java.util.List;
import java.util.Spliterator;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
public class RelatedAuthorSpliterator implements Spliterator<Author> {
private final List<Author> list;
AtomicInteger current = new AtomicInteger();
public RelatedAuthorSpliterator(List<Author> list) {
this.list = list;
}
@Override
public boolean tryAdvance(Consumer<? super Author> action) {
action.accept(list.get(current.getAndIncrement()));
return current.get() < list.size();
}
@Override
public Spliterator<Author> trySplit() {
int currentSize = list.size() - current.get();
if (currentSize < 10) {
return null;
}
for (int splitPos = currentSize / 2 + current.intValue(); splitPos < list.size(); splitPos++) {
if (list.get(splitPos).getRelatedArticleId() == 0) {
Spliterator<Author> spliterator = new RelatedAuthorSpliterator(list.subList(current.get(), splitPos));
current.set(splitPos);
return spliterator;
}
}
return null;
}
@Override
public long estimateSize() {
return list.size() - current.get();
}
@Override
public int characteristics() {
return CONCURRENT;
}
}
@@ -6,10 +6,10 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Spliterator;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import org.junit.Before;
import org.junit.Test;
@@ -18,22 +18,50 @@ import lombok.extern.slf4j.Slf4j;
@Slf4j
public class ExecutorUnitTest {
Article article;
Stream<Author> stream;
Spliterator<Author> spliterator;
@Before
public void init() {
article = new Article(Arrays.asList(new Author("Ahmad", 0), new Author("Eugen", 0), new Author("Alice", 1), new Author("Alice", 1), new Author("Mike", 0), new Author("Alice", 1), new Author("Mike", 0), new Author("Alice", 1), new Author("Mike", 0),
new Author("Alice", 1), new Author("Mike", 0), new Author("Mike", 0), new Author("Alice", 1), new Author("Mike", 0), new Author("Alice", 1), new Author("Mike", 0), new Author("Alice", 1), new Author("Mike", 0), new Author("Alice", 1),
new Author("Mike", 0), new Author("Michał", 0), new Author("Loredana", 1)), 0);
spliterator = new RelatedAuthorSpliterator(article.getListOfAuthors());
}
@Test
public void givenAstreamOfAuthors_whenProcessedInParallelWithCustomSpliterator_coubtProducessRightOutput() {
Stream<Author> stream2 = StreamSupport.stream(spliterator, true);
assertThat(Executor.countAutors(stream2.parallel())).isEqualTo(9);
public void givenAStreamOfIntegers_whenProcessedSequentialCustomSpliterator_countProducesRightOutput() {
List<Integer> numbers = new ArrayList<>();
numbers.add(1);
numbers.add(2);
numbers.add(3);
numbers.add(4);
numbers.add(5);
CustomSpliterator customSpliterator = new CustomSpliterator(numbers);
AtomicInteger sum = new AtomicInteger();
customSpliterator.forEachRemaining(sum::addAndGet);
assertThat(sum.get()).isEqualTo(15);
}
@Test
public void givenAStreamOfIntegers_whenProcessedInParallelWithCustomSpliterator_countProducesRightOutput() {
List<Integer> numbers = new ArrayList<>();
numbers.add(1);
numbers.add(2);
numbers.add(3);
numbers.add(4);
numbers.add(5);
CustomSpliterator customSpliterator = new CustomSpliterator(numbers);
// Create a ForkJoinPool for parallel processing
ForkJoinPool forkJoinPool = ForkJoinPool.commonPool();
AtomicInteger sum = new AtomicInteger(0);
// Process elements in parallel using parallelStream
forkJoinPool.submit(() -> customSpliterator.forEachRemaining(sum::addAndGet)).join();
assertThat(sum.get()).isEqualTo(15);
}
@Test
@@ -43,9 +71,7 @@ public class ExecutorUnitTest {
.collect(Collectors.toList());
Spliterator<Article> spliterator = articles.spliterator();
while (spliterator.tryAdvance(article -> article.setName(article.getName()
.concat("- published by Baeldung"))))
;
while(spliterator.tryAdvance(article -> article.setName(article.getName().concat("- published by Baeldung"))));
articles.forEach(article -> assertThat(article.getName()).isEqualTo("Java- published by Baeldung"));
}
@@ -0,0 +1,87 @@
package com.baeldung.vectors;
import static org.junit.Assert.assertEquals;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Vector;
import org.junit.Test;
public class VectorOperationsUnitTest {
private static Vector<String> getVector() {
Vector<String> vector = new Vector<String>();
vector.add("Today");
vector.add("is");
vector.add("a");
vector.add("great");
vector.add("day!");
return vector;
}
@Test
public void givenAVector_whenAddElementsUsingAddMethod_thenElementsGetAddedAtEnd() {
Vector<String> vector = getVector();
vector.add("Hello");
assertEquals(6, vector.size());
}
@Test
public void givenAVector_whenUpdateElementAtIndex_thenElementAtIndexGetsUpdated() {
Vector<String> vector = getVector();
assertEquals(5, vector.size());
assertEquals("great", vector.get(3));
vector.set(3, "good");
assertEquals("good", vector.get(3));
}
@Test
public void givenAVector_whenRemoveAnElement_thenElementGetsRemovedFromTheVector() {
Vector<String> vector = getVector();
assertEquals(5, vector.size());
// remove a specific element
vector.remove("a");
assertEquals(4, vector.size());
// remove at specific index
vector.remove(2);
assertEquals("day!", vector.get(2));
assertEquals(3, vector.size());
assertEquals(false, vector.remove("SomethingThatDoesn'tExist"));
}
@Test(expected = ArrayIndexOutOfBoundsException.class)
public void givenAVector_whenIndexIsBeyondRange_thenRemoveMethodThrowsArrayIndexOutOfBoundsException() {
Vector<String> vector = getVector();
assertEquals(5, vector.size());
vector.remove(10);
}
@Test
public void givenAVector_whenGetElementWithinARange_thenGetMethodGetsAnElementFromTheVector() {
Vector<String> vector = getVector();
String fourthElement = vector.get(3);
assertEquals("great", fourthElement);
}
@Test(expected = ArrayIndexOutOfBoundsException.class)
public void givenAVector_whenGetElementBeyondARange_thenGetMethodThrowsArrayIndexOutOfBoundsException() {
Vector<String> vector = getVector();
assertEquals(5, vector.size());
vector.get(10);
}
@Test
public void givenAVector_whenAddElementFromACollection_thenAllElementsGetAdeddToTheVector() {
Vector<String> vector = getVector();
assertEquals(5, vector.size());
ArrayList<String> words = new ArrayList<>(Arrays.asList("Baeldung", "is", "cool!"));
vector.addAll(words);
assertEquals(8, vector.size());
assertEquals("cool!", vector.get(7));
}
}
@@ -79,5 +79,18 @@
<version>1.5</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>
--add-opens java.base/java.util=ALL-UNNAMED
</argLine>
</configuration>
</plugin>
</plugins>
</build>
</project>
@@ -0,0 +1,85 @@
package com.baeldung.map.linkedhashmapfirstandlastentry;
import org.junit.jupiter.api.Test;
import java.lang.reflect.Field;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map.Entry;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
public class GetFirstAndLastEntryFromLinkedHashMapUnitTest {
private static final LinkedHashMap<String, String> THE_MAP = new LinkedHashMap<>();
static {
THE_MAP.put("key one", "a1 b1 c1");
THE_MAP.put("key two", "a2 b2 c2");
THE_MAP.put("key three", "a3 b3 c3");
THE_MAP.put("key four", "a4 b4 c4");
}
@Test
void whenIteratingEntrySet_thenGetExpectedResult() {
Entry<String, String> firstEntry = THE_MAP.entrySet().iterator().next();
assertEquals("key one", firstEntry.getKey());
assertEquals("a1 b1 c1", firstEntry.getValue());
Entry<String, String> lastEntry = null;
Iterator<Entry<String, String>> it = THE_MAP.entrySet().iterator();
while (it.hasNext()) {
lastEntry = it.next();
}
assertNotNull(lastEntry);
assertEquals("key four", lastEntry.getKey());
assertEquals("a4 b4 c4", lastEntry.getValue());
}
@Test
void whenConvertingEntriesToArray_thenGetExpectedResult() {
Entry<String, String>[] theArray = new Entry[THE_MAP.size()];
THE_MAP.entrySet().toArray(theArray);
Entry<String, String> firstEntry = theArray[0];
assertEquals("key one", firstEntry.getKey());
assertEquals("a1 b1 c1", firstEntry.getValue());
Entry<String, String> lastEntry = theArray[THE_MAP.size() - 1];
assertEquals("key four", lastEntry.getKey());
assertEquals("a4 b4 c4", lastEntry.getValue());
}
@Test
void whenUsingStreamAPI_thenGetExpectedResult() {
Entry<String, String> firstEntry = THE_MAP.entrySet().stream().findFirst().get();
assertEquals("key one", firstEntry.getKey());
assertEquals("a1 b1 c1", firstEntry.getValue());
Entry<String, String> lastEntry = THE_MAP.entrySet().stream().skip(THE_MAP.size() - 1).findFirst().get();
assertNotNull(lastEntry);
assertEquals("key four", lastEntry.getKey());
assertEquals("a4 b4 c4", lastEntry.getValue());
}
@Test
void whenUsingReflection_thenGetExpectedResult() throws NoSuchFieldException, IllegalAccessException {
Field head = THE_MAP.getClass().getDeclaredField("head");
head.setAccessible(true);
Entry<String, String> firstEntry = (Entry<String, String>) head.get(THE_MAP);
assertEquals("key one", firstEntry.getKey());
assertEquals("a1 b1 c1", firstEntry.getValue());
Field tail = THE_MAP.getClass().getDeclaredField("tail");
tail.setAccessible(true);
Entry<String, String> lastEntry = (Entry<String, String>) tail.get(THE_MAP);
assertEquals("key four", lastEntry.getKey());
assertEquals("a4 b4 c4", lastEntry.getValue());
}
}
@@ -11,4 +11,5 @@ This module contains articles about basic Java concurrency.
- [CompletableFuture and ThreadPool in Java](https://www.baeldung.com/java-completablefuture-threadpool)
- [CompletableFuture allOf().join() vs. CompletableFuture.join()](https://www.baeldung.com/java-completablefuture-allof-join)
- [Retry Logic with CompletableFuture](https://www.baeldung.com/java-completablefuture-retry-logic)
- [Convert From List of CompletableFuture to CompletableFuture List](https://www.baeldung.com/java-completablefuture-list-convert)
- [[<-- Prev]](../core-java-concurrency-basic-2)
@@ -0,0 +1,23 @@
package com.baeldung.generictype;
/**
* @param <T> The type of the first value in the {@code Pair<T,S>}.
* @param <S> The type of the second value in the {@code Pair<T,S>}.
*/
public class Pair<T, S> {
public T first;
public S second;
/**
* Constructs a new Pair object with the specified values.
*
* @param a The first value.
* @param b The second value.
*/
public Pair(T a, S b) {
first = a;
second = b;
}
}
@@ -5,5 +5,6 @@ This module contains articles about core Java input and output (IO)
### Relevant Articles:
- [Get File Extension From MIME Type in Java](https://www.baeldung.com/java-mime-type-file-extension)
- [How to Remove Line Breaks From a File in Java](https://www.baeldung.com/java-file-remove-line-breaks)
- [Difference Between ZipFile and ZipInputStream in Java](https://www.baeldung.com/java-zipfile-vs-zipinputstream)
- [[<-- Prev]](/core-java-modules/core-java-io-4)
@@ -8,3 +8,4 @@ This module contains articles about core Java input/output(IO) APIs.
- [Check if a File Is Empty in Java](https://www.baeldung.com/java-check-file-empty)
- [Converting Relative to Absolute Paths in Java](https://www.baeldung.com/java-from-relative-to-absolute-paths)
- [Detect EOF in Java](https://www.baeldung.com/java-file-detect-end-of-file)
- [PrintWriter vs. FileWriter in Java](https://www.baeldung.com/java-printwriter-filewriter-difference)
@@ -56,7 +56,7 @@
<source.version>11</source.version>
<target.version>11</target.version>
<json.version>20200518</json.version>
<opencsv.version>4.1</opencsv.version>
<opencsv.version>5.8</opencsv.version>
</properties>
</project>
@@ -0,0 +1,72 @@
package com.baeldung.jndi;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.jndi.JndiTemplate;
import org.springframework.mock.jndi.SimpleNamingContextBuilder;
import javax.naming.*;
import javax.sql.DataSource;
import java.util.Enumeration;
import static org.junit.jupiter.api.Assertions.*;
class JndiNamingUnitTest {
private static InitialContext context;
private static DriverManagerDataSource dataSource;
@BeforeAll
static void setUp() throws Exception {
SimpleNamingContextBuilder builder = new SimpleNamingContextBuilder();
dataSource = new DriverManagerDataSource("jdbc:h2:mem:mydb");
builder.activate();
JndiTemplate jndiTemplate = new JndiTemplate();
context = (InitialContext) jndiTemplate.getContext();
dataSource.setDriverClassName("org.h2.Driver");
context.bind("java:comp/env/jdbc/datasource", dataSource);
}
@Test
void givenACompositeName_whenAddingAnElement_thenNameIsAdded() throws Exception {
Name objectName = new CompositeName("java:comp/env/jdbc");
Enumeration<String> items = objectName.getAll();
while(items.hasMoreElements()) {
System.out.println(items.nextElement());
}
objectName.add("New Name");
assertEquals("env", objectName.get(1));
assertEquals("New Name", objectName.get(objectName.size() - 1));
}
@Test
void givenContext_whenLookupByName_thenReturnsValidObject() throws Exception {
DataSource ds = (DataSource) context.lookup("java:comp/env/jdbc/datasource");
assertNotNull(ds);
assertNotNull(ds.getConnection());
}
@Test
void givenSubContext_whenLookupByName_thenReturnsValidObject() throws Exception {
Context subContext = (Context) context.lookup("java:comp/env");
DataSource ds = (DataSource) subContext.lookup("jdbc/datasource");
assertNotNull(ds);
assertNotNull(ds.getConnection());
}
@AfterAll
static void tearDown() throws Exception {
context.close();
}
}
@@ -0,0 +1,122 @@
package com.baeldung.genericnumberscomparator;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.function.BiFunction;
import java.util.function.BiPredicate;
import java.util.function.Function;
import org.junit.jupiter.api.Test;
class GenericNumbersComparatorUnitTest {
public int compareDouble(Number num1, Number num2) {
return Double.compare(num1.doubleValue(), num2.doubleValue());
}
@Test
void givenNumbers_whenUseCompareDouble_thenWillExecuteComparison() {
assertEquals(0, compareDouble(5, 5.0));
}
public int compareTo(Integer int1, Integer int2) {
return int1.compareTo(int2);
}
@Test
void givenNumbers_whenUseCompareTo_thenWillExecuteComparison() {
assertEquals(-1, compareTo(5, 7));
}
Map<Class<? extends Number>, BiFunction<Number, Number, Integer>> comparisonMap = new HashMap<>();
public int compareUsingMap(Number num1, Number num2) {
comparisonMap.put(Integer.class, (a, b) -> ((Integer) num1).compareTo((Integer) num2));
return comparisonMap.get(num1.getClass())
.apply(num1, num2);
}
@Test
void givenNumbers_whenUseCompareUsingMap_thenWillExecuteComparison() {
assertEquals(-1, compareUsingMap(5, 7));
}
public interface NumberComparator {
int compare(Number num1, Number num2);
}
@Test
void givenNumbers_whenUseProxy_thenWillExecuteComparison() {
NumberComparator proxy = (NumberComparator) Proxy.newProxyInstance(NumberComparator.class.getClassLoader(), new Class[] { NumberComparator.class },
(p, method, args) -> Double.compare(((Number) args[0]).doubleValue(), ((Number) args[1]).doubleValue()));
assertEquals(0, proxy.compare(5, 5.0));
}
public int compareUsingReflection(Number num1, Number num2) throws Exception {
Method method = num1.getClass()
.getMethod("compareTo", num1.getClass());
return (int) method.invoke(num1, num2);
}
@Test
void givenNumbers_whenUseCompareUsingReflection_thenWillExecuteComparison() throws Exception {
assertEquals(-1, compareUsingReflection(5, 7));
}
interface NumberComparatorFactory {
Comparator<Number> getComparator();
}
class IntegerComparatorFactory implements NumberComparatorFactory {
@Override
public Comparator<Number> getComparator() {
return (num1, num2) -> ((Integer) num1).compareTo((Integer) num2);
}
}
@Test
void givenNumbers_whenUseComparatorFactory_thenWillExecuteComparison() {
NumberComparatorFactory factory = new IntegerComparatorFactory();
Comparator<Number> comparator = factory.getComparator();
assertEquals(-1, comparator.compare(5, 7));
}
Function<Number, Double> toDouble = Number::doubleValue;
BiPredicate<Number, Number> isEqual = (num1, num2) -> toDouble.apply(num1)
.equals(toDouble.apply(num2));
@Test
void givenNumbers_whenUseIsEqual_thenWillExecuteComparison() {
assertEquals(true, isEqual.test(5, 5.0));
}
private Number someNumber = 5;
private Number anotherNumber = 5.0;
Optional<Number> optNum1 = Optional.ofNullable(someNumber);
Optional<Number> optNum2 = Optional.ofNullable(anotherNumber);
int comparisonResult = optNum1.flatMap(n1 -> optNum2.map(n2 -> Double.compare(n1.doubleValue(), n2.doubleValue())))
.orElse(0);
@Test
void givenNumbers_whenUseComparisonResult_thenWillExecuteComparison() {
assertEquals(0, comparisonResult);
}
private boolean someCondition = true;
Function<Number, ?> dynamicFunction = someCondition ? Number::doubleValue : Number::intValue;
Comparator<Number> dynamicComparator = (num1, num2) -> ((Comparable) dynamicFunction.apply(num1)).compareTo(dynamicFunction.apply(num2));
@Test
void givenNumbers_whenUseDynamicComparator_thenWillExecuteComparison() {
assertEquals(0, dynamicComparator.compare(5, 5.0));
}
}
@@ -0,0 +1,6 @@
package com.baeldung.optionalsasparameterrecords;
import java.util.Optional;
public record Product(String name, double price, Optional<String> description) {
}
@@ -0,0 +1,17 @@
package com.baeldung.optionalsasparameterrecords;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import java.util.Optional;
public class OptionalAsRecordParameterUnitTest {
@Test
public void givenRecordCreationWithOptional_thenCreateItProperly() {
var emptyDescriptionProduct = new Product("television", 1699.99, Optional.empty());
Assertions.assertEquals("television", emptyDescriptionProduct.name());
Assertions.assertEquals(1699.99, emptyDescriptionProduct.price());
Assertions.assertNull(emptyDescriptionProduct.description().orElse(null));
}
}
@@ -85,7 +85,7 @@ public class AlphanumericPerformanceBenchmark {
public boolean isAlphanumeric(final int codePoint) {
return (codePoint >= 65 && codePoint <= 90) ||
(codePoint >= 97 && codePoint <= 172) ||
(codePoint >= 97 && codePoint <= 122) ||
(codePoint >= 48 && codePoint <= 57);
}
}
@@ -0,0 +1,100 @@
package com.baeldung.streamtomapandmultimap;
import com.google.common.collect.LinkedHashMultimap;
import org.junit.Test;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static org.junit.Assert.assertEquals;
public class StreamToMapAndMultiMapUnitTest {
@Test
public void givenStringStream_whenConvertingToMapWithMerge_thenExpectedMapIsGenerated() {
Stream<String> stringStream = Stream.of("one", "two", "three", "two");
Map<String, String> mergedMap = stringStream.collect(
Collectors.toMap(s -> s, s -> s, (s1, s2) -> s1 + ", " + s2)
);
// Define the expected map
Map<String, String> expectedMap = Map.of(
"one", "one",
"two", "two, two",
"three", "three"
);
assertEquals(expectedMap, mergedMap);
}
@Test
public void givenStringStream_whenConvertingToMultimap_thenExpectedMultimapIsGenerated() {
Stream<String> stringStream = Stream.of("one", "two", "three", "two");
LinkedHashMultimap<Object, Object> multimap = LinkedHashMultimap.create();
stringStream.collect(Collectors.groupingBy(
s -> s,
Collectors.mapping(s -> s, Collectors.toList())
)).forEach((key, value) -> multimap.putAll(key, value));
LinkedHashMultimap<Object, Object> expectedMultimap = LinkedHashMultimap.create();
expectedMultimap.put("one", "one");
expectedMultimap.put("two", "two");
expectedMultimap.put("three", "three");
assertEquals(expectedMultimap, multimap);
}
@Test
public void givenStringStream_whenConvertingToMultimapWithStreamReduce_thenExpectedMultimapIsGenerated() {
Stream<String> stringStream = Stream.of("one", "two", "three", "two");
Map<String, List<String>> multimap = stringStream.reduce(
new HashMap<>(),
(map, element) -> {
map.computeIfAbsent(element, k -> new ArrayList<>()).add(element);
return map;
},
(map1, map2) -> {
map2.forEach((key, value) -> map1.merge(key, value, (list1, list2) -> {
list1.addAll(list2);
return list1;
}));
return map1;
}
);
Map<String, List<String>> expectedMultimap = new HashMap<>();
expectedMultimap.put("one", Collections.singletonList("one"));
expectedMultimap.put("two", Arrays.asList("two", "two"));
expectedMultimap.put("three", Collections.singletonList("three"));
assertEquals(expectedMultimap, multimap);
}
@Test
public void givenStringStream_whenConvertingToMapWithStreamReduce_thenExpectedMapIsGenerated() {
Stream<String> stringStream = Stream.of("one", "two", "three", "two");
Map<String, String> resultMap = stringStream.reduce(
new HashMap<>(),
(map, element) -> {
map.put(element, element);
return map;
},
(map1, map2) -> {
map1.putAll(map2);
return map1;
}
);
Map<String, String> expectedMap = new HashMap<>();
expectedMap.put("one", "one");
expectedMap.put("two", "two");
expectedMap.put("three", "three");
assertEquals(expectedMap, resultMap);
}
}
@@ -1,7 +1,11 @@
package com.baeldung.streams;
import org.junit.Before;
import org.junit.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import java.nio.file.Path;
import java.nio.file.Paths;
@@ -11,14 +15,12 @@ import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static org.junit.Assert.*;
class Java8StreamsUnitTest {
public class Java8StreamsUnitTest {
private static List<String> list;
private List<String> list;
@Before
public void init() {
@BeforeAll
public static void init() {
list = new ArrayList<>();
list.add("One");
list.add("OneAndOnly");
@@ -42,60 +44,73 @@ public class Java8StreamsUnitTest {
Stream<String> streamOf = Stream.of("a", "b", "c");
assertEquals(streamOf.count(), 3);
long count = list.stream().distinct().count();
long count = list.stream()
.distinct()
.count();
assertEquals(count, 9);
}
@Test
public void checkStreamCount_whenOperationFilter_thanCorrect() {
Stream<String> streamFilter = list.stream().filter(element -> element.isEmpty());
void checkStreamCount_whenOperationFilter_thanCorrect() {
Stream<String> streamFilter = list.stream()
.filter(element -> element.isEmpty());
assertEquals(streamFilter.count(), 2);
}
@Test
public void checkStreamCount_whenOperationMap_thanCorrect() {
void checkStreamCount_whenOperationMap_thanCorrect() {
List<String> uris = new ArrayList<>();
uris.add("C:\\My.txt");
Stream<Path> streamMap = uris.stream().map(uri -> Paths.get(uri));
Stream<Path> streamMap = uris.stream()
.map(uri -> Paths.get(uri));
assertEquals(streamMap.count(), 1);
List<Detail> details = new ArrayList<>();
details.add(new Detail());
details.add(new Detail());
Stream<String> streamFlatMap = details.stream().flatMap(detail -> detail.getParts().stream());
Stream<String> streamFlatMap = details.stream()
.flatMap(detail -> detail.getParts()
.stream());
assertEquals(streamFlatMap.count(), 4);
}
@Test
public void checkStreamCount_whenOperationMatch_thenCorrect() {
boolean isValid = list.stream().anyMatch(element -> element.contains("h"));
boolean isValidOne = list.stream().allMatch(element -> element.contains("h"));
boolean isValidTwo = list.stream().noneMatch(element -> element.contains("h"));
void checkStreamCount_whenOperationMatch_thenCorrect() {
boolean isValid = list.stream()
.anyMatch(element -> element.contains("h"));
boolean isValidOne = list.stream()
.allMatch(element -> element.contains("h"));
boolean isValidTwo = list.stream()
.noneMatch(element -> element.contains("h"));
assertTrue(isValid);
assertFalse(isValidOne);
assertFalse(isValidTwo);
}
@Test
public void checkStreamReducedValue_whenOperationReduce_thenCorrect() {
void checkStreamReducedValue_whenOperationReduce_thenCorrect() {
List<Integer> integers = new ArrayList<>();
integers.add(1);
integers.add(1);
integers.add(1);
Integer reduced = integers.stream().reduce(23, (a, b) -> a + b);
Integer reduced = integers.stream()
.reduce(23, (a, b) -> a + b);
assertTrue(reduced == 26);
}
@Test
public void checkStreamContains_whenOperationCollect_thenCorrect() {
List<String> resultList = list.stream().map(element -> element.toUpperCase()).collect(Collectors.toList());
void checkStreamContains_whenOperationCollect_thenCorrect() {
List<String> resultList = list.stream()
.map(element -> element.toUpperCase())
.collect(Collectors.toList());
assertEquals(resultList.size(), list.size());
assertTrue(resultList.contains(""));
}
@Test
public void checkParallelStream_whenDoWork() {
list.parallelStream().forEach(element -> doWork(element));
list.parallelStream()
.forEach(element -> doWork(element));
}
private void doWork(String string) {
@@ -0,0 +1,106 @@
package com.baeldung.nthsubstring;
import org.junit.jupiter.api.Test;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class FindNthSubstringIndexUnitTest {
// "0 8 16 24 "
private final static String INPUT = "a word, a word, a word, a word";
@Test
void whenCallingIndexOfTwice_thenGetTheSecondSubstringIndex() {
int firstIdx = INPUT.indexOf("a");
int result = INPUT.indexOf("a", firstIdx + "a".length());
assertEquals(8, result);
}
// the recursive approach
static int nthIndexOf(String input, String substring, int nth) {
if (nth == 1) {
return input.indexOf(substring);
} else {
return input.indexOf(substring, nthIndexOf(input, substring, nth - 1) + substring.length());
}
}
@Test
void whenCallingRecursiveMethod_thenGetTheExpectedResult() {
int result1 = nthIndexOf(INPUT, "a", 1);
assertEquals(0, result1);
int result2 = nthIndexOf(INPUT, "a", 2);
assertEquals(8, result2);
int result3 = nthIndexOf(INPUT, "a", 3);
assertEquals(16, result3);
int result4 = nthIndexOf(INPUT, "a", 4);
assertEquals(24, result4);
int result5 = nthIndexOf(INPUT, "a", 5);
assertEquals(-1, result5);
}
// loop-based approach
static int nthIndexOf2(String input, String substring, int nth) {
int index = -1;
while (nth > 0) {
index = input.indexOf(substring, index + substring.length());
if (index == -1) {
return -1;
}
nth--;
}
return index;
}
@Test
void whenCallingLoopBasedMethod_thenGetTheExpectedResult() {
int result1 = nthIndexOf2(INPUT, "a", 1);
assertEquals(0, result1);
int result2 = nthIndexOf2(INPUT, "a", 2);
assertEquals(8, result2);
int result3 = nthIndexOf2(INPUT, "a", 3);
assertEquals(16, result3);
int result4 = nthIndexOf2(INPUT, "a", 4);
assertEquals(24, result4);
int result5 = nthIndexOf2(INPUT, "a", 5);
assertEquals(-1, result5);
}
static int nthOccurrenceIndex(String input, String regexPattern, int nth) {
Matcher matcher = Pattern.compile(regexPattern).matcher(INPUT);
for (int i = 0; i < nth; i++) {
if (!matcher.find()) {
return -1;
}
}
return matcher.start();
}
@Test
void whenCallingRegexBasedMethod_thenGetTheExpectedResult() {
int result1 = nthOccurrenceIndex(INPUT, "a", 1);
assertEquals(0, result1);
int result2 = nthOccurrenceIndex(INPUT, "a", 2);
assertEquals(8, result2);
int result3 = nthOccurrenceIndex(INPUT, "a", 3);
assertEquals(16, result3);
int result4 = nthOccurrenceIndex(INPUT, "a", 4);
assertEquals(24, result4);
int result5 = nthOccurrenceIndex(INPUT, "a", 5);
assertEquals(-1, result5);
}
}
@@ -54,6 +54,11 @@
<artifactId>commons-codec</artifactId>
<version>${commons-codec.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring-core.version}</version>
</dependency>
</dependencies>
<build>
@@ -95,6 +100,7 @@
<javax.el-api.version>3.0.0</javax.el-api.version>
<javax.el.version>2.2.6</javax.el.version>
<commons-codec.version>1.14</commons-codec.version>
<spring-core.version>5.3.0</spring-core.version>
</properties>
</project>
@@ -3,6 +3,7 @@ package com.baeldung.emptystrings;
import com.google.common.base.Strings;
import org.apache.commons.lang3.StringUtils;
import org.junit.Test;
import org.springframework.util.ObjectUtils;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
@@ -109,6 +110,24 @@ public class EmptyStringsUnitTest {
assertFalse(Strings.isNullOrEmpty(blankString));
}
/*
* Spring Core ObjectUtils
*/
@Test
public void givenSomeEmptyString_thenObjectUtilsIsEmptyReturnsTrue() {
assertTrue(ObjectUtils.isEmpty(emptyString));
}
@Test
public void givenSomeNonEmptyString_thenObjectUtilsIsEmptyReturnsFalse() {
assertFalse(ObjectUtils.isEmpty(nonEmptyString));
}
@Test
public void givenSomeBlankString_thenObjectUtilsIsEmptyReturnsFalse() {
assertFalse(ObjectUtils.isEmpty(blankString));
}
/*
* Bean Validation
*/
@@ -58,7 +58,7 @@
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<opencsv.version>4.1</opencsv.version>
<opencsv.version>5.8</opencsv.version>
<spring-core.version>5.3.13</spring-core.version>
<apache-commons-lang3.version>3.12.0</apache-commons-lang3.version>
<apache-commons-text.version>1.10.0</apache-commons-text.version>
@@ -12,6 +12,7 @@ import com.opencsv.CSVParser;
import com.opencsv.CSVParserBuilder;
import com.opencsv.CSVReader;
import com.opencsv.CSVReaderBuilder;
import com.opencsv.exceptions.CsvException;
public class SplitCommaSeparatedString {
@@ -50,7 +51,7 @@ public class SplitCommaSeparatedString {
return splitter.splitToList(input);
}
public static List<String[]> splitMultiLineWithOpenCSV(String input) throws IOException {
public static List<String[]> splitMultiLineWithOpenCSV(String input) throws IOException, CsvException {
CSVParser parser = new CSVParserBuilder().withSeparator(',')
.build();
@@ -14,6 +14,8 @@ import java.util.List;
import org.junit.Test;
import com.opencsv.exceptions.CsvException;
public class SplitCommaSeparatedStringUnitTest {
@Test
@@ -27,7 +29,7 @@ public class SplitCommaSeparatedStringUnitTest {
}
@Test
public void givenMultiLineInput_whenParsing_shouldIgnoreCommasInsideDoubleQuotes() throws IOException {
public void givenMultiLineInput_whenParsing_shouldIgnoreCommasInsideDoubleQuotes() throws IOException, CsvException {
String input = "baeldung,tutorial,splitting,text,\"ignoring this comma,\"" + System.lineSeparator()
+ "splitting,a,regular,line,no double quotes";
@@ -0,0 +1,34 @@
package com.baeldung.mutablestrings;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.CoderResult;
public class CharsetUsageExample {
public ByteBuffer encodeString(String inputString) {
Charset charset = Charset.forName("UTF-8");
CharsetEncoder encoder = charset.newEncoder();
CharBuffer charBuffer = CharBuffer.wrap(inputString);
ByteBuffer byteBuffer = ByteBuffer.allocate(50);
encoder.encode(charBuffer, byteBuffer, true); // true indicates the end of input
byteBuffer.flip();
return byteBuffer;
}
public String decodeString(ByteBuffer byteBuffer) {
Charset charset = Charset.forName("UTF-8");
CharsetDecoder decoder = charset.newDecoder();
CharBuffer decodedCharBuffer = CharBuffer.allocate(50);
decoder.decode(byteBuffer, decodedCharBuffer, true);
decodedCharBuffer.flip();
return decodedCharBuffer.toString();
}
}
@@ -0,0 +1,65 @@
package com.baeldung.mutablestrings;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.CoderResult;
import java.util.concurrent.atomic.AtomicReference;
public class MutableStringUsingCharset {
private final AtomicReference<CharBuffer> cbRef = new AtomicReference<>();
private final Charset myCharset = new Charset("mycharset", null) {
@Override
public boolean contains(Charset cs) {
return false;
}
@Override
public CharsetDecoder newDecoder() {
return new CharsetDecoder(this, 1.0f, 1.0f) {
@Override
protected CoderResult decodeLoop(ByteBuffer in, CharBuffer out) {
cbRef.set(out);
while (in.remaining() > 0) {
out.append((char) in.get());
}
return CoderResult.UNDERFLOW;
}
};
}
@Override
public CharsetEncoder newEncoder() {
CharsetEncoder cd = new CharsetEncoder(this, 1.0f, 1.0f) {
@Override
protected CoderResult encodeLoop(CharBuffer in, ByteBuffer out) {
while (in.hasRemaining()) {
if (!out.hasRemaining()) {
return CoderResult.OVERFLOW;
}
char currentChar = in.get();
if (currentChar > 127) {
return CoderResult.unmappableForLength(1);
}
out.put((byte) currentChar);
}
return CoderResult.UNDERFLOW;
}
};
return cd;
}
};
public String createModifiableString(String s) {
return new String(s.getBytes(), myCharset);
}
public void modifyString() {
CharBuffer cb = cbRef.get();
cb.position(0);
cb.put("xyz");
}
}
@@ -0,0 +1,24 @@
package com.baeldung.mutablestrings;
import java.lang.reflect.Field;
import java.nio.charset.Charset;
import com.google.errorprone.annotations.DoNotCall;
public class MutableStrings {
/**
* This involves using Reflection to change String fields and it is not encouraged to use this in programs.
* @throws NoSuchFieldException
* @throws IllegalAccessException
*/
@DoNotCall
public void mutableUsingReflection() throws NoSuchFieldException, IllegalAccessException {
String myString = "Hello World";
String otherString = new String("Hello World");
Field f = String.class.getDeclaredField("value");
f.setAccessible(true);
f.set(myString, "Hi World".toCharArray());
System.out.println(otherString);
}
}
@@ -0,0 +1,30 @@
package com.baeldung.unicode;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.lang3.StringUtils;
public class UnicodeLetterChecker {
public boolean characterClassCheck(String input) {
for (char c : input.toCharArray()) {
if (!Character.isLetter(c)) {
return false;
}
}
return true;
}
public boolean regexCheck(String input) {
Pattern pattern = Pattern.compile("^\\p{L}+$");
Matcher matcher = pattern.matcher(input);
return matcher.matches();
}
public boolean isAlphaCheck(String input) {
return StringUtils.isAlpha(input);
}
public boolean StreamsCheck(String input) {
return input.codePoints().allMatch(Character::isLetter);
}
}
@@ -0,0 +1,17 @@
package com.baeldung.mutablestring;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import com.baeldung.mutablestrings.CharsetUsageExample;
public class CharsetUsageUnitTest {
@Test
public void givenCharset_whenStringIsEncodedAndDecoded_thenGivesCorrectResult() {
CharsetUsageExample ch = new CharsetUsageExample();
String inputString = "hello दुनिया";
String result = ch.decodeString(ch.encodeString(inputString));
Assertions.assertEquals(inputString, result);
}
}
@@ -0,0 +1,24 @@
package com.baeldung.mutablestring;
import org.junit.Assert;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import com.baeldung.mutablestrings.MutableStringUsingCharset;
public class MutableStringUsingCharsetUnitTest {
@Test
@Disabled
/**
* This test is disabled as it works well for Java 8 and below
*/
public void givenCustomCharSet_whenStringUpdated_StringGetsMutated() throws Exception {
MutableStringUsingCharset ms = new MutableStringUsingCharset();
String s = ms.createModifiableString("Hello");
Assert.assertEquals("Hello", s);
ms.modifyString();
Assert.assertEquals("something", s);
}
}
@@ -0,0 +1,38 @@
package com.baeldung.unicode;
import org.junit.Test;
import static org.junit.Assert.assertTrue;
public class UnicodeLetterCheckerUnitTest {
@Test
public void givenString_whenUsingIsLetter_thenReturnTrue() {
UnicodeLetterChecker checker = new UnicodeLetterChecker();
boolean isUnicodeLetter = checker.characterClassCheck("HelloWorld");
assertTrue(isUnicodeLetter);
}
@Test
public void givenString_whenUsingRegex_thenReturnTrue() {
UnicodeLetterChecker checker = new UnicodeLetterChecker();
boolean isUnicodeLetter = checker.regexCheck("HelloWorld");
assertTrue(isUnicodeLetter);
}
@Test
public void givenString_whenUsingIsAlpha_thenReturnTrue() {
UnicodeLetterChecker checker = new UnicodeLetterChecker();
boolean isUnicodeLetter = checker.isAlphaCheck("HelloWorld");
assertTrue(isUnicodeLetter);
}
@Test
public void givenString_whenUsingStreams_thenReturnTrue() {
UnicodeLetterChecker checker = new UnicodeLetterChecker();
boolean isUnicodeLetter = checker.StreamsCheck("HelloWorld");
assertTrue(isUnicodeLetter);
}
}
@@ -14,3 +14,5 @@ Listed here there are only those articles that does not fit into other core-java
- [Java String Interview Questions and Answers](https://www.baeldung.com/java-string-interview-questions)
- [Java Multi-line String](https://www.baeldung.com/java-multiline-string)
- [Reuse StringBuilder for Efficiency](https://www.baeldung.com/java-reuse-stringbuilder-for-efficiency)
- [How to Iterate Over the String Characters in Java](https://www.baeldung.com/java-iterate-string-characters)
- [Passing Strings by Reference in Java](https://www.baeldung.com/java-method-pass-string-reference)
@@ -0,0 +1,42 @@
package com.baeldung.stringIterator;
import java.text.*;
import java.util.*;
public class StringIterator {
public static String javaCharArray(String str){
StringBuilder result = new StringBuilder();
for (char c : str.toCharArray()) {
result.append(c);
}
return result.toString();
}
public static String javaforLoop(String str) {
StringBuilder result = new StringBuilder();
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
result.append(c);
}
return result.toString();
}
public static String java8forEach(String str){
StringBuilder result = new StringBuilder();
str.chars().forEach(name -> {
result.append((char) name);
});
return result.toString();
}
public static String javaCharacterIterator(String str){
StringBuilder result = new StringBuilder();
CharacterIterator it = new StringCharacterIterator(str);
while (it.current() != CharacterIterator.DONE) {
result.append(it.current());
it.next();
}
return result.toString();
}
}
@@ -0,0 +1,39 @@
package com.baeldung.stringIterator;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
public class StringIteratorTest {
@Test
public void whenUseCharArrayMethod_thenIterate() {
String input = "Hello, Baeldung!";
String expectedOutput = "Hello, Baeldung!";
String result = StringIterator.javaCharArray(input);
assertEquals(expectedOutput, result);
}
@Test
public void whenUseJavaForLoop_thenIterate() {
String input = "Hello, Baeldung!";
String expectedOutput = "Hello, Baeldung!";
String result = StringIterator.javaForLoop(input);
assertEquals(expectedOutput, result);
}
@Test
public void whenUseForEachMethod_thenIterate() {
String input = "Hello, Baeldung!";
String expectedOutput = "Hello, Baeldung!";
String result = StringIterator.java8ForEach(input);
assertEquals(expectedOutput, result);
}
@Test
public void whenUseCharacterIterator_thenIterate() {
String input = "Hello, Baeldung!";
String expectedOutput = "Hello, Baeldung!";
String result = StringIterator.javaCharacterIterator(input);
assertEquals(expectedOutput, result);
}
}
+11
View File
@@ -0,0 +1,11 @@
## JNI
This module contains articles about the Java Native Interface (JNI).
### Relevant Articles:
- [Guide to JNI (Java Native Interface)](https://www.baeldung.com/jni)
- [Using JNA to Access Native Dynamic Libraries](https://www.baeldung.com/java-jna-dynamic-libraries)
- [Check if a Java Program Is Running in 64-Bit or 32-Bit JVM](https://www.baeldung.com/java-detect-jvm-64-or-32-bit)
- [How to use JNIs RegisterNatives() method?](https://www.baeldung.com/jni-registernatives)
- [Custom DLL Load Fixing the “java.lang.UnsatisfiedLinkError” Error](https://www.baeldung.com/java-custom-dll-load-fixing-the-java-lang-unsatisfiedlinkerror-error)
+40
View File
@@ -0,0 +1,40 @@
<?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>java-native</artifactId>
<name>java-native</name>
<parent>
<groupId>com.baeldung.core-java-modules</groupId>
<artifactId>core-java-modules</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna-platform</artifactId>
<version>${jna.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<!-- we don't want to reuse JVMs here ! -->
<reuseForks>false</reuseForks>
</configuration>
</plugin>
</plugins>
</build>
<properties>
<jna.version>5.6.0</jna.version>
</properties>
</project>
@@ -0,0 +1,48 @@
#include "com_baeldung_jni_ExampleObjectsJNI.h"
#include <iostream>
/*
* Class: com_baeldung_jni_ExampleObjectsJNI
* Method: createUser
* Signature: (Ljava/lang/String;D)Lcom/baeldung/jni/UserData;
*/
JNIEXPORT jobject JNICALL Java_com_baeldung_jni_ExampleObjectsJNI_createUser
(JNIEnv *env, jobject thisObject, jstring name, jdouble balance){
// Create the object of the class UserData
jclass userDataClass = env->FindClass("com/baeldung/jni/UserData");
jobject newUserData = env->AllocObject(userDataClass);
// Get UserData fields to set
jfieldID nameField = env->GetFieldID(userDataClass , "name", "Ljava/lang/String;");
jfieldID balanceField = env->GetFieldID(userDataClass , "balance", "D");
// Set the values of the new object
env->SetObjectField(newUserData, nameField, name);
env->SetDoubleField(newUserData, balanceField, balance);
// Return the created object
return newUserData;
}
/*
* Class: com_baeldung_jni_ExampleObjectsJNI
* Method: printUserData
* Signature: (Lcom/baeldung/jni/UserData;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_baeldung_jni_ExampleObjectsJNI_printUserData
(JNIEnv *env, jobject thisObject, jobject userData){
// Find the class method id
jclass userDataClass = env->GetObjectClass(userData);
jmethodID methodId = env->GetMethodID(userDataClass, "getUserInfo", "()Ljava/lang/String;");
// Call the object method and get the result
jstring result = (jstring)env->CallObjectMethod(userData, methodId);
// Print the result
std::cout << "C++: User data is: " << env->GetStringUTFChars(result, NULL) << std::endl;
return result;
}
@@ -0,0 +1,29 @@
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_baeldung_jni_ExampleObjectsJNI */
#ifndef _Included_com_baeldung_jni_ExampleObjectsJNI
#define _Included_com_baeldung_jni_ExampleObjectsJNI
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_baeldung_jni_ExampleObjectsJNI
* Method: createUser
* Signature: (Ljava/lang/String;D)Lcom/baeldung/jni/UserData;
*/
JNIEXPORT jobject JNICALL Java_com_baeldung_jni_ExampleObjectsJNI_createUser
(JNIEnv *, jobject, jstring, jdouble);
/*
* Class: com_baeldung_jni_ExampleObjectsJNI
* Method: printUserData
* Signature: (Lcom/baeldung/jni/UserData;)V
*/
JNIEXPORT jstring JNICALL Java_com_baeldung_jni_ExampleObjectsJNI_printUserData
(JNIEnv *, jobject, jobject);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,34 @@
#include "com_baeldung_jni_ExampleParametersJNI.h"
#include <iostream>
#include <string>
/*
* Class: com_baeldung_jni_ExampleParametersJNI
* Method: sumIntegers
* Signature: (II)J
*/
JNIEXPORT jlong JNICALL Java_com_baeldung_jni_ExampleParametersJNI_sumIntegers (JNIEnv* env, jobject thisObject, jint first, jint second){
std::cout << "C++: The numbers received are : " << first << " and " << second << std::endl;
return (long)first + (long)second;
}
/*
* Class: com_baeldung_jni_ExampleParametersJNI
* Method: sayHelloToMe
* Signature: (Ljava/lang/String;Z)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_baeldung_jni_ExampleParametersJNI_sayHelloToMe (JNIEnv* env, jobject thisObject, jstring name, jboolean isFemale){
const char* nameCharPointer = env->GetStringUTFChars(name, NULL);
std::cout << "C++: The string received is: " << nameCharPointer << std::endl;
std::string title;
if(isFemale){
title = "Ms. ";
}
else{
title = "Mr. ";
}
std::string fullName = title + nameCharPointer;
return env->NewStringUTF(fullName.c_str());
}
@@ -0,0 +1,29 @@
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_baeldung_jni_ExampleParametersJNI */
#ifndef _Included_com_baeldung_jni_ExampleParametersJNI
#define _Included_com_baeldung_jni_ExampleParametersJNI
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_baeldung_jni_ExampleParametersJNI
* Method: sumIntegers
* Signature: (II)J
*/
JNIEXPORT jlong JNICALL Java_com_baeldung_jni_ExampleParametersJNI_sumIntegers
(JNIEnv*, jobject, jint, jint);
/*
* Class: com_baeldung_jni_ExampleParametersJNI
* Method: sayHelloToMe
* Signature: (Ljava/lang/String;Z)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_baeldung_jni_ExampleParametersJNI_sayHelloToMe
(JNIEnv*, jobject, jstring, jboolean);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,13 @@
#include "com_baeldung_jni_HelloWorldJNI.h"
#include <iostream>
/*
* Class: com_baeldung_jni_HelloWorldJNI
* Method: sayHello
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_baeldung_jni_HelloWorldJNI_sayHello (JNIEnv* env, jobject thisObject) {
std::string hello = "Hello from C++ !!";
std::cout << hello << std::endl;
return env->NewStringUTF(hello.c_str());
}
@@ -0,0 +1,21 @@
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_baeldung_jni_HelloWorldJNI */
#ifndef _Included_com_baeldung_jni_HelloWorldJNI
#define _Included_com_baeldung_jni_HelloWorldJNI
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_baeldung_jni_HelloWorldJNI
* Method: sayHello
* Signature: ()V
*/
JNIEXPORT jstring JNICALL Java_com_baeldung_jni_HelloWorldJNI_sayHello
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,21 @@
#include "com_baeldung_jni_RegisterNativesHelloWorldJNI.h"
#include <iostream>
JNIEXPORT jstring JNICALL hello (JNIEnv* env, jobject thisObject) {
std::string hello = "Hello from registered native C++ !!";
std::cout << hello << std::endl;
return env->NewStringUTF(hello.c_str());
}
static JNINativeMethod methods[] = {
{"sayHello", "()Ljava/lang/String;", (void*) &hello },
};
JNIEXPORT void JNICALL Java_com_baeldung_jni_RegisterNativesHelloWorldJNI_register (JNIEnv* env, jobject thsObject) {
jclass clazz = env->FindClass("com/baeldung/jni/RegisterNativesHelloWorldJNI");
(env)->RegisterNatives(clazz, methods, sizeof(methods)/sizeof(methods[0]));
}
@@ -0,0 +1,29 @@
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_baeldung_jni_RegisterNativesHelloWorldJNI */
#ifndef _Included_com_baeldung_jni_RegisterNativesHelloWorldJNI
#define _Included_com_baeldung_jni_RegisterNativesHelloWorldJNI
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_baeldung_jni_RegisterNativesHelloWorldJNI
* Method: sayHello
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_baeldung_jni_RegisterNativesHelloWorldJNI_sayHello
(JNIEnv *, jobject);
/*
* Class: com_baeldung_jni_RegisterNativesHelloWorldJNI
* Method: register
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_baeldung_jni_RegisterNativesHelloWorldJNI_register
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,6 @@
REM Create the header with javac -h . ClassName.java
REM Remember to set your JAVA_HOME env var
g++ -c -I%JAVA_HOME%\include -I%JAVA_HOME%\include\win32 com_baeldung_jni_HelloWorldJNI.cpp -o com_baeldung_jni_HelloWorldJNI.o
g++ -c -I%JAVA_HOME%\include -I%JAVA_HOME%\include\win32 com_baeldung_jni_ExampleParametersJNI.cpp -o com_baeldung_jni_ExampleParametersJNI.o
g++ -c -I%JAVA_HOME%\include -I%JAVA_HOME%\include\win32 com_baeldung_jni_ExampleObjectsJNI.cpp -o com_baeldung_jni_ExampleObjectsJNI.o
g++ -shared -o ..\..\..\native\win32\native.dll com_baeldung_jni_HelloWorldJNI.o com_baeldung_jni_ExampleParametersJNI.o com_baeldung_jni_ExampleObjectsJNI.o -Wl,--add-stdcall-alias
@@ -0,0 +1,7 @@
# Create the header with javac -h . ClassName.java
# Remember to set your JAVA_HOME env var
g++ -c -fPIC -I${JAVA_HOME}/include -I${JAVA_HOME}/include/linux com_baeldung_jni_HelloWorldJNI.cpp -o com_baeldung_jni_HelloWorldJNI.o
g++ -c -fPIC -I${JAVA_HOME}/include -I${JAVA_HOME}/include/linux com_baeldung_jni_ExampleParametersJNI.cpp -o com_baeldung_jni_ExampleParametersJNI.o
g++ -c -fPIC -I${JAVA_HOME}/include -I${JAVA_HOME}/include/linux com_baeldung_jni_ExampleObjectsJNI.cpp -o com_baeldung_jni_ExampleObjectsJNI.o
g++ -shared -fPIC -o ../../../native/linux_x86_64/libnative.so com_baeldung_jni_HelloWorldJNI.o com_baeldung_jni_ExampleParametersJNI.o com_baeldung_jni_ExampleObjectsJNI.o -lc
# Don't forget to set java.library.path to point to the folder where you have the libnative you're loading.
@@ -0,0 +1,7 @@
# Create the header with javac -h . ClassName.java
# Remember to set your JAVA_HOME env var
g++ -c -fPIC -I${JAVA_HOME}/include -I${JAVA_HOME}/include/darwin com_baeldung_jni_HelloWorldJNI.cpp -o com_baeldung_jni_HelloWorldJNI.o
g++ -c -fPIC -I${JAVA_HOME}/include -I${JAVA_HOME}/include/darwin com_baeldung_jni_ExampleParametersJNI.cpp -o com_baeldung_jni_ExampleParametersJNI.o
g++ -c -fPIC -I${JAVA_HOME}/include -I${JAVA_HOME}/include/darwin com_baeldung_jni_ExampleObjectsJNI.cpp -o com_baeldung_jni_ExampleObjectsJNI.o
g++ -c -fPIC -I${JAVA_HOME}/include -I${JAVA_HOME}/include/darwin com_baeldung_jni_RegisterNativesHelloWorldJNI.cpp -o com_baeldung_jni_RegisterNativesHelloWorldJNI.o
g++ -dynamiclib -o ../../../native/macos/libnative.dylib com_baeldung_jni_HelloWorldJNI.o com_baeldung_jni_ExampleParametersJNI.o com_baeldung_jni_ExampleObjectsJNI.o com_baeldung_jni_RegisterNativesHelloWorldJNI.o -lc
@@ -0,0 +1,13 @@
#include "com_baeldung_unsatisfiedlink_JniUnsatisfiedLink.h"
#include <iostream>
/*
* Class: com_baeldung_unsatisfiedlink_JniUnsatisfiedLink
* Method: test
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_baeldung_unsatisfiedlink_JniUnsatisfiedLink_test (JNIEnv* env, jobject thisObject) {
std::string test = "Test OK";
std::cout << test << std::endl;
return env->NewStringUTF(test.c_str());
}
@@ -0,0 +1,21 @@
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_baeldung_unsatisfiedlink_JniUnsatisfiedLink */
#ifndef _Included_com_baeldung_unsatisfiedlink_JniUnsatisfiedLink
#define _Included_com_baeldung_unsatisfiedlink_JniUnsatisfiedLink
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_baeldung_unsatisfiedlink_JniUnsatisfiedLink
* Method: test
* Signature: ()V
*/
JNIEXPORT jstring JNICALL Java_com_baeldung_unsatisfiedlink_JniUnsatisfiedLink_test
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,22 @@
#!/bin/bash
# Create the header with javac -h . ClassName.java
# Remember to set your JAVA_HOME env var
# Don't forget to set java.library.path to point to the folder where you have the lib you're loading.
MYSELF="$(readlink -f "$0")"
MYDIR="${MYSELF%/*}"
cd "$MYDIR"
class_name=com_baeldung_unsatisfiedlink_JniUnsatisfiedLink
lib_name=test
g++ -c -fPIC -I"${JAVA_HOME}/include" -I"${JAVA_HOME}/include/linux" ${class_name}.cpp -o ${class_name}.o
g++ -shared -fPIC -o lib${lib_name}.so ${class_name}.o -lc
# 32-bit version
g++ -m32 -c -fPIC -I"${JAVA_HOME}/include" -I"${JAVA_HOME}/include/linux" ${class_name}.cpp -o ${class_name}32.o
g++ -m32 -shared -fPIC -o lib${lib_name}32.so ${class_name}32.o -lc
# dummy version
touch ${class_name}-dummy.o
ls lib*
@@ -0,0 +1,10 @@
package com.baeldung.jna;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Platform;
public interface CMath extends Library {
CMath INSTANCE = Native.load(Platform.isWindows() ? "msvcrt" : "c", CMath.class);
double cosh(double value);
}
@@ -0,0 +1,8 @@
package com.baeldung.jna;
public class Main {
public static void main(String[] args) {
}
}
@@ -0,0 +1,46 @@
package com.baeldung.jna;
import java.util.Collections;
import java.util.Map;
import com.sun.jna.FunctionMapper;
import com.sun.jna.LastErrorException;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.NativeLong;
import com.sun.jna.Platform;
import com.sun.jna.Structure;
import com.sun.jna.Structure.FieldOrder;
public interface NativeFS extends Library {
FunctionMapper mapper = (library,method) -> {
if (Platform.isWindows()) {
return "_" + method.getName();
}
else {
return "__x" + method.getName(); // On Linux, stat is actually _xstat
}
};
public NativeFS INSTANCE = Native.load(Platform.isWindows() ? "msvcrt" : "c",
NativeFS.class,
Collections.singletonMap(Library.OPTION_FUNCTION_MAPPER, mapper));
int stat(String path, Stat stat) throws LastErrorException;
@FieldOrder({"st_dev","st_ino","st_mode","st_nlink","st_uid","st_gid","st_rdev","st_size","st_atime","st_mtime","st_ctime"})
public class Stat extends Structure {
public int st_dev;
public int st_ino;
public short st_mode;
public short st_nlink;
public short st_uid;
public short st_gid;
public int st_rdev;
public NativeLong st_size;
public NativeLong st_atime;
public NativeLong st_mtime;
public NativeLong st_ctime;
}
}
@@ -0,0 +1,17 @@
package com.baeldung.jna;
import com.sun.jna.LastErrorException;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Platform;
import com.sun.jna.Pointer;
public interface StdC extends Library {
StdC INSTANCE = Native.load(Platform.isWindows() ? "msvcrt" : "c", StdC.class );
Pointer malloc(long n);
void free(Pointer p);
Pointer memset(Pointer p, int c, long n);
int open(String path, int flags) throws LastErrorException;
int close(int fd) throws LastErrorException;
}
@@ -0,0 +1,19 @@
package com.baeldung.jni;
public class ExampleObjectsJNI {
static {
System.loadLibrary("native");
}
public static void main(String[] args) {
ExampleObjectsJNI instance = new ExampleObjectsJNI();
UserData newUser = instance.createUser("John Doe", 450.67);
instance.printUserData(newUser);
}
public native UserData createUser(String name, double balance);
public native String printUserData(UserData user);
}
@@ -0,0 +1,20 @@
package com.baeldung.jni;
public class ExampleParametersJNI {
static {
System.loadLibrary("native");
}
public static void main(String[] args) {
System.out.println("Java: My full name: " + new ExampleParametersJNI().sayHelloToMe("Martin", false));
long sumFromNative = new ExampleParametersJNI().sumIntegers(456, 44);
System.out.println("Java: The sum coming from native code is: " + sumFromNative);
}
// Declare another method sumIntegers that receives two integers and return a long with the sum
public native long sumIntegers(int first, int second);
// Declare another method sayHelloToMe that receives the name and gender and returns the proper salutation
public native String sayHelloToMe(String name, boolean isFemale);
}
@@ -0,0 +1,15 @@
package com.baeldung.jni;
public class HelloWorldJNI {
static {
System.loadLibrary("native");
}
public static void main(String[] args) {
new HelloWorldJNI().sayHello();
}
// Declare a native method sayHello() that receives no arguments and returns void
public native String sayHello();
}
@@ -0,0 +1,18 @@
package com.baeldung.jni;
public class RegisterNativesHelloWorldJNI {
static {
System.loadLibrary("native");
}
public static void main(String[] args) {
RegisterNativesHelloWorldJNI helloWorldJNI = new RegisterNativesHelloWorldJNI();
helloWorldJNI.register();
helloWorldJNI.sayHello();
}
public native String sayHello();
public native void register();
}
@@ -0,0 +1,11 @@
package com.baeldung.jni;
public class UserData {
public String name;
public double balance;
public String getUserInfo() {
return "[name]=" + name + ", [balance]=" + balance;
}
}
@@ -0,0 +1,24 @@
package com.baeldung.jvmbitversion;
import com.sun.jna.Platform;
public class JVMBitVersion {
public String getUsingSystemClass() {
return System.getProperty("sun.arch.data.model") + "-bit";
}
public String getUsingNativeClass() {
if (com.sun.jna.Native.POINTER_SIZE == 8) {
return "64-bit";
} else if (com.sun.jna.Native.POINTER_SIZE == 4) {
return "32-bit";
} else
return "unknown";
}
public boolean getUsingPlatformClass() {
return (Platform.is64Bit());
}
}
@@ -0,0 +1,15 @@
package com.baeldung.unsatisfiedlink;
public class JniUnsatisfiedLink {
public static final String LIB_NAME = "test";
public static void main(String[] args) {
System.loadLibrary(LIB_NAME);
new JniUnsatisfiedLink().test();
}
public native String test();
public native String nonexistentDllMethod();
}
@@ -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>
@@ -0,0 +1,3 @@
grant {
permission java.lang.RuntimePermission "loadLibrary.test";
};
@@ -0,0 +1,18 @@
package com.baeldung.jna;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;
import com.sun.jna.Native;
import com.sun.jna.Platform;
class CMathUnitTest {
@Test
void whenCallNative_thenSuccess() {
CMath lib = Native.load(Platform.isWindows() ? "msvcrt" : "c", CMath.class);
double result = lib.cosh(0);
assertEquals(1.0,result);
}
}
@@ -0,0 +1,38 @@
package com.baeldung.jna;
import static org.junit.Assert.fail;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import org.junit.jupiter.api.Test;
import com.baeldung.jna.NativeFS.Stat;
import com.sun.jna.LastErrorException;
import com.sun.jna.Platform;
public class NativeFSUnitTest {
@Test
public void whenCallNative_thenSuccess() throws IOException {
NativeFS lib = NativeFS.INSTANCE;
File f = Files.createTempFile("junit", ".bin").toFile();
f.deleteOnExit();
Stat stat = new Stat();
try {
if (Platform.isWindows()) {
int rc = lib.stat(f.getAbsolutePath(), stat);
assertEquals(0, rc);
assertEquals(0,stat.st_size.longValue());
}
}
catch(LastErrorException error) {
fail("stat failed: error code=" + error.getErrorCode());
}
}
}
@@ -0,0 +1,47 @@
package com.baeldung.jna;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.BeforeClass;
import org.junit.jupiter.api.Test;
import com.sun.jna.Native;
import com.sun.jna.Platform;
import com.sun.jna.Pointer;
class StdCUnitTest {
@BeforeClass
public static void setupProtectedMode() {
Native.setProtected(true);
}
@Test
public void whenMalloc_thenSuccess() {
StdC lib = StdC.INSTANCE;
Pointer p = lib.malloc(1024);
p.setMemory(0l, 1024l, (byte) 0);
lib.free(p);
}
@Test
public void whenAccessViolation_thenShouldThrowError() {
// Running this test on Linux requires additional setup using libjsig.so
// Details here: http://java-native-access.github.io/jna/5.6.0/javadoc/overview-summary.html#crash-protection
// IMPORTANT NOTICE: Code for illustration purposes only. DON'T DO THIS IN YOUR OWN CODE
if ( Platform.isWindows()) {
Error e = null;
Pointer p = new Pointer(0l);
try {
p.setMemory(0, 100*1024, (byte) 0);
}
catch(Error err) {
e = err;
}
assertNotNull(e, "Should throw Error");
}
}
}
@@ -0,0 +1,58 @@
package com.baeldung.jni;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import org.junit.Before;
import org.junit.Test;
public class JNINativeManualTest {
@Before
public void setup() {
System.loadLibrary("native");
}
@Test
public void whenNativeHelloWorld_thenOutputIsAsExpected() {
HelloWorldJNI helloWorld = new HelloWorldJNI();
String helloFromNative = helloWorld.sayHello();
assertTrue(!helloFromNative.isEmpty() && helloFromNative.equals("Hello from C++ !!"));
}
@Test
public void whenSumNative_thenResultIsArithmeticallyCorrect() {
ExampleParametersJNI parametersNativeMethods = new ExampleParametersJNI();
assertTrue(parametersNativeMethods.sumIntegers(200, 400) == 600L);
}
@Test
public void whenSayingNativeHelloToMe_thenResultIsAsExpected() {
ExampleParametersJNI parametersNativeMethods = new ExampleParametersJNI();
assertEquals(parametersNativeMethods.sayHelloToMe("Orange", true), "Ms. Orange");
}
@Test
public void whenCreatingNativeObject_thenObjectIsNotNullAndHasCorrectData() {
String name = "Iker Casillas";
double balance = 2378.78;
ExampleObjectsJNI objectsNativeMethods = new ExampleObjectsJNI();
UserData userFromNative = objectsNativeMethods.createUser(name, balance);
assertNotNull(userFromNative);
assertEquals(userFromNative.name, name);
assertTrue(userFromNative.balance == balance);
}
@Test
public void whenNativeCallingObjectMethod_thenResultIsAsExpected() {
String name = "Sergio Ramos";
double balance = 666.77;
ExampleObjectsJNI objectsNativeMethods = new ExampleObjectsJNI();
UserData userData = new UserData();
userData.name = name;
userData.balance = balance;
assertEquals(objectsNativeMethods.printUserData(userData), "[name]=" + name + ", [balance]=" + balance);
}
}
@@ -0,0 +1,26 @@
package com.baeldung.jni.registernatives;
import com.baeldung.jni.RegisterNativesHelloWorldJNI;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
public class JNIRegisterNativesManualTest {
@Before
public void setup() {
System.loadLibrary("native");
}
@Test
public void whenRegisteredNativeHelloWorld_thenOutputIsAsExpected() {
RegisterNativesHelloWorldJNI helloWorld = new RegisterNativesHelloWorldJNI();
helloWorld.register();
String helloFromNative = helloWorld.sayHello();
assertNotNull(helloFromNative);
assertTrue(helloFromNative.equals("Hello from registered native C++ !!"));
}
}
@@ -0,0 +1,45 @@
package com.baeldung.jvmbitversion;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.Before;
import org.junit.Test;
import com.sun.jna.Platform;
public class JVMBitVersionUnitTest {
private JVMBitVersion jvmVersion;
@Before
public void setup() {
jvmVersion = new JVMBitVersion();
}
@Test
public void whenUsingSystemClass_thenOutputIsAsExpected() {
if ("64".equals(System.getProperty("sun.arch.data.model"))) {
assertEquals("64-bit", jvmVersion.getUsingSystemClass());
} else if ("32".equals(System.getProperty("sun.arch.data.model"))) {
assertEquals("32-bit", jvmVersion.getUsingSystemClass());
}
}
@Test
public void whenUsingNativeClass_thenResultIsAsExpected() {
if (com.sun.jna.Native.POINTER_SIZE == 8) {
assertEquals("64-bit", jvmVersion.getUsingNativeClass());
} else if (com.sun.jna.Native.POINTER_SIZE == 4) {
assertEquals("32-bit", jvmVersion.getUsingNativeClass());
}
}
@Test
public void whenUsingPlatformClass_thenResultIsAsExpected() {
if (Platform.is64Bit() == Boolean.TRUE) {
assertEquals(Boolean.TRUE, jvmVersion.getUsingPlatformClass());
} else if (com.sun.jna.Native.POINTER_SIZE == 4) {
assertEquals(Boolean.FALSE, jvmVersion.getUsingPlatformClass());
}
}
}
@@ -0,0 +1,105 @@
package com.baeldung.unsatisfiedlink;
import static com.baeldung.unsatisfiedlink.JniUnsatisfiedLink.LIB_NAME;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.io.File;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
public class JniUnsatisfiedLinkManualTest {
static String osLibPrefix = "";
static String osLibSuffix = "";
@BeforeAll
static void setup() {
String osName = System.getProperty("os.name")
.toLowerCase();
if (osName.contains("win")) {
osLibSuffix = ".dll";
} else if (osName.contains("nix") || osName.contains("nux") || osName.contains("mac")) {
osLibPrefix = "lib";
osLibSuffix = ".so";
if (osName.contains("mac")) {
osLibPrefix = "lib";
osLibSuffix = ".dylib";
}
} else {
throw new UnsupportedOperationException("Unsupported operating system: " + osName);
}
}
@Test
public void whenCorrectLibName_thenLibLoaded() {
assertDoesNotThrow(() -> {
System.loadLibrary(LIB_NAME);
new JniUnsatisfiedLink().test();
});
}
@Test
public void whenIncorrectLibName_thenLibNotFound() {
String libName = osLibPrefix + LIB_NAME + osLibSuffix;
Error error = assertThrows(UnsatisfiedLinkError.class, () -> System.loadLibrary(libName));
assertEquals(String.format("no %s in java.library.path", libName), error.getMessage());
}
@Test
public void whenLoadLibraryContainsPathSeparator_thenErrorThrown() {
String libName = "/" + LIB_NAME;
Error error = assertThrows(UnsatisfiedLinkError.class, () -> System.loadLibrary(libName));
assertEquals(String.format("Directory separator should not appear in library name: %s", libName), error.getMessage());
}
@Test
public void whenLoadWithoutAbsolutePath_thenErrorThrown() {
String libName = LIB_NAME;
Error error = assertThrows(UnsatisfiedLinkError.class, () -> System.load(libName));
assertEquals(String.format("Expecting an absolute path of the library: %s", libName), error.getMessage());
}
@Test
public void whenUnlinkedMethod_thenErrorThrown() {
System.loadLibrary(LIB_NAME);
Error error = assertThrows(UnsatisfiedLinkError.class, () -> new JniUnsatisfiedLink().nonexistentDllMethod());
assertTrue(error.getMessage()
.contains("JniUnsatisfiedLink.nonexistentDllMethod"));
}
@Test
public void whenIncompatibleArchitecture_thenErrorThrown() {
Error error = assertThrows(UnsatisfiedLinkError.class, () -> System.loadLibrary(LIB_NAME + "32"));
assertTrue(error.getMessage()
.contains("wrong ELF class: ELFCLASS32"));
}
@Test
public void whenCorruptedFile_thenErrorThrown() {
String libPath = System.getProperty("java.library.path");
assertNotNull(libPath);
String dummyLib = LIB_NAME + "-dummy";
assertTrue(new File(libPath, osLibPrefix + dummyLib + osLibSuffix).isFile());
Error error = assertThrows(UnsatisfiedLinkError.class, () -> System.loadLibrary(dummyLib));
assertTrue(error.getMessage()
.contains("file too short"));
}
}
+1
View File
@@ -199,6 +199,7 @@
<module>core-java-date-operations-1</module>
<!--<module>core-java-datetime-conversion</module>--> <!--JAVA-25433-->
<module>core-java-httpclient</module>
<module>java-native</module>
</modules>
<dependencyManagement>