This question already has answers here:
Using streams, how can I map the values in a HashMap?
(4 answers)
Closed 8 years ago.
Say I have a Map<String, Integer>. Is there an easy way to get a Map<String, String> from it?
By easy, I mean not like this:
Map<String, String> mapped = new HashMap<>();
for(String key : originalMap.keySet()) {
mapped.put(key, originalMap.get(key).toString());
}
But rather some one liner like:
Map<String, String> mapped = originalMap.mapValues(v -> v.toString());
But obviously there is no method mapValues.
You need to stream the entries and collect them in a new map:
Map<String, String> result = map.entrySet()
.stream()
.collect(Collectors.toMap(Entry::getKey, e -> String.valueOf(e.getValue()));
The easiest way to do so is:
Map<String, Integer> map = new HashMap<>();
Map<String, String> mapped = map.entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getKey, entry -> String.valueOf(entry.getValue())));
What you do here, is:
Obtain a Stream<Map.Entry<String, Integer>>
Collect the results in the resulting map:
Map the entries to their key.
Map the entries to the new values, incorporating String.valueOf.
The reason you cannot do it in a one-liner, is because the Map interface does not offer such, the closest you can get to that is map.replaceAll, but that method dictates that the type should remain the same.
Related
I have a nested map Map<String, Map<String, List<ObjectA>>> passed to me, and I want to change it to type Map<String, Map<String, Set<ObjectA>>>, what is the easiest way to do so in Java using stream? I have tried to use Collectors.groupingBy but can't get it working.
The best way is you have to iterate through each entry in outer map and inner map, and then convert the inner map entry value List<ObjectA> to Set<ObjectA>
Map<String, Map<String, Set<ObjectA>>> resultMap = map.entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue().entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getKey, val -> new HashSet<>(val.getValue())))));
Note : If you are converting List to HashSet then you will not maintain same order, so you can choose LinkedHashSet over HashSet to maintain order
Map<String, Map<String, Set<ObjectA>>> resultMap = map.entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue().entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getKey, val -> new LinkedHashSet<>(val.getValue())))));
This question already has an answer here:
How to flatten List of Maps in java 8
(1 answer)
Closed 3 years ago.
I have below list of Map.
Map<String,String> map1 = new HashMap<>(); map1.put("DAY1","40T"); map1.put("DAY2","60T");
Map<String,String> map2 = new HashMap<>(); map2.put("DAY5","70T"); map2.put("DAY6","90T");
Map<String,String>[] mapArr= new Map[] {map1,map2};
List<Map<String,String>> lstOfMaps = Arrays.asList(mapArr);
How to convert the above lstOfMaps as Map<String,String> using java8.
Where Keys are DAY1,DAY2,DAY5,DAY6 and Values will be 40T,60T,70T,90T
I have tried in cople of ways but it was lengthy using a for loop. Trying to use lambdas and streams now.
The easiest solution would be to take the entry stream of each map in the list, flatten them into one stream, and collect that back into a map:
return lstOfMaps.stream().flatMap(map ->
map.entrySet().stream()
).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
This question already has answers here:
How to convert Map<String, String> to Map<Long, String> ? (option : using guava)
(6 answers)
Closed 4 years ago.
I have a Map<String, String> object. I want to have it sorted by the keys, but the keys should be seen as integer. I just created an TreeMap<Integer, String>(myMapObject).
But this obviously does not work. How can I create a new TreeMap and change the keys from String to Integer?
You can use Collectors.toMap in Java 8:
Map<Integer, String> map1 = map.entrySet().stream().collect(Collectors.toMap(entry -> Integer.parseInt(entry.getKey()), Map.Entry::getValue, (a, b) -> b));
Or below traditional approach:
Map<Integer, String> map1 = new HashMap<>();
for(final Map.Entry<String, String> entry : map.entrySet()){
map1.put(Integer.parseInt(entry.getKey()), entry.getValue());
}
This question already has answers here:
How can I sort a Map according to the parameters of its values? [duplicate]
(3 answers)
Closed 6 years ago.
I'm using the solution from this question to sort the String values in a LinkedHashMap. However the sorting simply doesn't work. Here is the code I wrote.
Map<Integer, String> sortedMap = myMap.entrySet().stream()
.sorted(Map.Entry.comparingByValue())
.collect(Collectors.toMap(Map.Entry<Integer, String>::getKey,
Map.Entry<Integer, String>::getValue));
myMap = new LinkedHashMap<Integer, String>(sortedMap);
The weird thing is that it is sorting the Integerkeys when both comparingByValue and comparingByKey methods are used. So it definitely is sorting, just not the String values but in both cases the Integer keys. I don't understand what I'm doing wrong here.
The toMap collector you are using put the elements in an HashMap, so sorting does not help here since you end up putting them in a non-ordered collection.
Use the overloaded toMap method, and supply a LinkedHashMap as concrete instance, i.e:
Map<Integer, String> sortedMap =
myMap.entrySet()
.stream()
.sorted(Map.Entry.comparingByValue())
.collect(Collectors.toMap(Map.Entry::getKey,
Map.Entry::getValue,
(a, b) -> a, //or throw an exception
LinkedHashMap::new));
My guess would be that Collectors.toMap is collecting them in an unordered map, immediately destroying the ordering.
Try collecting them directly in a LinkedHashMap:
LinkedHashMap<Integer, String> newMap = new LinkedHashMap<>();
Map<Integer, String> sortedMap = myMap.entrySet().stream()
.sorted(Map.Entry.comparingByValue())
.collect((k, v) -> newMap.put(k, v));
myMap = newMap;
As for why the integer keys are sorted: this is probably mere coincidence, based on how the HashMap is bucketing the keys.
I have a list that I need to custom sort and then convert to a map with its Id vs. name map.
Here is my code:
Map<Long, String> map = new LinkedHashMap<>();
list.stream().sorted(Comparator.comparing(Building::getName)).forEach(b-> map.put(b.getId(), b.getName()));
I think this will do the job but I wonder if I can avoid creating LinkedHashMap here and use fancy functional programming to do the job in one line.
You have Collectors.toMap for that purpose :
Map<Long, String> map =
list.stream()
.sorted(Comparator.comparing(Building::getName))
.collect(Collectors.toMap(Building::getId,Building::getName));
If you want to force the Map implementation that will be instantiated, use this :
Map<Long, String> map =
list.stream()
.sorted(Comparator.comparing(Building::getName))
.collect(Collectors.toMap(Building::getId,
Building::getName,
(v1,v2)->v1,
LinkedHashMap::new));