With a little reworking of the method you can use a method reference. Since you didn't specify if a set
was required, I am using a map
as it offers some efficiencies.
List<String> listColors = Arrays.asList("Red", "blue", "green",
"green");
I am calling the method printOccurrences
since that is what you are doing. It takes a Supplier<Stream<String>>
as the parameter. The stream is obtained in the method by using get()
.
printOccurrences(listColors::stream);
prints
Red : 1, blue : 1, green : 2
Using Collections.frequency
is ill advised since you must traverse the entire list for each specified object. Using a Map
to compute frequencies is a more common technique as it does it in a single pass over the list. For each color string, Collectors.groupingBy along with Collectors.counting will compute the frequency for each map entry pair of <String, Long>
. The entries are then streamed to obtain the collected data and joinedinto a string for printing (the format of which can be altered as required). I used a LinkedHashMap
supplier to preserve the order of colors as they are processed. If not required or desired, it can be removed.
So in order
- get the stream and compute the frequencies using
groupingBy
- then stream the entry set, extracting the key(color String) and value(frequency) and format for joining. I am joining each pair with
", "
.
- all of the above is then passed to
System.out.println
.
static void printOccurrences(Supplier<Stream<String>> stream) {
System.out.println(stream.get()
.collect(Collectors.groupingBy(color -> color,
LinkedHashMap::new, Collectors.counting()))
.entrySet().stream().map(e -> e.getKey() + " : " + e.getValue())
.collect(Collectors.joining(", ")));
}
Some final notes.
The method above can also be easily altered to return the string for printing and/or take the list as an argument and just stream it there without using a Supplier.
Unless you want "Red"
to be different than "red"
you should convert to a common case, otherwise they will be treated as different colors. For something like this, title case might be a nice choice so it can be done as follows:
static String toTitleCase(String str) {
return str.substring(0,1).toUpperCase() + str.substring(1).toLowerCase();
}
Then change a -> a
in groupingBy
to a->toTitleCase(a)