Requirement
Given a sentence comprising of one or multiple words separated by space (e.g. java, Hello World, aadsbbaba), return a sorted list of distinct characters excluding space
Solve this problem using Java Stream
Hint: Use String.split(“”)to split a string into a String[], then use String.charAt(0) to convert each single-char string to char
Discussion
This problem tests candidate’s knowledge of the following Stream methods:
Stream.of(...)orArray.stream(...)to convert an array of single-char string (e.g. fromstr.split("")) toStream<String>map(str -> str.charAt(0))to convertStringtoCharacter. Note: whileString.toCharArraycan readily convert aStringto anchar[], turning the resulting array to aCharacterstream isn’t straightforward due to lack of built-in support forchartype in Stream and Collection API. TheArrays.asList(str.toCharArray()orList.of(...)results in aList<char[]>insteaddistinct()to keep only 1 instance of each encountered charactersorted()to sort the encountered characters in their natural ordercollect(Collectors.toList())to collect stream elements into a list
Sample Solution
A sample solution is shown below. In addition to above operations, we only utilize an extra filter(...) operation to discard spaces from getting into our response
public static List<Character> distinctCharsStream2(String sentence) {
return Arrays.stream(sentence.split(""))
.map(s -> s.charAt(0))
.filter(i -> i != ' ')
.distinct()
.sorted()
.collect(Collectors.toList());
}
Recall again the use of String.split("") and String.charAt(0) instead of String.toCharArray(). Due to the lack of built-in support for char type in Stream and Collection API, Arrays.asList(sentence.toCharArray()) or List.of(sentence.toCharArray()) result in a List<char[]> instead of List<Character> that we need
Extra
Instead of a sentence string, candidate shall be given an list of words.
This modification results in mostly the same solution as the original problem, with 2 twists:
- Spaces are omitted
- Candidate may use
flatMapto merge characters from each word into a singleStream<Character>
words.stream()
.flatMap(word -> Stream.of(word.split("")))
.map(s -> s.charAt(0))
...
A small modification to the sample solution can lead us to the same flatMap(...) usage
return Arrays.stream(sentence.split(" "))
.flatMap(word -> Stream.of(word.split("")))
...
Imperative Solution
If we omit the Stream requirement, some candidate may derive an imperative solution using loop and Set
Set<Character> characters = new HashSet<>();
for (char c : sentence.toCharArray()) {
if (c == ' ') continue;
characters.add(c);
}
List<Character> result = new ArrayList<>(characters);
result.sort((c1, c2) -> c1 - c2);
return result;
There is nothing wrong with this approach. To some extend, I think it is even more understandable than the Stream-based one.
But as functional and reactive programming become more and more popular, so does the need to master Stream operations. If there are still time, I would politely ask the candidate to convert his/her codes to Stream.

distinct characters
Sample Codes
Checkout sample solutions and tests in my github
comments powered by Disqus