How to convert a nested map to a list:
the map is:
Map<Integer, Map<Integer, Map<String, Double>>> list
the Object class is:
public class employee {
private Integer id;
private Integer number;
private String name;
private Double salary;
How to convert the nested map to the List?
Iterate over the map entries. For each inner map, also iterate over its entries, etc. For each entry in the innermost map, create an Employee and add it to your list.
The standard way to iterate over a map is to iterate over its entry set. vefthym’s answer shows you how to do this with a for loop. You may eloborate that code into what you need.
You may also do it with streams, provided you can use Java 8. I am assuming that your outer map maps from ID to an intermediate map (I would expect that intermediate map to hold exactly one entry; but my code will also work with more or fewer). The next map maps from number to a map from name to salary.
List<Employee> empls = list.entrySet()
.stream()
.flatMap(oe -> oe.getValue()
.entrySet()
.stream()
.flatMap((Map.Entry<Integer, Map<String, Double>> me) -> me.getValue()
.entrySet()
.stream()
.map((Map.Entry<String, Double> ie)
-> new Employee(oe.getKey(), me.getKey(), ie.getKey(), ie.getValue()))))
.collect(Collectors.toList());
That was meant to be oe for outer entry, that is, entry in the outer map. Similarly me for middle entry and ie for inner entry. I have renamed your class to begin with a capital E to follow Java naming conventions, and I have assumed a convenient constructor.
EDIT: vefthym, where did your answer go now that I was referring to it? I know you were not too happy about it yourself, it’s fair enough. In any case, the standard way to iterate over a map with a for loop is:
for (Map.Entry<Integer, String> currentEntry : yourMap.entrySet()) {
// do your stuff here
// use currentEntry.getKey() and currentEntry.getValue() to get the key and value from the current entry
}
You need to repeat the type arguments from your map declaration in the <> after Map.Entry.
Related
I have written my code using a nested HashMap and i'm trying to figure out how to put all values pointed by the key of the inner map into an ArrayList, in order to properly sort it.
My map looks like this:
HashMap<String, HashMap<String, Double>> vlist;
My idea was to create another HashMap with same key and value of the inner map shown before,
then populate it in this way.
HashMap<String, Double> vlistValues = new HashMap<>(vlist.values());
I get a compilation error, and i can figure out that the compiler doesn't know that the value of my outer map is a map itself, but reading the hashmap documentation i didn't find a method that fits my situation.
Basically i want to put all the values of the inner map declared hereHashMap<String ,HashMap<String, Double>> vlist; to a list like thisArrayList<Double> listOfValues;
If it wasn't clear i'm totally new to programming :-)
I'll show an example:
My map HashMap<String, Hashmap<String,Double>> represents the adjacency list of a weighted graph. I need to sort all the edges (as i'm trying to implement Kruskal's algorithm) and my idea was to put all the weights in an list doing something like this:
ArrayList<String> vertexList; //all the vertices of the graph
ArrayList<Double> weights;
HashMap<String, String> orderedEdges = new HashMap<>(); //here i put ordered edges
double min = Collections.min(weights); //i use this double to keep track of the minimum element in weights
for(String vertex1 : vertexlist){
makeSet(vertex1);
for(String vertex2 : ajacents(vertex1)){
if(getEdgeWeight(v1,v2) <= min){ //method "getEdgeWeight" is to retrieve weight of an edge
orderedEdges.put(v1,v2);
min = getEdgeWeight(v1,v2)
weights.remove(min) //i'm not sure this line is correct
}
}
}
Looking at some pseudo-code online i saw that it is able to make the disjoint sets and ordering the edges in the same for-loop. Probably my code is not efficent but i really don't know how to sort the edges without visiting all the graph. Ps i cannot use a priority queue but i perfectly know that what i'm trying to do is something similar
So you said:
Basically i want to put all the values of the inner map declared here HashMap<String ,HashMap<String, Double>> vlist; to a list like this ArrayList<Double> listOfValues
Here is the sample hashMap.
Map<String, Map<String, Double>> mm = Map.of("A",
Map.of("R", 1.2, "S", 3.4, "T", 3.8),
"B",
Map.of("S", 9.8, "V", 2.8),
"Z",
Map.of("P", 22.3));
System.out.println(mm);
Here's the map.
{Z={P=22.3}, B={S=9.8, V=2.8}, A={T=3.8, S=3.4, R=1.2}}
To convert to a List of doubles you can do this. Get a stream of the values (which are the inner maps), and then combine all the values in those maps into a common stream via a flatMap and then collect to a List.
List<Double> dubs =
mm.values().stream().flatMap(k -> k.values().stream()).collect(
Collectors.toList());
System.out.println(dubs);
Here's the list.
[22.3, 9.8, 2.8, 3.8, 3.4, 1.2]
If you want a Map<String, List<Doubles>> where the String is the key of the outer Map you can do this. Create a stream of entrySet of the outer map and pass it to a collector. The collector creates a map using the outer maps key and then takes the values of the inner map (which is a collection) and passes them as an argument to ArrayList<> to create a List.
Map<String, List<Double>> mapOfDubs =
mm.entrySet().stream().collect(Collectors.toMap(e -> e.getKey(),
e -> new ArrayList<>(e.getValue().values())));
System.out.println(mapOfDubs);
Here's the map.
{A=[1.2, 3.4, 3.8], B=[2.8, 9.8], Z=[22.3]}
From a map like HashMap<String, HashMap<String, Double>> vlist; you have
vlist.keys() a List<String> , which contains all the keys
vlist.values() a List<HashMap<String, Double>>, which contains all the map that are a value
To get a particular List<Double> you need a key, so select the inner map from which you'll read the doubles
HashMap<String, HashMap<String, Double>> outer = ...; // don't call a map *list*
HashMap<String, Double> inner = outer.get("mykey");
List<Double> values = new ArrayList<>(inner.values()); // as values() returns a Collection
I have a map of maps - Map> - collection.
I need to filter the map and get the outer map that has a given value for a given key of the inner map.
I tried some combinations, but it is not working.
How do I achieve this.
This is what I have tried
Map<String, Map<String, String>> originalMap = getOriginalMap();
String channelId = "channelIdVal";
Map<String, Map<String, String>> filteredMapForKey = originalMap.entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getKey,
e -> e.getValue().entrySet().stream().filter(innerMap -> innerMap.getValue().equalsIgnoreCase(channelId)).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue))));
Basically, I am expecting the filteredMapForKey to have a single entry whose inner map ( the value of the entry ) to contain a key whose value is channelId
How do I achieve that. The above code is returning the entire original map with same keys but empty inner maps except for the valid one. For the valid map, instead of returning the complete inner map, it is only return the map with the key and value of matching channel id
Thanks
Seems like there are two things to correct here:
The filter logic to filter in entries instead of filtering them out.
To filter only those outer entries for which inner map satisfies the condition stated.
You can achieve that as:
Map<String, Map<String, String>> filteredMapForKey = originalMap.entrySet()
.stream()
.filter(e -> e.getValue()
.values()
.stream()
.anyMatch(innerMapVal -> innerMapVal.equalsIgnoreCase(channelId)))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
This filters all the outer map entries such that, the inner map for them has a value that is equal(ignoreCase) to the given channelId and then collects these entries into a similar Map as the input.
I have below the class definition of Entry -
public class Entry {
private String key;
private String Value;
// getters and setters
// equals hashcode toString
}
I got List of Entry objects from database.
I want to group them based on key and values of the result Map should be Set<value>.
I tried and end up with the below code.
Map<String, Set<Entry>> groupedEntries =
entryList.findAll()
.stream()
.collect(Collectors.groupingBy(ek -> ek.getKey().toLowerCase(), Collectors.toSet()));
The problem with this code is the result type is Map<String, Set<Entry>> but I want to be Map<String, Set<String>>.
is it possible to do this in single collect?
use the mapping collector:
.collect(Collectors.groupingBy(ek -> ek.getKey().toLowerCase(),
Collectors.mapping(Entry::getValue, Collector.toSet())));
Disclaimer : I have already once posted such a question and it was marked duplicate. Please try and help me. I have gone through all previous methods on stackoverflow and none was of any help. All the methods mentioned to sort Map(Key,Values) didn't work in my case as I have one step further i.e. retrieving the attribute of the value. This time, I tried to go with full detail.
I've a Map (String,Object) in Java and I want to sort it using one of the attributes of the Object.
e.g. Suppose I have a class
class Entry
{
int id;
String name;
String address;
//Rest of the code
}
Now, I created a map
Map<String,Entry>
I want to sort the map by the attribute id of the class Entry (Entry.id)
Please help !
For example, I have three objects of Entry class
entry1 :
id=1
name="abc"
address="india"
entry2 :
id=2
name="xyz"
address="india"
entry3 :
id=3
name="pqr"
address="india"
Now, I have the Map initially as follows :
Key : Value
first: entry2
second: entry3
third : entry1
After sorting, it should be like
Key : Value
third : entry1
first: entry2
second: entry3
You can easily accomplish the task with the stream API:
Map<String, Entry> resultSet = myMap.entrySet()
.stream()
.sorted(Comparator.comparingInt(e -> e.getValue().getId()))
.collect(Collectors.toMap(Map.Entry::getKey,
Map.Entry::getValue,
(left, right) -> left,
LinkedHashMap::new));
Your requirement is typically a symptom of bad data-structure usage.
If you wanted the map to be sorted by an attribute of key objects, you would just write a custom comparator, but since you want to sort by values, it's a bit more complicated.
Try understanding answers to this question: Sort a Map<Key, Value> by values. And then try using a custom comparator in combination.
You can’t sort a map.
You can have a map that keeps its entries sorted, or you can sort a List<Map.Entry>.
Try this:
Map<String, Entry> map; // your map
Map<String, Entry> sorted = new TreeMap<>(Comparator.comparing(s -> map.get(s).getId());
sorted.putAll(map);
I have the following Object and a Map:
MyObject
String name;
Long priority;
foo bar;
Map<String, List<MyObject>> anotherHashMap;
I want to convert the Map in another Map. The Key of the result map is the key of the input map. The value of the result map ist the Property "name" of My object, ordered by priority.
The ordering and extracting the name is not the problem, but I could not put it into the result map. I do it the old Java 7 way, but it would be nice it is possible to use the streaming API.
Map<String, List<String>> result = new HashMap<>();
for (String identifier : anotherHashMap.keySet()) {
List<String> generatedList = anotherHashMap.get(identifier).stream()...;
teaserPerPage.put(identifier, generatedList);
}
Has anyone an idea? I tried this, but got stuck:
anotherHashMap.entrySet().stream().collect(Collectors.asMap(..., ...));
Map<String, List<String>> result = anotherHashMap
.entrySet().stream() // Stream over entry set
.collect(Collectors.toMap( // Collect final result map
Map.Entry::getKey, // Key mapping is the same
e -> e.getValue().stream() // Stream over list
.sorted(Comparator.comparingLong(MyObject::getPriority)) // Sort by priority
.map(MyObject::getName) // Apply mapping to MyObject
.collect(Collectors.toList())) // Collect mapping into list
);
Essentially, you stream over each entry set and collect it into a new map. To compute the value in the new map, you stream over the List<MyOjbect> from the old map, sort, and apply a mapping and collection function to it. In this case I used MyObject::getName as the mapping and collected the resulting names into a list.
For generating another map, we can have something like following:
HashMap<String, List<String>> result = anotherHashMap.entrySet().stream().collect(Collectors.toMap(elem -> elem.getKey(), elem -> elem.getValue() // can further process it);
Above I am recreating the map again, but you can process the key or the value according to your needs.
Map<String, List<String>> result = anotherHashMap.entrySet().stream().collect(Collectors.toMap(
Map.Entry::getKey,
e -> e.getValue().stream()
.sorted(comparing(MyObject::getPriority))
.map(MyObject::getName)
.collect(Collectors.toList())));
Similar to answer of Mike Kobit, but sorting is applied in the correct place (i.e. value is sorted, not map entries) and more concise static method Comparator.comparing is used to get Comparator for sorting.