I have a list of String.
I want to store each string as key and the string's length as value in a Map (say HashMap).
I'm not able to achieve it.
List<String> ls = Arrays.asList("James", "Sam", "Scot", "Elich");
Map<String,Integer> map = new HashMap<>();
Function<String, Map<String, Integer>> fs = new Function<>() {
@Override
public Map<String, Integer> apply(String s) {
map.put(s,s.length());
return map;
}
};
Map<String, Integer> nmap = ls
.stream()
.map(fs).
.collect(Collectors.toMap()); //Lost here
System.out.println(nmap);
All strings are unique.
CodePudding user response:
There's no need to wrap each and every string with its own map, as the function you've created does.
Instead, you need to provide proper arguments while calling Collectors.toMap() :
keyMapper- a function responsible for extracting a key from the stream element.valueMapper- a function that generates a value from the stream element.
Hence, you need the stream element itself to be a key we can use Function.identity(), which is more descriptive than lambda str -> str, but does precisely the same.
Map<String,Integer> lengthByStr = ls.stream()
.collect(Collectors.toMap(
Function.identity(), // extracting a key
String::length // extracting a value
));
In case when the source list might contain duplicates, you need to provide the third argument - mergeFunction that will be responsible for resolving duplicates.
Map<String,Integer> lengthByStr = ls.stream()
.collect(Collectors.toMap(
Function.identity(), // key
String::length, // value
(left, right) -> left // resolving duplicates
));
CodePudding user response:
You said there would be no duplicate Strings. But if one gets by you can use distinct() to ensure it doesn't cause issues.
a-> ais a shorthand for using the stream value. Essentially a lambda that returns its argument.distinct()removes any duplicate strings
Map<String, Integer> result = names.stream().distinct()
.collect(Collectors.toMap(a -> a, String::length));
The other alternative for handling duplicates is in Alexander Ivanchenko's second toMap answer.
If you want to get the length of a String, you can do it immediately as someString.length(). But suppose you want to get a map of all the Strings keyed by a particular length. You can do it using Collectors.groupingBy() which by default puts duplicates in a list. In this case, the duplicate would be the length of the String.
- use the
lengthof the string as a key. - the value will be a
List<String>to hold all strings that match that length.
List<String> names = List.of("James", "Sam", "Scot",
"Elich", "lucy", "Jennifer","Bob", "Joe", "William");
Map<Integer, List<String>> lengthMap = names.stream()
.distinct()
.collect(Collectors.groupingBy(String::length));
lengthMap.entrySet().forEach(System.out::println);
prints
3=[Sam, Bob, Joe]
4=[Scot, lucy]
5=[James, Elich]
7=[William]
8=[Jennifer]
