Merge remote-tracking branch 'upstream/master' into feature/BAEL-7062-GetIndex

This commit is contained in:
Niket Agrawal
2023-12-14 19:56:27 +05:30
2179 changed files with 27446 additions and 6797 deletions
@@ -3,3 +3,8 @@
- [Working With Empty Stream in Java](https://www.baeldung.com/java-empty-stream)
- [Aggregate Runtime Exceptions in Java Streams](https://www.baeldung.com/java-streams-aggregate-exceptions)
- [Streams vs. Loops in Java](https://www.baeldung.com/java-streams-vs-loops)
- [Partition a Stream in Java](https://www.baeldung.com/java-partition-stream)
- [Taking Every N-th Element from Finite and Infinite Streams in Java](https://www.baeldung.com/java-nth-element-finite-infinite-streams)
- [Modifying Objects Within Stream While Iterating](https://www.baeldung.com/java-stream-modify-objects-during-iteration)
- [Convert a Stream into a Map or Multimap in Java](https://www.baeldung.com/java-convert-stream-map-multimap)
- [How to Avoid NoSuchElementException in Stream API](https://www.baeldung.com/java-streams-api-avoid-nosuchelementexception)
@@ -82,7 +82,6 @@
<maven.compiler.source>12</maven.compiler.source>
<maven.compiler.target>12</maven.compiler.target>
<vavr.version>0.10.2</vavr.version>
<guava.version>32.1.2-jre</guava.version>
</properties>
</project>
@@ -0,0 +1,36 @@
package com.baeldung.skippingelements;
import java.util.ArrayList;
import java.util.List;
import java.util.function.BinaryOperator;
import java.util.stream.Collector;
class SkippingCollector {
private static final BinaryOperator<SkippingCollector> IGNORE_COMBINE = (a, b) -> a;
private final int skip;
private final List<String> list = new ArrayList<>();
private int currentIndex = 0;
private SkippingCollector(int skip) {
this.skip = skip;
}
private void accept(String item) {
final int index = ++currentIndex % skip;
if (index == 0) {
list.add(item);
}
}
private List<String> getResult() {
return list;
}
public static Collector<String, SkippingCollector, List<String>> collector(int skip) {
return Collector.of(() -> new SkippingCollector(skip),
SkippingCollector::accept,
IGNORE_COMBINE,
SkippingCollector::getResult);
}
}
@@ -0,0 +1,25 @@
package com.baledung.modifystream.entity;
public class ImmutablePerson {
private String name;
private String email;
public ImmutablePerson(String name, String email) {
this.name = name;
this.email = email;
}
public ImmutablePerson withEmail(String email) {
return new ImmutablePerson(this.name, email);
}
public String getName() {
return name;
}
public String getEmail() {
return email;
}
}
@@ -0,0 +1,27 @@
package com.baledung.modifystream.entity;
public class Person {
private String name;
private String email;
public Person(String name, String email) {
this.name = name;
this.email = email;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
@@ -0,0 +1,42 @@
package com.baeldung.findfirstnullpointerexception;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Function;
import org.junit.Test;
public class FindFirstNullPointerExceptionUnitTest {
private final List<String> inputs = Arrays.asList(null, "foo", "bar");
@Test(expected = NullPointerException.class)
public void givenStream_whenCallingFindFirst_thenThrowNullPointerException() {
Optional<String> firstElement = inputs.stream()
.findFirst();
}
@Test
public void givenStream_whenUsingOfNullableBeforeFindFirst_thenCorrect() {
Optional<String> firstElement = inputs.stream()
.map(Optional::ofNullable)
.findFirst()
.flatMap(Function.identity());
assertTrue(firstElement.isEmpty());
}
@Test
public void givenStream_whenUsingFilterBeforeFindFirst_thenCorrect() {
Optional<String> firstNonNullElement = inputs.stream()
.filter(Objects::nonNull)
.findFirst();
assertTrue(firstNonNullElement.isPresent());
}
}
@@ -0,0 +1,132 @@
package com.baeldung.modifystream;
import com.baledung.modifystream.entity.ImmutablePerson;
import com.baledung.modifystream.entity.Person;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.ConcurrentModificationException;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Collectors;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
public class ModifyStreamUnitTest {
Logger logger = LoggerFactory.getLogger(ModifyStreamUnitTest.class);
List<Person> personList = new ArrayList<Person>();
List<ImmutablePerson> immutablePersonList = new ArrayList<ImmutablePerson>();
@BeforeEach
void prepare() {
Person person1 = new Person("John", "john@gmail.com");
Person person2 = new Person("Peter", "peter@gmail.com");
Person person3 = new Person("Mary", "mary@gmail.com");
Person person4 = new Person("William", "william@gmail.com");
personList.add(person1);
personList.add(person2);
personList.add(person3);
personList.add(person4);
}
@BeforeEach
void prepareImmutablePerson() {
ImmutablePerson immutablePerson1 = new ImmutablePerson("John", "john@gmail.com");
ImmutablePerson immutablePerson2 = new ImmutablePerson("Peter", "peter@gmail.com");
ImmutablePerson immutablePerson3 = new ImmutablePerson("Mary", "mary@gmail.com");
ImmutablePerson immutablePerson4 = new ImmutablePerson("William", "william@gmail.com");
immutablePersonList.add(immutablePerson1);
immutablePersonList.add(immutablePerson2);
immutablePersonList.add(immutablePerson3);
immutablePersonList.add(immutablePerson4);
}
@Test
void givenPersonList_whenRemoveWhileIterating_thenThrowException() {
assertThrows(NullPointerException.class, () -> {
personList.stream().forEach(e -> {
if(e.getName().equals("John")) {
personList.remove(e);
}
});
});
}
@Test
void givenPersonList_whenRemoveWhileIteratingWithForEach_thenThrowException() {
assertThrows(ConcurrentModificationException.class, () -> {
personList.forEach(e -> {
if(e.getName().equals("John")) {
personList.remove(e);
}
});
});
}
@Test
void givenPersonList_whenRemoveWhileIterating_thenPersonRemoved() {
assertEquals(4, personList.size());
CopyOnWriteArrayList<Person> cps = new CopyOnWriteArrayList<>(personList);
cps.stream().forEach(e -> {
if(e.getName().equals("John")) {
cps.remove(e);
}
});
assertEquals(3, cps.size());
}
@Test
void givenPersonList_whenRemovePersonWithFilter_thenPersonRemoved() {
assertEquals(4, personList.size());
List<Person> newPersonList = personList.stream()
.filter(e -> !e.getName().equals("John"))
.collect(Collectors.toList());
assertEquals(3, newPersonList.size());
}
@Test
void givenPersonList_whenUpdatePersonEmailByInterferingWithForEach_thenPersonEmailUpdated() {
personList.stream().forEach(e -> e.setEmail(e.getEmail().toUpperCase()));
personList.forEach(e -> assertEquals(e.getEmail(), e.getEmail().toUpperCase()));
}
@Test
void givenPersonList_whenUpdatePersonEmailWithMapMethod_thenPersonEmailUpdated() {
List<Person> newPersonList = personList.stream()
.map(e -> new Person(e.getName(), e.getEmail().toUpperCase()))
.collect(Collectors.toList());
newPersonList.forEach(e -> assertEquals(e.getEmail(), e.getEmail().toUpperCase()));
}
@Test
void givenPersonList_whenUpdateImmutablePersonEmailWithMapMethod_thenPersonEmailUpdated() {
List<ImmutablePerson> newImmutablePersonList = immutablePersonList.stream()
.map(e -> e.withEmail(e.getEmail().toUpperCase()))
.collect(Collectors.toList());
newImmutablePersonList.forEach(e -> assertEquals(e.getEmail(), e.getEmail().toUpperCase()));
}
@Test
void givenPersonList_whenUpdatePersonEmailByInterferingWithPeek_thenPersonEmailUpdated() {
personList.stream()
.peek(e -> e.setEmail(e.getEmail().toUpperCase()))
.collect(Collectors.toList());
personList.forEach(e -> assertEquals(e.getEmail(), e.getEmail().toUpperCase()));
}
}
@@ -0,0 +1,62 @@
package com.baeldung.nosuchelementexception;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Optional;
import org.junit.Test;
public class NoSuchElementExceptionStreamUnitTest {
@Test(expected = NoSuchElementException.class)
public void givenEmptyOptional_whenCallingGetMethod_thenThrowNoSuchElementException() {
List<String> names = List.of("William", "Amelia", "Albert", "Philip");
Optional<String> emptyOptional = names.stream()
.filter(name -> name.equals("Emma"))
.findFirst();
emptyOptional.get();
}
@Test
public void givenEmptyOptional_whenUsingIsPresentMethod_thenReturnDefault() {
List<String> names = List.of("Tyler", "Amelia", "James", "Emma");
Optional<String> emptyOptional = names.stream()
.filter(name -> name.equals("Lucas"))
.findFirst();
String name = "unknown";
if (emptyOptional.isPresent()) {
name = emptyOptional.get();
}
assertEquals("unknown", name);
}
@Test
public void givenEmptyOptional_whenUsingOrElseMethod_thenReturnDefault() {
List<String> names = List.of("Nicholas", "Justin", "James");
Optional<String> emptyOptional = names.stream()
.filter(name -> name.equals("Lucas"))
.findFirst();
String name = emptyOptional.orElse("unknown");
assertEquals("unknown", name);
}
@Test
public void givenEmptyOptional_whenUsingOrElseGetMethod_thenReturnDefault() {
List<String> names = List.of("Thomas", "Catherine", "David", "Olivia");
Optional<String> emptyOptional = names.stream()
.filter(name -> name.equals("Liam"))
.findFirst();
String name = emptyOptional.orElseGet(() -> "unknown");
assertEquals("unknown", name);
}
}
@@ -0,0 +1,147 @@
package com.baeldung.skippingelements;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
class SkippingElementsUnitTest {
private static Stream<Arguments> testSource() {
return Stream.of(
Arguments.of(
Stream.of("One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve", "Thirteen",
"Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen", "Twenty", "Twenty One", "Twenty Two",
"Twenty Three", "Twenty Four", "Twenty Five", "Twenty Six", "Twenty Seven", "Twenty Eight", "Twenty Nine", "Thirty",
"Thirty One", "Thirty Two", "Thirty Three"),
List.of("Three", "Six", "Nine", "Twelve", "Fifteen", "Eighteen", "Twenty One", "Twenty Four", "Twenty Seven", "Thirty",
"Thirty Three"),
3),
Arguments.of(
Stream.of("One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve", "Thirteen",
"Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen", "Twenty", "Twenty One", "Twenty Two",
"Twenty Three", "Twenty Four", "Twenty Five", "Twenty Six", "Twenty Seven", "Twenty Eight", "Twenty Nine", "Thirty",
"Thirty One", "Thirty Two", "Thirty Three"),
List.of("Five", "Ten", "Fifteen", "Twenty", "Twenty Five", "Thirty"),
5),
Arguments.of(
Stream.of("One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve", "Thirteen",
"Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen", "Twenty", "Twenty One", "Twenty Two",
"Twenty Three", "Twenty Four", "Twenty Five", "Twenty Six", "Twenty Seven", "Twenty Eight", "Twenty Nine", "Thirty",
"Thirty One", "Thirty Two", "Thirty Three"),
List.of("One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve", "Thirteen",
"Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen", "Twenty", "Twenty One", "Twenty Two",
"Twenty Three", "Twenty Four", "Twenty Five", "Twenty Six", "Twenty Seven", "Twenty Eight", "Twenty Nine", "Thirty",
"Thirty One", "Thirty Two", "Thirty Three"),
1),
Arguments.of(
Stream.of("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"),
List.of("Wednesday", "Saturday"),
3),
Arguments.of(
Stream.of("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"),
List.of("Friday"),
5),
Arguments.of(
Stream.of("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"),
List.of("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"),
1),
Arguments.of(
Stream.of("January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November",
"December"),
List.of("March", "June", "September", "December"),
3),
Arguments.of(
Stream.of("January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November",
"December"),
List.of("May", "October"),
5),
Arguments.of(
Stream.of("January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November",
"December"),
List.of("January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November",
"December"),
1)
);
}
@ParameterizedTest
@MethodSource("testSource")
void givenListSkipNthElementInListWithFilterTestShouldFilterNthElement(Stream<String> input, List<String> expected, int n) {
final List<String> sourceList = input.collect(Collectors.toList());
final List<String> actual = IntStream.range(0, sourceList.size())
.filter(s -> (s + 1) % n == 0)
.mapToObj(sourceList::get)
.collect(Collectors.toList());
assertEquals(expected, actual);
}
@ParameterizedTest
@MethodSource("testSource")
void givenListSkipNthElementInListWithIterateTestShouldFilterNthElement(Stream<String> input, List<String> expected, int n) {
final List<String> sourceList = input.collect(Collectors.toList());
int limit = sourceList.size() / n;
final List<String> actual = IntStream.iterate(n - 1, i -> (i + n))
.limit(limit)
.mapToObj(sourceList::get)
.collect(Collectors.toList());
assertEquals(expected, actual);
}
@ParameterizedTest
@MethodSource("testSource")
void givenListSkipNthElementInListWithSublistTestShouldFilterNthElement(Stream<String> input, List<String> expected, int n) {
final List<String> sourceList = input.collect(Collectors.toList());
int limit = sourceList.size() / n;
final List<String> actual = Stream.iterate(sourceList, s -> s.subList(n, s.size()))
.limit(limit)
.map(s -> s.get(n - 1))
.collect(Collectors.toList());
assertEquals(expected, actual);
}
@ParameterizedTest
@MethodSource("testSource")
void givenListSkipNthElementInListWithForTestShouldFilterNthElement(Stream<String> input, List<String> expected, int n) {
final List<String> sourceList = input.collect(Collectors.toList());
List<String> result = new ArrayList<>();
for (int i = n - 1; i < sourceList.size(); i += n) {
result.add(sourceList.get(i));
}
final List<String> actual = result;
assertEquals(expected, actual);
}
@ParameterizedTest
@MethodSource("testSource")
void givenListSkipNthElementInStreamWithIteratorTestShouldFilterNthElement(Stream<String> input, List<String> expected, int n) {
List<String> result = new ArrayList<>();
final Iterator<String> iterator = input.iterator();
int count = 0;
while (iterator.hasNext()) {
if (count % n == n - 1) {
result.add(iterator.next());
} else {
iterator.next();
}
++count;
}
final List<String> actual = result;
assertEquals(expected, actual);
}
@ParameterizedTest
@MethodSource("testSource")
void givenListSkipNthElementInStreamWithCollectorShouldFilterNthElement(Stream<String> input, List<String> expected, int n) {
final List<String> actual = input.collect(SkippingCollector.collector(n));
assertEquals(expected, actual);
}
}
@@ -0,0 +1,101 @@
package com.baeldung.streamtomapandmultimap;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ListMultimap;
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");
ListMultimap<String, String> multimap = stringStream.collect(
ArrayListMultimap::create,
(map, element) -> map.put(element, element),
ArrayListMultimap::putAll
);
ListMultimap<String, String> expectedMultimap = ArrayListMultimap.create();
expectedMultimap.put("one", "one");
expectedMultimap.put("two", "two");
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);
}
}