Skip to content

Commit 7bce761

Browse files
committed
feat(streams-collectors): add comprehensive demo of Java Collectors API with real-world patterns
What - Introduced `Test.java` showcasing advanced usage of the `Collectors` utility in the Streams API. - Demonstrated 13 collector patterns with comments and examples: 1. toList → collect filtered results into a List. 2. toSet → unique collection, removes duplicates. 3. toCollection → collect into a specific collection (ArrayDeque). 4. joining → concatenate stream elements into a String with delimiter. 5. summarizingInt → compute count, sum, min, average, max. 6. averagingInt → directly calculate averages. 7. counting → count total elements. 8. groupingBy → classify/group by function (length, etc.), with downstream collectors. 9. partitioningBy → split into two groups by predicate (true/false). 10. mapping → transform before collecting. 11. toMap → create Map with key/value mappers. 12. toMap with merge function → handle duplicate keys (frequency counter). 13. reduce vs summingInt → comparison of manual vs collector-based summation. - Added extensive inline notes + revision guide at the end of file. Why - Collectors are a core part of Java’s functional style introduced in Java 8. - Understanding different collectors is essential for: - Data aggregation (counts, averages, groupings). - Data transformation pipelines (filtering, mapping). - Preparing data for APIs, reports, or dashboards. - This example acts as both a coding reference and revision guide for interviews or project work. Logic 1. **Collection Operations** - Used toList, toSet, toCollection to demonstrate how streams can materialize results in different container types. - Ensures developers see the difference between ordered duplicates (List) vs unique (Set). 2. **String & Numeric Summarization** - joining() simplifies concatenation of stream elements. - summarizingInt() and averagingInt() abstract common statistical operations, reducing boilerplate. 3. **Counting & Partitioning** - counting() is shorthand for size. - partitioningBy() is a specialized grouping for boolean conditions, ideal for classification tasks. 4. **Grouping & Mapping** - groupingBy() allows flexible downstream collectors (joining, counting). - mapping() provides transformation during collection stage. 5. **Map Creation & Frequency Analysis** - toMap() builds dictionaries (key → value). - Merge function `(x, y) -> x + y` elegantly counts word frequencies, replacing manual loops. 6. **Reduction vs Collector** - Showed reduce() vs summingInt() for summation: - reduce → general-purpose but verbose. - summingInt → cleaner, purpose-built for sums. Real-life applications - **Analytics & Reporting**: group employees by department, calculate averages, prepare dashboards. - **Log Processing**: count word/phrase occurrences, group by severity levels. - **Finance & E-commerce**: partition transactions (fraudulent vs safe), calculate order totals. - **APIs & Microservices**: transform backend data into DTO maps for response payloads. - **Data Science/ETL Pipelines**: summarize, clean, and aggregate large datasets with declarative pipelines. Notes - Collectors significantly reduce boilerplate (no explicit loops, maps). - Declarative style improves readability and maintainability. - groupingBy + downstream collectors = one of the most powerful patterns in stream processing. - This file doubles as a "Collectors revision cheat-sheet." Signed-off-by: https://github.com/Someshdiwan <[email protected]>
1 parent 2e3531b commit 7bce761

File tree

1 file changed

+160
-0
lines changed
  • Java 8 Crash Course/Java Collectors API/src

1 file changed

