Reputation: 12451
I have some code that splits a String of letters, make a List with that and
later, populate a LinkedHashMap of Character
and Integer
with the letter and its frequency. The code is as following,
List<String> values = Arrays.asList((subjects.split(",")));
for (String value : values) {
char v = value.charAt(0);
map.put(v, map.containsKey(v) ? map.get(v) + 1 : 1);
}
map.put('X', 0);
How can I write it concisely with Java 8 ? Thanks.
Upvotes: 5
Views: 229
Reputation: 50746
Try this:
LinkedHashMap<Character, Long> counts = Pattern.compile(",")
.splitAsStream(subjects)
.collect(Collectors.groupingBy(
s -> s.charAt(0),
LinkedHashMap::new,
Collectors.counting()));
If you must have an Integer
count, you can wrap the counting collector like this:
Collectors.collectingAndThen(Collectors.counting(), Long::intValue)
Another option (thanks @Holger):
Collectors.summingInt(x -> 1)
As a side note, you could replace your looping update with this:
map.merge(v, 1, Integer::sum);
Upvotes: 9
Reputation: 425278
One liner:
Map<String, Long> frequency = Arrays.stream(input.split("(?<=.)\\W*"))
.collect(Collectors.groupingBy(s -> s, Collectors.counting()));
This counts all "word" characters (letters and digits).
Upvotes: 3
Reputation: 7322
So you are looking for something like:
Map<Character, Integer> result = new LinkedHashMap<>();
Arrays.asList(subjects.split(""))
.stream().map(s -> s.charAt(0))
.forEach(c -> result.put(c, result.containsKey(c) ? result.get(c) + 1 : 1));
and a better solution is
Map<Character, Integer> result = new LinkedHashMap<>();
subjects.chars().mapToObj(c->(char)c)
.forEach(c -> result.put(c, result.containsKey(c) ? result.get(c) + 1 : 1));
Upvotes: 0