diff --git a/core-java-modules/core-java-streams-4/.gitignore b/core-java-modules/core-java-streams-4/.gitignore
new file mode 100644
index 0000000000..3de4cc647e
--- /dev/null
+++ b/core-java-modules/core-java-streams-4/.gitignore
@@ -0,0 +1,26 @@
+*.class
+
+0.*
+
+#folders#
+/target
+/neoDb*
+/data
+/src/main/webapp/WEB-INF/classes
+*/META-INF/*
+.resourceCache
+
+# Packaged files #
+*.jar
+*.war
+*.ear
+
+# Files generated by integration tests
+*.txt
+backup-pom.xml
+/bin/
+/temp
+
+#IntelliJ specific
+.idea/
+*.iml
\ No newline at end of file
diff --git a/core-java-modules/core-java-streams-4/README.md b/core-java-modules/core-java-streams-4/README.md
new file mode 100644
index 0000000000..06b426d8a7
--- /dev/null
+++ b/core-java-modules/core-java-streams-4/README.md
@@ -0,0 +1,6 @@
+## Core Java streams
+
+This module contains articles about the Stream API in Java.
+
+### Relevant Articles:
+- [Count Occurrences using Java groupingBy Collector](https://baeldung.com/count-occurrences-with-java-groupingby-collector)
diff --git a/core-java-modules/core-java-streams-4/pom.xml b/core-java-modules/core-java-streams-4/pom.xml
new file mode 100644
index 0000000000..0a411bcc43
--- /dev/null
+++ b/core-java-modules/core-java-streams-4/pom.xml
@@ -0,0 +1,63 @@
+
+
+ 4.0.0
+ core-java-streams-4
+ 0.1.0-SNAPSHOT
+ core-java-streams
+ jar
+
+
+ com.baeldung.core-java-modules
+ core-java-modules
+ 0.0.1-SNAPSHOT
+ ../
+
+
+
+
+ log4j
+ log4j
+ ${log4j.version}
+
+
+ org.junit
+ junit-bom
+ ${junit-jupiter.version}
+ pom
+ import
+
+
+
+
+ core-java-streams-4
+
+
+ src/main
+ true
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ ${maven-compiler-plugin.version}
+
+
+ ${maven.compiler.target}
+ -parameters
+
+
+
+
+
+
+
+ 3.1
+ 1.8
+ 1.8
+
+
+
\ No newline at end of file
diff --git a/core-java-modules/core-java-streams-4/src/test/java/com/baeldung/streamcollectors/StreamGroupingByCollectorUnitTest.java b/core-java-modules/core-java-streams-4/src/test/java/com/baeldung/streamcollectors/StreamGroupingByCollectorUnitTest.java
new file mode 100644
index 0000000000..74b9d61370
--- /dev/null
+++ b/core-java-modules/core-java-streams-4/src/test/java/com/baeldung/streamcollectors/StreamGroupingByCollectorUnitTest.java
@@ -0,0 +1,99 @@
+package com.baeldung.streamcollectors;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class StreamGroupingByCollectorUnitTest
+{
+ static class Employee {
+
+ Integer employeeId;
+ String employeeName;
+ Integer departmentId;
+
+ Employee(Integer employeeId, String employeeName, Integer departmentId) {
+ this.employeeId = employeeId;
+ this.employeeName = employeeName;
+ this.departmentId = departmentId;
+ }
+
+ public Integer getEmployeeId() {
+ return employeeId;
+ }
+
+ public void setEmployeeId(Integer employeeId) {
+ this.employeeId = employeeId;
+ }
+
+ public String getEmployeeName() {
+ return employeeName;
+ }
+
+ public void setEmployeeName(String employeeName) {
+ this.employeeName = employeeName;
+ }
+
+ public Integer getDepartmentId() {
+ return departmentId;
+ }
+
+ public void setDepartmentId(Integer departmentId) {
+ this.departmentId = departmentId;
+ }
+ }
+
+ @Test
+ public void
+ givenListOfStrings_whenGroupingEqualStrings_thenUseCollectorsGroupingByToGroupEqualStringsAndCountOfOccurrences() {
+ List list = new ArrayList<>(
+ Arrays.asList("Foo", "Bar", "Bar", "Foo", "Bar")
+ );
+
+ Map result = list.stream().collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
+ Assert.assertEquals(new Long(2), result.get("Foo"));
+ Assert.assertEquals(new Long(3), result.get("Bar"));
+
+ }
+
+ @Test
+ public void
+ givenListOfStrings_whenGroupingEqualLengthStrings_thenUseCollectorsGroupingByConcurrentToGroupEqualLengthStringsAndCountOfOccurrences() {
+
+ List list = new ArrayList<>(
+ Arrays.asList("Adam", "Bill", "Jack", "Joe", "Ian")
+ );
+
+ Map result = list.stream()
+ .collect(Collectors.groupingByConcurrent(String::length, Collectors.counting()));
+ Assert.assertEquals(new Long(2), result.get(3));
+ Assert.assertEquals(new Long(3), result.get(4));
+
+ }
+
+
+ @Test
+ public void
+ givenListOfEmployees_whenGroupingDepartmentId_thenUseCollectorsGroupingByDepartmentIdAndCountNumberOfEmployeesWithinEveryDepartment() {
+
+ List list = new ArrayList<>(
+ Arrays.asList(new Employee(1, "Joe", 1),
+ new Employee(2, "Josh", 1),
+ new Employee(3, "Jamie", 2),
+ new Employee(4, "Jim", 2),
+ new Employee(5, "Jack", 2))
+ );
+
+ Map result = list.stream() .collect(Collectors.groupingBy(Employee::getDepartmentId, Collectors.counting()));
+ Assert.assertEquals(new Long(2), result.get(1));
+ Assert.assertEquals(new Long(3), result.get(2));
+
+ }
+
+}
diff --git a/core-java-modules/core-java-streams-4/src/test/resources/.gitignore b/core-java-modules/core-java-streams-4/src/test/resources/.gitignore
new file mode 100644
index 0000000000..83c05e60c8
--- /dev/null
+++ b/core-java-modules/core-java-streams-4/src/test/resources/.gitignore
@@ -0,0 +1,13 @@
+*.class
+
+#folders#
+/target
+/neoDb*
+/data
+/src/main/webapp/WEB-INF/classes
+*/META-INF/*
+
+# Packaged files #
+*.jar
+*.war
+*.ear
\ No newline at end of file
diff --git a/core-java-modules/pom.xml b/core-java-modules/pom.xml
index 8661f1ba01..8c6df97ad7 100644
--- a/core-java-modules/pom.xml
+++ b/core-java-modules/pom.xml
@@ -103,6 +103,7 @@
core-java-streams
core-java-streams-2
core-java-streams-3
+ core-java-streams-4
core-java-string-algorithms
core-java-string-algorithms-2
core-java-string-algorithms-3