Definition
- split("\\s+") splits a sentence into words by one or more whitespace characters (spaces, tabs, newlines).
- map(String::toLowerCase) normalizes case so "NEFT" and "neft" are treated as the same word.
- distinct() removes duplicates based on String's
equalsmethod, using O(n) internal memory. - sorted() produces alphabetically ordered output after dedup.
- toCollection(LinkedHashSet::new) preserves the order words were first seen while removing duplicates.
- The two approaches differ in output order: sorted gives alphabetical, LinkedHashSet gives first-occurrence order.
At National Bank of India, a transaction narration reads "NEFT transfer to savings NEFT credit from savings." The search index needs unique keywords. Splitting by spaces gives 8 words, but "NEFT" and "savings" appear twice. After dedup, 6 unique keywords remain for the index.
Understanding the Concepts
How do you extract unique words sorted alphabetically?
package com.bank.util;
import java.util.*;
import java.util.stream.Collectors;
public class UniqueWordsDemo {
public static void main(String[] args) {
String narration = "NEFT transfer to savings NEFT credit from savings";
// Unique words, sorted alphabetically
List<String> unique = Arrays.stream(narration.split("\\s+"))
.map(String::toLowerCase)
.distinct()
.sorted()
.toList();
System.out.println("Unique (sorted): " + unique);
}
}
Unique (sorted): [credit, from, neft, savings, to, transfer]
How do you preserve first-occurrence order?
// Unique words in first-seen order
List<String> ordered = Arrays.stream(narration.split("\\s+"))
.map(String::toLowerCase)
.collect(Collectors.toCollection(LinkedHashSet::new))
.stream()
.toList();
System.out.println("Unique (first-seen): " + ordered);
Unique (first-seen): [neft, transfer, to, savings, credit, from]
How is distinct() different from LinkedHashSet?
| Approach | Output Order | Memory |
|----------|-------------|--------|
| distinct().sorted() | Alphabetical | O(n) for distinct + O(n) for sort |
| distinct() alone | Encounter order (source order) | O(n) |
| toCollection(LinkedHashSet::new) | First-occurrence order | O(k) where k = distinct count |
distinct() alone already preserves encounter order in ordered streams. Adding sorted() reorders alphabetically. The LinkedHashSet approach is equivalent to distinct() for ordered streams but collects into a Set for downstream use.
What about punctuation?
// Handle punctuation: split by non-word characters
String withPunctuation = "Account-holder: Rajesh, Priya. Account-holder: Amit.";
List<String> words = Arrays.stream(withPunctuation.split("[^a-zA-Z]+"))
.map(String::toLowerCase)
.filter(s -> !s.isEmpty())
.distinct()
.toList();
// [account, holder, rajesh, priya, amit]
What are common mistakes?
WRONG: Splitting by a single space instead of \\s+.
// WRONG: split(" ") fails on multiple spaces or tabs
String messy = "NEFT transfer\tto savings";
String[] wrong = messy.split(" "); // produces empty strings!
CORRECT: Use \\s+ to handle any whitespace.
// CORRECT: \\s+ handles multiple spaces, tabs, newlines
String[] correct = messy.split("\\s+");
What should a senior engineer know?
distinct()uses an internalHashSetthat grows with the number of distinct elements. For very large text processing, consider streaming the text lazily withBufferedReader.lines()instead of loading it all into memory.- For locale-aware case normalization, use
toLowerCase(Locale.ROOT)to avoid the Turkish-i problem where"I".toLowerCase()produces a dotless i in Turkish locale. - The
splitmethod compiles the regex each time. For repeated calls, pre-compile withPattern.compile("\\s+").splitAsStream(sentence)for better performance.
Visual Overview
"NEFT transfer to savings NEFT credit from savings"
│
▼
split("\\s+")
[NEFT, transfer, to, savings, NEFT, credit, from, savings]
│
▼
map(toLowerCase)
[neft, transfer, to, savings, neft, credit, from, savings]
│
▼
distinct()
[neft, transfer, to, savings, credit, from] (6 unique)
│
▼
sorted()
[credit, from, neft, savings, to, transfer] (alphabetical)
Key Takeaway
Extracting unique words from a sentence uses split("\\s+") to tokenize, map(String::toLowerCase) for case-insensitive dedup, distinct() to remove duplicates, and sorted() or LinkedHashSet for ordering. The distinct() approach uses O(n) memory internally.
At National Bank of India, a narration indexer processes transaction descriptions. Eight words become six unique keywords for the search index. The LinkedHashSet approach preserves first-occurrence order (neft first because it appeared first), while sorted() gives alphabetical order.
Remember one sentence: split by whitespace, normalize case, then distinct gives unique words, with sorted or LinkedHashSet controlling the output order.
---