Java Programs›Java 8 Streams›Group Words by Length Using Streams

Group Words by Length Using Streams in Java

intermediate·  Java 8 Streams  ·  Streams

Problem

Grouping splits a collection into buckets that share a key — like SQL's GROUP BY — producing a Map from each key to the elements that have it.

Given a list of words, group them by their length, with the groups listed from shortest to longest.

Input
[sun, moon, star, sky, comet, planet, orbit]
Output
3=[sun, sky], 4=[moon, star], 5=[comet, orbit], 6=[planet]

Java Program

Java
import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.TreeMap; import java.util.stream.Collectors; public class GroupWordsByLength { public static void main(String[] args) { List<String> words = Arrays.asList("sun", "moon", "star", "sky", "comet", "planet", "orbit"); Map<Integer, List<String>> byLength = words.stream() .collect(Collectors.groupingBy( String::length, // the key each word is grouped under TreeMap::new, // sorted keys, so the output order is predictable Collectors.toList())); // what to collect inside each group byLength.forEach((length, group) -> System.out.println(length + " letters: " + group)); } }

Output

3 letters: [sun, sky] 4 letters: [moon, star] 5 letters: [comet, orbit] 6 letters: [planet]

Core Logic

groupingBy takes a classifier function that computes each element's key, and builds the map of buckets for you.

How It Works
  1. 1String::length is the classifier, so each word is filed under its length.
  2. 2TreeMap::new makes the result a sorted map, so the groups print in key order.
  3. 3Collectors.toList() decides what each bucket holds — here, the words themselves.
  4. 4forEach((length, group) -> ...) prints each key with its list.
sun and sky both have length 3, so they land in the same bucket, in the order they appeared.
💡

Key Point: The one-argument groupingBy(String::length) returns a HashMap, whose iteration order isn't guaranteed — pass a map factory when the order matters.

Complexity
Time Complexity: O(n log k)Space Complexity: O(n)

Why: Each of the n words is inserted into a TreeMap with k distinct keys, and every word is stored in some bucket.

Key Concepts

Collectors.groupingBy()TreeMapmethod referenceMap.forEach()

Approach 2: Counting Each Group

Java
import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.TreeMap; import java.util.stream.Collectors; public class GroupWordsByLengthCounting { public static void main(String[] args) { List<String> words = Arrays.asList("sun", "moon", "star", "sky", "comet", "planet", "orbit"); Map<Integer, Long> counts = words.stream() .collect(Collectors.groupingBy(String::length, TreeMap::new, Collectors.counting())); System.out.println(counts); } }

Output

{3=2, 4=2, 5=2, 6=1}

Core Logic

Swapping the downstream collector changes what each bucket holds — counting() stores how many words fell into it instead of the words themselves.

How It Works
  1. 1The classifier and map factory stay the same.
  2. 2Collectors.counting() replaces toList() as the downstream collector.
  3. 3The values become Long counts.
Lengths 3, 4 and 5 each have two words, and length 6 has one.
💡

Key Point: Other downstream collectors work the same way — summingInt, averagingDouble, mapping or joining — which makes groupingBy a mini reporting engine.

Complexity
Time Complexity: O(n log k)Space Complexity: O(k)

Why: Each word is still classified once, but only one counter per key is stored.

Key Concepts

Collectors.counting()downstream collector

Interview Questions

What map type does groupingBy return by default?

A HashMap. Pass a map factory such as TreeMap::new when the keys need to be sorted.

How do you collect only part of each element into the groups?

Use Collectors.mapping as the downstream collector, for example groupingBy(Person::getCity, mapping(Person::getName, toList())).

Learn the Concept

Related Programs