+160
-0
lines changed
Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
import java.util.*;
2+
import java.util.stream.Collectors;
3+
4+
public class Test {
5+
public static void main(String[] args) {
6+
// 1. Collecting to a List
7+
// Filter names starting with "A" and collect them into a List.
8+
List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "Ankit");
9+
List<String> res = names.stream()
10+
.filter(name -> name.startsWith("A"))
11+
.collect(Collectors.toList());
12+
System.out.println("Names starting with A: " + res);
13+
14+
15+
// 2. Collecting to a Set
16+
// Collects numbers into a Set, automatically removing duplicates.
17+
List<Integer> nums = Arrays.asList(1, 2, 2, 3, 4, 4, 5);
18+
Set<Integer> set = nums.stream().collect(Collectors.toSet());
19+
System.out.println("Unique Numbers (Set): " + set);
20+
21+
22+
// 3. Collecting to a Specific Collection
23+
// Collect into ArrayDeque instead of List/Set.
24+
ArrayDeque<String> deque = names.stream()
25+
.collect(Collectors.toCollection(ArrayDeque::new));
26+
System.out.println("Collected into ArrayDeque: " + deque);
27+
28+
29+
// 4. Joining Strings
30+
// Join names into one string, separated by commas.
31+
String concatenated = names.stream()
32+
.map(String::toUpperCase)
33+
.collect(Collectors.joining(", "));
34+
System.out.println("Concatenated Names: " + concatenated);
35+
36+
37+
// 5. Summarizing Data
38+
// Provides count, sum, min, average, max for integer stream.
39+
List<Integer> numbers = Arrays.asList(2, 3, 5, 7, 11);
40+
IntSummaryStatistics stats = numbers.stream()
41+
.collect(Collectors.summarizingInt(x -> x));
42+
System.out.println("Summary Stats: " + stats);
43+
44+
45+
// 6. Calculating Averages
46+
Double avg = numbers.stream().collect(Collectors.averagingInt(x -> x));
47+
System.out.println("Average: " + avg);
48+
49+
50+
// 7. Counting Elements
51+
Long count = numbers.stream().collect(Collectors.counting());
52+
System.out.println("Count: " + count);
53+
54+
55+
// 8. Grouping Elements
56+
List<String> words = Arrays.asList("hello", "world", "java", "streams", "collecting");
57+
System.out.println("Group by length: " +
58+
words.stream().collect(Collectors.groupingBy(String::length)));
59+
System.out.println("Group + join: " +
60+
words.stream().collect(Collectors.groupingBy(String::length, Collectors.joining(", "))));
61+
System.out.println("Group + count: " +
62+
words.stream().collect(Collectors.groupingBy(String::length, Collectors.counting())));
63+
64+
65+
// 9. Partitioning Elements
66+
// Partition words into two groups: >5 letters and <=5 letters.
67+
System.out.println("Partition: " +
68+
words.stream().collect(Collectors.partitioningBy(x -> x.length() > 5)));
69+
70+
71+
// 10. Mapping and Collecting
72+
// Transform words to uppercase before collecting.
73+
System.out.println("Mapped to Uppercase: " +
74+
words.stream().collect(Collectors.mapping(String::toUpperCase, Collectors.toList())));
75+
76+
77+
// 11. Creating a Map with toMap
78+
List<String> fruits = Arrays.asList("Apple", "Banana", "Cherry");
79+
Map<String, Integer> fruitMap = fruits.stream()
80+
.collect(Collectors.toMap(x -> x.toUpperCase(), x -> x.length()));
81+
System.out.println("Fruit Map: " + fruitMap);
82+
83+
84+
// 12. Handling Duplicate Keys with Merge Function
85+
List<String> words2 = Arrays.asList("apple", "banana", "apple", "orange", "banana", "apple");
86+
Map<String, Integer> freqMap = words2.stream()
87+
.collect(Collectors.toMap(k -> k, v -> 1, (x, y) -> x + y));
88+
System.out.println("Word Frequency: " + freqMap);
89+
90+
91+
// 13. Reduction vs Summing Collector
92+
Map<String, Integer> items = new HashMap<>();
93+
items.put("Apple", 10);
94+
items.put("Banana", 20);
95+
items.put("Orange", 15);
96+
97+
// Using reduce()
98+
int sumReduce = items.values().stream().reduce(0, Integer::sum);
99+
System.out.println("Sum using reduce(): " + sumReduce);
100+
101+
// Using summingInt()
102+
int sumCollector = items.values().stream().collect(Collectors.summingInt(x -> x));
103+
System.out.println("Sum using summingInt(): " + sumCollector);
104+
}
105+
}
106+
107+
/*
108+
Java Collectors API & Stream Operations – Revision Notes
109+
110+
1. Collectors.toList()
111+
→ Collects elements into a List (keeps duplicates, preserves order).
112+
113+
2. Collectors.toSet()
114+
→ Collects elements into a Set (removes duplicates, no guaranteed order).
115+
116+
3. Collectors.toCollection(Supplier)
117+
→ Collects elements into a user-defined collection (e.g., ArrayDeque).
118+
119+
4. Collectors.joining(delimiter)
120+
→ Concatenates elements into a single String with a delimiter.
121+
122+
5. Collectors.summarizingInt()
123+
→ Provides count, sum, min, average, max as IntSummaryStatistics.
124+
125+
6. Collectors.averagingInt()
126+
→ Directly calculates the average of numbers.
127+
128+
7. Collectors.counting()
129+
→ Returns the count of elements.
130+
131+
8. Collectors.groupingBy()
132+
→ Groups elements by classifier function.
133+
- groupingBy(String::length) → groups by string length
134+
- groupingBy(..., Collectors.joining()) → groups + joins
135+
- groupingBy(..., Collectors.counting()) → groups + counts
136+
137+
9. Collectors.partitioningBy(predicate)
138+
→ Splits into two groups (true/false) based on condition.
139+
140+
10. Collectors.mapping()
141+
→ Applies transformation before collecting.
142+
143+
11. Collectors.toMap(keyMapper, valueMapper)
144+
→ Creates a Map from stream elements.
145+
Example: {APPLE=5, BANANA=6, CHERRY=6}
146+
147+
12. Collectors.toMap with merge function
148+
→ Handles duplicate keys.
149+
Example: word frequency counter.
150+
151+
13. reduce() vs summingInt()
152+
- reduce(): Manual reduction, returns Optional or value.
153+
- summingInt(): Built-in collector, cleaner for summation.
154+
155+
Real-world usage:
156+
✔ Data transformation (filter/map/reduce).
157+
✔ Counting/grouping/partitioning records from DB.
158+
✔ Summaries for reporting dashboards.
159+
✔ Frequency analysis (logs, words, etc.).
160+
*/

0 commit comments

Comments
 (0)