diff --git a/libraries/pom.xml b/libraries/pom.xml
index 1d0f0db165..d2b8d6ffd8 100644
--- a/libraries/pom.xml
+++ b/libraries/pom.xml
@@ -1,111 +1,110 @@
-
- parent-modules
- com.baeldung
- 1.0.0-SNAPSHOT
-
- 4.0.0
- libraries
- libraries
-
-
-
- org.apache.maven.plugins
- maven-dependency-plugin
-
-
- org.apache.felix
- maven-bundle-plugin
- 3.3.0
- maven-plugin
-
-
- true
-
-
- maven-failsafe-plugin
- 2.20
-
-
- chromedriver
-
-
-
-
- net.serenity-bdd.maven.plugins
- serenity-maven-plugin
- ${serenity.plugin.version}
-
-
- serenity-reports
- post-integration-test
-
- aggregate
-
-
-
-
-
-
- org.datanucleus
- datanucleus-maven-plugin
- 5.0.2
-
- JDO
- ${basedir}/datanucleus.properties
- ${basedir}/log4j.properties
- true
- false
-
-
-
-
- process-classes
-
- enhance
-
-
-
-
-
-
- org.apache.maven.plugins
- maven-jar-plugin
- 3.0.2
-
-
- **/log4j.properties
-
-
-
- com.baeldung.neuroph.NeurophXOR
-
-
-
-
-
- org.apache.maven.plugins
- maven-surefire-plugin
- 2.18.1
-
-
- test
- test
-
- test
-
-
-
- test/java/com/baeldung/neuroph/XORTest.java
-
-
-
-
-
-
-
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ parent-modules
+ com.baeldung
+ 1.0.0-SNAPSHOT
+
+ 4.0.0
+ libraries
+ libraries
+
+
+
+ org.apache.maven.plugins
+ maven-dependency-plugin
+
+
+ org.apache.felix
+ maven-bundle-plugin
+ 3.3.0
+ maven-plugin
+
+
+ true
+
+
+ maven-failsafe-plugin
+ 2.20
+
+
+ chromedriver
+
+
+
+
+ net.serenity-bdd.maven.plugins
+ serenity-maven-plugin
+ ${serenity.plugin.version}
+
+
+ serenity-reports
+ post-integration-test
+
+ aggregate
+
+
+
+
+
+
+ org.datanucleus
+ datanucleus-maven-plugin
+ 5.0.2
+
+ JDO
+ ${basedir}/datanucleus.properties
+ ${basedir}/log4j.properties
+ true
+ false
+
+
+
+
+ process-classes
+
+ enhance
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+ 3.0.2
+
+
+ **/log4j.properties
+
+
+
+ com.baeldung.neuroph.NeurophXOR
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 2.18.1
+
+
+ test
+ test
+
+ test
+
+
+
+ test/java/com/baeldung/neuroph/XORTest.java
+
+
+
+
+
+
@@ -534,7 +533,12 @@
jdeferred-core
1.2.6
-
+
+ com.codepoetics
+ protonpack
+ ${protonpack.version}
+
+
maven2-repository.dev.java.net
@@ -610,5 +614,6 @@
15.2
2.9.9
1.5.1
+ 1.14
diff --git a/libraries/src/main/java/com/baeldung/protonpack/CollectorUtilsExample.java b/libraries/src/main/java/com/baeldung/protonpack/CollectorUtilsExample.java
new file mode 100644
index 0000000000..016178083a
--- /dev/null
+++ b/libraries/src/main/java/com/baeldung/protonpack/CollectorUtilsExample.java
@@ -0,0 +1,18 @@
+package com.baeldung.protonpack;
+
+import java.util.Optional;
+import java.util.stream.Stream;
+
+import static com.codepoetics.protonpack.collectors.CollectorUtils.maxBy;
+import static com.codepoetics.protonpack.collectors.CollectorUtils.minBy;
+
+public class CollectorUtilsExample {
+
+ public void minMaxProjectionCollector() {
+ Stream integerStream = Stream.of("a", "bb", "ccc", "1");
+
+ Optional max = integerStream.collect(maxBy(String::length));
+ Optional min = integerStream.collect(minBy(String::length));
+
+ }
+}
diff --git a/libraries/src/main/java/com/baeldung/protonpack/StreamUtilsExample.java b/libraries/src/main/java/com/baeldung/protonpack/StreamUtilsExample.java
new file mode 100644
index 0000000000..eead34af71
--- /dev/null
+++ b/libraries/src/main/java/com/baeldung/protonpack/StreamUtilsExample.java
@@ -0,0 +1,107 @@
+package com.baeldung.protonpack;
+
+import com.codepoetics.protonpack.Indexed;
+import com.codepoetics.protonpack.StreamUtils;
+import com.codepoetics.protonpack.selectors.Selectors;
+
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+import java.util.stream.LongStream;
+import java.util.stream.Stream;
+
+import static java.util.stream.Collectors.toList;
+
+public class StreamUtilsExample {
+
+ public void createInfiniteIndex() {
+ LongStream indices = StreamUtils.indices();
+ }
+
+ public void zipAStreamWithIndex() {
+ Stream source = Stream.of("Foo", "Bar", "Baz");
+ List> zipped = StreamUtils
+ .zipWithIndex(source)
+ .collect(Collectors.toList());
+ }
+
+ public void zipAPairOfStreams() {
+ Stream streamA = Stream.of("A", "B", "C");
+ Stream streamB = Stream.of("Apple", "Banana", "Carrot");
+
+ List zipped = StreamUtils
+ .zip(streamA, streamB, (a, b) -> a + " is for " + b)
+ .collect(Collectors.toList());
+ }
+
+ public void zipThreeStreams() {
+ Stream streamA = Stream.of("A", "B", "C");
+ Stream streamB = Stream.of("aggravating", "banausic", "complaisant");
+ Stream streamC = Stream.of("Apple", "Banana", "Carrot");
+
+ List zipped = StreamUtils
+ .zip(streamA, streamB, streamC, (a, b, c) -> a + " is for " + b + " " + c)
+ .collect(Collectors.toList());
+ }
+
+ public void mergeThreeStreams() {
+ Stream streamA = Stream.of("A", "B", "C");
+ Stream streamB = Stream.of("apple", "banana", "carrot", "date");
+ Stream streamC = Stream.of("fritter", "split", "cake", "roll", "pastry");
+
+ Stream> merged = StreamUtils.mergeToList(streamA, streamB, streamC);
+ }
+
+ public void interleavingStreamsUsingRoundRobin() {
+ Stream streamA = Stream.of("Peter", "Paul", "Mary");
+ Stream streamB = Stream.of("A", "B", "C", "D", "E");
+ Stream streamC = Stream.of("foo", "bar", "baz", "xyzzy");
+
+ Stream interleaved = StreamUtils.interleave(Selectors.roundRobin(), streamA, streamB, streamC);
+ }
+
+ public void takeWhileAndTakeUntilStream() {
+ Stream infiniteInts = Stream.iterate(0, i -> i + 1);
+ Stream finiteIntsWhileLessThan10 = StreamUtils.takeWhile(infiniteInts, i -> i < 10);
+ Stream finiteIntsUntilGreaterThan10 = StreamUtils.takeUntil(infiniteInts, i -> i > 10);
+ }
+
+ public void skipWhileAndSkipUntilStream() {
+ Stream ints = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
+ Stream skippedWhileConditionMet = StreamUtils.skipWhile(ints, i -> i < 4);
+ Stream skippedUntilConditionMet = StreamUtils.skipWhile(ints, i -> i > 4);
+ }
+
+ public void unfoldStream() {
+ Stream unfolded = StreamUtils.unfold(1, i -> (i < 10) ? Optional.of(i + 1) : Optional.empty());
+ }
+
+ public void windowedStream() {
+ Stream integerStream = Stream.of(1, 2, 3, 4, 5);
+
+ List> windows = StreamUtils
+ .windowed(integerStream, 2)
+ .collect(toList());
+ List> windowsWithSkipIndex = StreamUtils
+ .windowed(integerStream, 3, 2)
+ .collect(toList());
+ List> windowsWithSkipIndexAndAllowLowerSize = StreamUtils
+ .windowed(integerStream, 2, 2, true)
+ .collect(toList());
+
+ }
+
+ public void groupRunsStreams() {
+ Stream integerStream = Stream.of(1, 1, 2, 2, 3, 4, 5);
+
+ List> runs = StreamUtils
+ .groupRuns(integerStream)
+ .collect(toList());
+ }
+
+ public void aggreagateOnBiElementPredicate() {
+ Stream stream = Stream.of("a1", "b1", "b2", "c1");
+ Stream> aggregated = StreamUtils.aggregate(stream, (e1, e2) -> e1.charAt(0) == e2.charAt(0));
+ }
+
+}
diff --git a/libraries/src/test/java/com/baeldung/protonpack/CollectorUtilsTests.java b/libraries/src/test/java/com/baeldung/protonpack/CollectorUtilsTests.java
new file mode 100644
index 0000000000..4fd21ec508
--- /dev/null
+++ b/libraries/src/test/java/com/baeldung/protonpack/CollectorUtilsTests.java
@@ -0,0 +1,66 @@
+package com.baeldung.protonpack;
+
+import com.codepoetics.protonpack.collectors.CollectorUtils;
+import com.codepoetics.protonpack.collectors.NonUniqueValueException;
+import org.junit.Test;
+
+import java.util.Optional;
+import java.util.stream.Stream;
+
+import static com.codepoetics.protonpack.collectors.CollectorUtils.maxBy;
+import static com.codepoetics.protonpack.collectors.CollectorUtils.minBy;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+public class CollectorUtilsTests {
+
+ @Test
+ public void maxByWithProjectionAndDefaultComparer() {
+ Stream integerStream = Stream.of("a", "bb", "ccc", "1");
+
+ Optional max = integerStream.collect(maxBy(String::length));
+
+ assertThat(max.get(), is("ccc"));
+ }
+
+ @Test
+ public void minByWithProjectionAndDefaultComparer() {
+ Stream integerStream = Stream.of("abc", "bb", "ccc", "1");
+
+ Optional max = integerStream.collect(minBy(String::length));
+
+ assertThat(max.get(), is("1"));
+ }
+
+ @Test
+ public void returnsEmptyForEmptyStream() {
+ assertThat(Stream
+ .empty()
+ .collect(CollectorUtils.unique()), equalTo(Optional.empty()));
+ }
+
+ @Test
+ public void returnsUniqueItem() {
+ assertThat(Stream
+ .of(1, 2, 3)
+ .filter(i -> i > 2)
+ .collect(CollectorUtils.unique()), equalTo(Optional.of(3)));
+ }
+
+ @Test
+ public void returnsUniqueNullableItem() {
+ assertThat(Stream
+ .of(1, 2, 3)
+ .filter(i -> i > 2)
+ .collect(CollectorUtils.uniqueNullable()), equalTo(3));
+ }
+
+ @Test(expected = NonUniqueValueException.class)
+ public void throwsExceptionIfItemIsNotUnique() {
+ Stream
+ .of(1, 2, 3)
+ .filter(i -> i > 1)
+ .collect(CollectorUtils.unique());
+ }
+}
diff --git a/libraries/src/test/java/com/baeldung/protonpack/StreamUtilsTests.java b/libraries/src/test/java/com/baeldung/protonpack/StreamUtilsTests.java
new file mode 100644
index 0000000000..282a41e0df
--- /dev/null
+++ b/libraries/src/test/java/com/baeldung/protonpack/StreamUtilsTests.java
@@ -0,0 +1,208 @@
+package com.baeldung.protonpack;
+
+import com.codepoetics.protonpack.Indexed;
+import com.codepoetics.protonpack.StreamUtils;
+import com.codepoetics.protonpack.selectors.Selectors;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+import java.util.stream.LongStream;
+import java.util.stream.Stream;
+
+import static java.util.Arrays.asList;
+import static java.util.stream.Collectors.maxBy;
+import static java.util.stream.Collectors.toList;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.*;
+
+public class StreamUtilsTests {
+
+ @Test
+ public void createInfiniteIndex() {
+ LongStream indices = StreamUtils
+ .indices()
+ .limit(500);
+
+ }
+
+ @Test
+ public void zipAStreamWithIndex() {
+ Stream source = Stream.of("Foo", "Bar", "Baz");
+
+ List> zipped = StreamUtils
+ .zipWithIndex(source)
+ .collect(Collectors.toList());
+
+ assertThat(zipped, contains(Indexed.index(0, "Foo"), Indexed.index(1, "Bar"), Indexed.index(2, "Baz")));
+ }
+
+ @Test
+ public void zipAPairOfStreams() {
+ Stream streamA = Stream.of("A", "B", "C");
+ Stream streamB = Stream.of("Apple", "Banana", "Carrot");
+
+ List zipped = StreamUtils
+ .zip(streamA, streamB, (a, b) -> a + " is for " + b)
+ .collect(Collectors.toList());
+
+ assertThat(zipped, contains("A is for Apple", "B is for Banana", "C is for Carrot"));
+ }
+
+ @Test
+ public void zipThreeStreams() {
+ Stream streamA = Stream.of("A", "B", "C");
+ Stream streamB = Stream.of("aggravating", "banausic", "complaisant");
+ Stream streamC = Stream.of("Apple", "Banana", "Carrot");
+
+ List zipped = StreamUtils
+ .zip(streamA, streamB, streamC, (a, b, c) -> a + " is for " + b + " " + c)
+ .collect(Collectors.toList());
+
+ assertThat(zipped, contains("A is for aggravating Apple", "B is for banausic Banana", "C is for complaisant Carrot"));
+ }
+
+ @Test
+ public void mergeThreeStreams() {
+ Stream streamA = Stream.of("A", "B", "C");
+ Stream streamB = Stream.of("apple", "banana", "carrot", "date");
+ Stream streamC = Stream.of("fritter", "split", "cake", "roll", "pastry");
+
+ Stream> merged = StreamUtils.mergeToList(streamA, streamB, streamC);
+
+ assertThat(merged.collect(toList()), contains(asList("A", "apple", "fritter"), asList("B", "banana", "split"), asList("C", "carrot", "cake"), asList("date", "roll"), asList("pastry")));
+ }
+
+ @Test
+ public void roundRobinInterleaving() {
+ Stream streamA = Stream.of("Peter", "Paul", "Mary");
+ Stream streamB = Stream.of("A", "B", "C", "D", "E");
+ Stream streamC = Stream.of("foo", "bar", "baz", "xyzzy");
+
+ Stream interleaved = StreamUtils.interleave(Selectors.roundRobin(), streamA, streamB, streamC);
+
+ assertThat(interleaved.collect(Collectors.toList()), contains("Peter", "A", "foo", "Paul", "B", "bar", "Mary", "C", "baz", "D", "xyzzy", "E"));
+ }
+
+ @Test
+ public void takeWhileConditionIsMet() {
+ Stream infiniteInts = Stream.iterate(0, i -> i + 1);
+ Stream finiteInts = StreamUtils.takeWhile(infiniteInts, i -> i < 10);
+
+ assertThat(finiteInts.collect(Collectors.toList()), hasSize(10));
+ }
+
+ @Test
+ public void takeUntilConditionIsNotMet() {
+ Stream infiniteInts = Stream.iterate(0, i -> i + 1);
+ Stream finiteInts = StreamUtils.takeUntil(infiniteInts, i -> i > 10);
+
+ assertThat(finiteInts.collect(Collectors.toList()), hasSize(11));
+ }
+
+ @Test
+ public void skipWhileConditionMet() {
+ Stream ints = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
+ Stream skipped = StreamUtils.skipWhile(ints, i -> i < 4);
+ List collected = skipped.collect(Collectors.toList());
+
+ assertThat(collected, contains(4, 5, 6, 7, 8, 9, 10));
+ }
+
+ @Test
+ public void skipUntilConditionMet() {
+ Stream ints = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
+ Stream skipped = StreamUtils.skipUntil(ints, i -> i > 4);
+ List collected = skipped.collect(Collectors.toList());
+
+ assertThat(collected, contains(5, 6, 7, 8, 9, 10));
+ }
+
+ @Test
+ public void unfoldUntilEmptyIsReturned() {
+ Stream unfolded = StreamUtils.unfold(1, i -> (i < 10) ? Optional.of(i + 1) : Optional.empty());
+
+ assertThat(unfolded.collect(Collectors.toList()), contains(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
+ }
+
+ @Test
+ public void groupRunsStreamTest() {
+ Stream integerStream = Stream.of(1, 1, 2, 2, 3, 4, 5);
+ List> runs = StreamUtils
+ .groupRuns(integerStream)
+ .collect(toList());
+
+ assertThat(runs, contains(asList(1, 1), asList(2, 2), asList(3), asList(4), asList(5)));
+ }
+
+ @Test
+ public void aggreagateOnBiElementPredicate() {
+ Stream stream = Stream.of("a1", "b1", "b2", "c1");
+ Stream> aggregated = StreamUtils.aggregate(stream, (e1, e2) -> e1.charAt(0) == e2.charAt(0));
+ assertThat(aggregated.collect(toList()), contains(asList("a1"), asList("b1", "b2"), asList("c1")));
+ }
+
+ @Test
+ public void windowingOnList() {
+ Stream integerStream = Stream.of(1, 2, 3, 4, 5);
+
+ List> windows = StreamUtils
+ .windowed(integerStream, 2)
+ .collect(toList());
+
+ assertThat(windows, contains(asList(1, 2), asList(2, 3), asList(3, 4), asList(4, 5)));
+ }
+
+ @Test
+ public void windowingOnListTwoOverlap() {
+ Stream integerStream = Stream.of(1, 2, 3, 4, 5);
+
+ List> windows = StreamUtils
+ .windowed(integerStream, 3, 2)
+ .collect(toList());
+
+ assertThat(windows, contains(asList(1, 2, 3), asList(3, 4, 5)));
+ }
+
+ @Test
+ public void windowingOnEmptyList() {
+ ArrayList ints = new ArrayList<>();
+
+ ints
+ .stream()
+ .collect(maxBy((a, b) -> a
+ .toString()
+ .compareTo(b.toString())));
+
+ List> windows = StreamUtils
+ .windowed(ints.stream(), 2)
+ .collect(toList());
+
+ assertThat(windows, iterableWithSize(0));
+ }
+
+ @Test
+ public void windowingOnListTwoOverlapAllowLesserSize() {
+ Stream integerStream = Stream.of(1, 2, 3, 4, 5);
+
+ List> windows = StreamUtils
+ .windowed(integerStream, 2, 2, true)
+ .collect(toList());
+
+ assertThat(windows, contains(asList(1, 2), asList(3, 4), asList(5)));
+ }
+
+ @Test
+ public void windowingOnListOneOverlapAllowLesserSizeMultipleLesserWindows() {
+ Stream integerStream = Stream.of(1, 2, 3, 4, 5);
+
+ List> windows = StreamUtils
+ .windowed(integerStream, 3, 1, true)
+ .collect(toList());
+
+ assertThat(windows, contains(asList(1, 2, 3), asList(2, 3, 4), asList(3, 4, 5), asList(4, 5), asList(5)));
+ }
+
+}