diff --git a/core-java-8/.project b/core-java-8/.project
deleted file mode 100644
index a23ff42ae0..0000000000
--- a/core-java-8/.project
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
- core-java8
-
-
-
-
-
- org.eclipse.m2e.core.maven2Builder
-
-
-
-
-
- org.eclipse.m2e.core.maven2Nature
-
-
diff --git a/core-java-8/README.md b/core-java-8/README.md
index b03d24c34e..e6bac2a4c9 100644
--- a/core-java-8/README.md
+++ b/core-java-8/README.md
@@ -3,9 +3,12 @@
## Core Java 8 Cookbooks and Examples
### Relevant Articles:
-// - [Java 8 – Powerful Comparison with Lambdas](http://www.baeldung.com/java-8-sort-lambda)
+- [Java 8 – Powerful Comparison with Lambdas](http://www.baeldung.com/java-8-sort-lambda)
- [Java – Directory Size](http://www.baeldung.com/java-folder-size)
- [Java – Try with Resources](http://www.baeldung.com/java-try-with-resources)
+- [A Guide to the Java ExecutorService](http://www.baeldung.com/java-executor-service-tutorial)
+- [Java 8 New Features](http://www.baeldung.com/java-8-new-features)
- [Lambda Expressions and Functional Interfaces: Tips and Best Practices](http://www.baeldung.com/java-8-lambda-expressions-tips)
- [The Double Colon Operator in Java 8](http://www.baeldung.com/java-8-double-colon-operator)
-- [A Guide to the Java ExecutorService](http://www.baeldung.com/java-executor-service-tutorial)
+- [Java 8 Streams Advanced](http://www.baeldung.com/java-8-streams)
+- [Java 8 Collectors](http://www.baeldung.com/java-8-collectors)
\ No newline at end of file
diff --git a/core-java-8/pom.xml b/core-java-8/pom.xml
index 8c9bb36f7d..63df0e1b95 100644
--- a/core-java-8/pom.xml
+++ b/core-java-8/pom.xml
@@ -66,7 +66,8 @@
org.assertj
assertj-core
- 3.4.1
+ 3.5.1
+ test
diff --git a/core-java-8/src/test/java/com/baeldung/collectors/Java8CollectorsTest.java b/core-java-8/src/test/java/com/baeldung/collectors/Java8CollectorsTest.java
new file mode 100644
index 0000000000..d94f72b685
--- /dev/null
+++ b/core-java-8/src/test/java/com/baeldung/collectors/Java8CollectorsTest.java
@@ -0,0 +1,265 @@
+package com.baeldung.collectors;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Sets;
+import org.junit.Test;
+
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.DoubleSummaryStatistics;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.function.BiConsumer;
+import java.util.function.BinaryOperator;
+import java.util.function.Function;
+import java.util.function.Supplier;
+import java.util.stream.Collector;
+
+import static com.google.common.collect.Sets.newHashSet;
+import static java.util.stream.Collectors.averagingDouble;
+import static java.util.stream.Collectors.collectingAndThen;
+import static java.util.stream.Collectors.counting;
+import static java.util.stream.Collectors.groupingBy;
+import static java.util.stream.Collectors.joining;
+import static java.util.stream.Collectors.maxBy;
+import static java.util.stream.Collectors.partitioningBy;
+import static java.util.stream.Collectors.summarizingDouble;
+import static java.util.stream.Collectors.summingDouble;
+import static java.util.stream.Collectors.toCollection;
+import static java.util.stream.Collectors.toList;
+import static java.util.stream.Collectors.toMap;
+import static java.util.stream.Collectors.toSet;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+public class Java8CollectorsTest {
+
+ private final List givenList = Arrays.asList("a", "bb", "ccc", "dd");
+
+ @Test
+ public void whenCollectingToList_shouldCollectToList() throws Exception {
+ final List result = givenList.stream()
+ .collect(toList());
+
+ assertThat(result)
+ .containsAll(givenList);
+ }
+
+ @Test
+ public void whenCollectingToList_shouldCollectToSet() throws Exception {
+ final Set result = givenList.stream()
+ .collect(toSet());
+
+ assertThat(result)
+ .containsAll(givenList);
+ }
+
+ @Test
+ public void whenCollectingToCollection_shouldCollectToCollection() throws Exception {
+ final List result = givenList.stream()
+ .collect(toCollection(LinkedList::new));
+
+ assertThat(result)
+ .containsAll(givenList)
+ .isInstanceOf(LinkedList.class);
+ }
+
+ @Test
+ public void whenCollectingToImmutableCollection_shouldThrowException() throws Exception {
+ assertThatThrownBy(() -> {
+ givenList.stream()
+ .collect(toCollection(ImmutableList::of));
+ }).isInstanceOf(UnsupportedOperationException.class);
+
+ }
+
+ @Test
+ public void whenCollectingToMap_shouldCollectToMap() throws Exception {
+ final Map result = givenList.stream()
+ .collect(toMap(Function.identity(), String::length));
+
+ assertThat(result)
+ .containsEntry("a", 1)
+ .containsEntry("bb", 2)
+ .containsEntry("ccc", 3)
+ .containsEntry("dd", 2);
+ }
+
+ @Test
+ public void whenCollectingToMap_shouldCollectToMapMerging() throws Exception {
+ final Map result = givenList.stream()
+ .collect(toMap(Function.identity(), String::length, (i1, i2) -> i1));
+
+ assertThat(result)
+ .containsEntry("a", 1)
+ .containsEntry("bb", 2)
+ .containsEntry("ccc", 3)
+ .containsEntry("dd", 2);
+ }
+
+ @Test
+ public void whenCollectingAndThen_shouldCollect() throws Exception {
+ final List result = givenList.stream()
+ .collect(collectingAndThen(toList(), ImmutableList::copyOf));
+
+ assertThat(result)
+ .containsAll(givenList)
+ .isInstanceOf(ImmutableList.class);
+ }
+
+ @Test
+ public void whenJoining_shouldJoin() throws Exception {
+ final String result = givenList.stream()
+ .collect(joining());
+
+ assertThat(result)
+ .isEqualTo("abbcccdd");
+ }
+
+ @Test
+ public void whenJoiningWithSeparator_shouldJoinWithSeparator() throws Exception {
+ final String result = givenList.stream()
+ .collect(joining(" "));
+
+ assertThat(result)
+ .isEqualTo("a bb ccc dd");
+ }
+
+ @Test
+ public void whenJoiningWithSeparatorAndPrefixAndPostfix_shouldJoinWithSeparatorPrePost() throws Exception {
+ final String result = givenList.stream()
+ .collect(joining(" ", "PRE-", "-POST"));
+
+ assertThat(result)
+ .isEqualTo("PRE-a bb ccc dd-POST");
+ }
+
+ @Test
+ public void whenPartitioningBy_shouldPartition() throws Exception {
+ final Map> result = givenList.stream()
+ .collect(partitioningBy(s -> s.length() > 2));
+
+ assertThat(result)
+ .containsKeys(true, false)
+ .satisfies(booleanListMap -> {
+ assertThat(booleanListMap.get(true))
+ .contains("ccc");
+
+ assertThat(booleanListMap.get(false))
+ .contains("a", "bb", "dd");
+ });
+ }
+
+ @Test
+ public void whenCounting_shouldCount() throws Exception {
+ final Long result = givenList.stream()
+ .collect(counting());
+
+ assertThat(result)
+ .isEqualTo(4);
+ }
+
+ @Test
+ public void whenSummarizing_shouldSummarize() throws Exception {
+ final DoubleSummaryStatistics result = givenList.stream()
+ .collect(summarizingDouble(String::length));
+
+ assertThat(result.getAverage())
+ .isEqualTo(2);
+ assertThat(result.getCount())
+ .isEqualTo(4);
+ assertThat(result.getMax())
+ .isEqualTo(3);
+ assertThat(result.getMin())
+ .isEqualTo(1);
+ assertThat(result.getSum())
+ .isEqualTo(8);
+ }
+
+ @Test
+ public void whenAveraging_shouldAverage() throws Exception {
+ final Double result = givenList.stream()
+ .collect(averagingDouble(String::length));
+
+ assertThat(result)
+ .isEqualTo(2);
+ }
+
+ @Test
+ public void whenSumming_shouldSum() throws Exception {
+ final Double result = givenList.stream()
+ .collect(summingDouble(String::length));
+
+ assertThat(result)
+ .isEqualTo(8);
+ }
+
+ @Test
+ public void whenMaxingBy_shouldMaxBy() throws Exception {
+ final Optional result = givenList.stream()
+ .collect(maxBy(Comparator.naturalOrder()));
+
+ assertThat(result)
+ .isPresent()
+ .hasValue("dd");
+ }
+
+ @Test
+ public void whenGroupingBy_shouldGroupBy() throws Exception {
+ final Map> result = givenList.stream()
+ .collect(groupingBy(String::length, toSet()));
+
+ assertThat(result)
+ .containsEntry(1, newHashSet("a"))
+ .containsEntry(2, newHashSet("bb", "dd"))
+ .containsEntry(3, newHashSet("ccc"));
+ }
+
+
+ @Test
+ public void whenCreatingCustomCollector_shouldCollect() throws Exception {
+ final ImmutableSet result = givenList.stream()
+ .collect(toImmutableSet());
+
+ assertThat(result)
+ .isInstanceOf(ImmutableSet.class)
+ .contains("a", "bb", "ccc", "dd");
+
+ }
+
+ private static ImmutableSetCollector toImmutableSet() {
+ return new ImmutableSetCollector<>();
+ }
+
+ private static class ImmutableSetCollector implements Collector, ImmutableSet> {
+
+ @Override
+ public Supplier> supplier() {
+ return ImmutableSet::builder;
+ }
+
+ @Override
+ public BiConsumer, T> accumulator() {
+ return ImmutableSet.Builder::add;
+ }
+
+ @Override
+ public BinaryOperator> combiner() {
+ return (left, right) -> left.addAll(right.build());
+ }
+
+ @Override
+ public Function, ImmutableSet> finisher() {
+ return ImmutableSet.Builder::build;
+ }
+
+ @Override
+ public Set characteristics() {
+ return Sets.immutableEnumSet(Characteristics.UNORDERED);
+ }
+ }
+}