How to sort two HashMap which has common key? - java

I have two HashMap which look like this,
public HashMap<Integer, String> scoreName = new HashMap<Integer, String>();
public HashMap<Integer, Integer> scoreValue = new HashMap<Integer, Integer>();
Here both HashMap has common key. I want to sort scoreValue HashMap and scoreName HashMap where scoreName HashMap should also be sorted according scoreValue.
Example:
scoreValue = 5,1,7,7,9
scoreName = a, b , c, d,e
after sorting scoreValue = 1,5,7,7,9
sorting scoreName = b,a,c,d,e
I can sort my scoreValue
List sortedKeys = new ArrayList(scoreValue.values());
Collections.sort(sortedKeys);
but this is not the solution that I am looking for !

HashMaps are unordered collections, so you cannot sort them.
What would be better here is to have a Score object which contains the key, name and value as member variables.
Then just have a simple List<Score> and then call Collections.sort() on the list.
If you need the fast id look-up as well then you can have as HashMap of id to Score. Iterate over the list when you need them in order. Look them up in the map to find the score and name for a given id.
If each Score object wants to know it's ranking in the list then you can loop through the sorted collection after doing the sort and have a variable in the Score object to store that as well.
TreeMap/TreeSet might also be helpful in this case but they don't allow random access (i.e. who is at position 3) and TreeMap sorts based on the key in the map, not the value.

HashMap has no ordering of any sort. You can use a LinkedHashMap or you can use trees (or data structures similar to trees). Using a LinkedHashMap is very similar to using a HashMap.

Related

How to sort a hashmap consisting of Class objects as key and another hashmap as value in java?

I'm fairly new to Java and found some resources on how to sort the hashmap based on certain attributes of the key object. However, I'm still not able to figure out what I'm missing in my code.
I would really appreciate any help.
I have a Monkey class, one of whose attribute is name. And, the location of the monkey could be either {"isolationId" : someInteger} or {"enclosureId": someInteger}.
And my hashmap looks like this:
HashMap<Monkey, HashMap<String, Integer>> monkeyAndLocation = new HashMap<Monkey, HashMap<String, Integer>>();
Now, I want to sort the monkeyAndLocation with respect to the name attribute of the monkey object.
Can you help me with this?
If you want a sorted copy of your Map, you could just do (apparently your map should be filled with something):
private Map<Monkey, HashMap<String, Integer>> sortMonkeys(){
Map<Monkey, HashMap<String, Integer>> monkeyAndLocation = new HashMap<Monkey, HashMap<String, Integer>>();
return new TreeMap<>(monkeyAndLocation);
}
// the Monkey class should reside in a file of its own!
private static class Monkey implements Comparable<Monkey>{
#Override
public int compareTo(Monkey other){
return name.compareTo(other.name);
}
String name;
Integer isolationId;
Integer enclosureId;
}
The TreeMap sorts by the natural order of its keys. So by implementing Comparable you set the natural order to the order of the names of the monkeys.
First things first: You cannot sort a HashMap. Technically you can't sort any Map type, but some map types can control the iteration order of their entries to emulate being sorted.
A TreeMap maintains order of its entries, so load one with the contents of your map, providing the Comparator it should use to order its entries.
First change the definition of your map to its abstract type - see Liskov substitution principle:
Map<Monkey, Map<String, Integer>> monkeyAndLocation = new HashMap<>();
To convert this map to one that is "sorted" (iterates in sort order):
Map<Monkey, Map<String, Integer>> monkeyAndLocationSorted
= new TreeMap<>(Comparators.comparing(Monkey::getName));
monkeyAndLocationSorted.putAll(monkeyAndLocation);

Why doesn't arrayList sort in java even after using collections.reverse()

I am trying to sort a hashmap based on its values,
The way I am doing this is separating the keyset and valueset of the hashmap into two arrayList
,then sorting the lists individually and then adding the values in a new haspMap after some comparison operations
but for some reason collection.reverse(LIST), won't sort the list in descending order
Here is my code:
public LinkedHashMap sortHashMapByValuesD(HashMap passedMap)
{
ArrayList <Integer>mapKeys = new ArrayList<Integer>(passedMap.keySet());
ArrayList <Double>mapValues= new ArrayList<Double>(passedMap.values());
Collections.reverse(mapValues);
Collections.reverse(mapKeys); //>>**Here the list won't sort for some reason**
LinkedHashMap<Integer, Double> sortedMap = new LinkedHashMap<Integer, Double>();
Iterator valueIt = mapValues.iterator();
while (valueIt.hasNext()) {
Object val = valueIt.next();
//System.out.println(val);
Iterator keyIt = mapKeys.iterator();
while (keyIt.hasNext()) {
Object key = keyIt.next();
Double comp1 =(Double)passedMap.get(key);
Double comp2 = (Double)val;
if (comp1==comp2){
passedMap.remove(key);
mapKeys.remove(key);
sortedMap.put((Integer)key,(Double)val);
break;
}
}
}
return sortedMap;
}
Thanks in advance
HashMaps are hashed, not sorted. In particular, HashMap<K, V> does not implement the SortedMap<K, V> interface. If you want a map sorted by key, try TreeMap, or any other implementation of SortedMap.
Maps sorted by index are not commonly requested and not directly supported within rt.jar. You can't even call them SortedMaps, since a map sorted by values is (almost) certainly not sorted by keys. While you can implement a map that is sorted by value, you may find that a slightly different approach fits the bill while sticking to the philosphies of java's collections framework. Try creating a map-backed collection or iterator, that provides the ordering you require, and uses your original HashMap as its store.
A much simpler solution would be to
Set<Double> sortedSet = new TreeSet<Double>(yourPreferredComparator);
sortedSet.addAll(passedMap.values());
However you would lose any duplicated values with this solution.

How to sort a Map by Value (ArrayList) size in Java?

I have the following Map:
Map<String, List<String>> map = new HashMap<String, List<String>>();
which is filled with pairs of keys and values.
For example: key = student name and value = family members names.
I want to sort the map by the size of the list of strings. I have tried implementing Comparator with a TreeMap but I got an error so I switched back to HashMap. Any ideas?
You should use the HashMap unordered, and then each time you want to order, put all the values of the HashMap into a TreeMap, using a Comparator that has the HashMap as a variable.
Then, for each key you compare, you get the value of the HashMap (the list) and check the list size. So you compare by the list sizes, returning -1, 0 or 1 depending on the case.
Once you finish what you need, you discard that TreeMap.
If you try to use only a TreeMap, then you'll see that you are ordering the keys according to a value that is not a property of such key. In this case, the length of the value (a list). So, there may exist a function that increases the length of the list, and the TreeMap won't even notice.
Some code:
public class ListSizeComparator implements Comparator<String> {
private final Map<String, List<String>> map;
public ListSizeComparator(final Map<String, List<String>> map) {
this.map = map;
}
#Override
public int compare(String s1, String s2) {
//Here I assume both keys exist in the map.
List<String> list1 = this.map.get(s1);
List<String> list2 = this.map.get(s2);
Integer length1 = list1.size();
Integer length2 = list2.size();
return length1.compareTo(length2);
}
}
The solution is more or less identical to https://stackoverflow.com/a/8897384/869736, but all you need to do is write a Comparator that compares lists by their length.
Comparator<List<String>> lengthComparator = new Comparator<List<String>>() {
public int compare(List<String> a, List<String> b) {
return a.size() - b.size();
// size() is always nonnegative, so this won't have crazy overflow bugs
}
};
and then just use the solution outlined there.
I see three choices here:
Sort the map contents every time you need - if it's not too often that it's OK.
In addition to the map store other auxiliary structure with desired order, for example TreeMap<Integer, List<String>> (key - number of family members, value - list of students).
May be you don't need at all your map as you described it and following map will be sufficient: TreeMap<Integer, Map<String, List<String>>> (key - number of family members, value - part of your original map containing students with number of family members equal $key).

Get 3 highest values from Map<String,String>

I have a Map<String,String> which has entries like "User1","43". Now I want a "Top 3" of the highest values.
It would be easier with a Map<String,Integer>, but due to technical limitations I can just grab the Map as a <String,String>.
What's the most efficient way to convert a <String,String> map to a <String,Int> one and then sort it?
To convert from <String, String> to <String, Integer> you can use:
Map<String, Integer> treemap = new HashMap<String, Integer>();
for (Entry<String, String> entry : entries) {
treemap.put(entry.getKey(), Integer.parseInt(entry.getValue()));
}
However, then you will have to iterate the Map again. If you don't need the whole map, but rather just the top 3, then you can simply iterate the entries and get the top three by comparison.
Or you can reverse the key and value and use a TreeMap<Integer, String> with a Comparator, if you need both the top elements and the whole data.
There are a few ways:
Create SortedMap, e.g. TreeMap with a custom -anonymous- Comparator which performs comparisons by looking up the keys it gets in the compare() method call against the values in the original map.
Populate it with all key/value entries in the original through addAll() method.
Watch the map being sorted by value.
Grab the head/tail (depending on how your comparator sorts)
Similar to above:
Create a TreeSet of keys with a custom comparator as above...
Populate it with the keySet() of your original map.
Grab the head/tail set of the keys.
Create a new Map from those keys and value from the original map...
You could just put the values in a List and sort it:
ArrayList<Integer> highest = new ArrayList<Integer>();
for (String value : map.values()) {
highest.add(Integer.parseInt(value));
}
Collections.sort(highest);
for(int i = highest.size() - 1; i >=0 && i > highest.size()-4; i--){
System.out.println(highest.get(i));
}
If the map is very large it might be better to iterate through it and only select the 3 highest values without sorting the whole list.
You could iterate through the values of the Map (with Map.values()), converting each to an Integer (with Integer.getInteger(String s)), and keeping track of the top 3 you see.
Or, you could do as above but instead of keeping track of the top 3, make a LinkedList and insert each Integer at the correct place (traverse the LinkedList until you find where the Integer should be inserted).

How can I sort the keys of a Map in Java?

This is a very basic question, I'm just not that good with Java. I have a Map and I want to get a list or something of the keys in sorted order so I can iterate over them.
Use a TreeMap, which is an implementation of the SortedMap interface. It presents its keys in sorted order.
Map<String, Object> map = new TreeMap<String, Object>();
/* Add entries to the map in any order. */
...
/* Now, iterate over the map's contents, sorted by key. */
for (Map.Entry<String, ?> entry : map.entrySet()) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}
If you are working with another Map implementation that isn't sorted as you like, you can pass it to the constructor of TreeMap to create a new map with sorted keys.
void process(Map<String, Object> original) {
Map<String, Object> copy = new TreeMap<String, Object>(original);
/* Now use "copy", which will have keys in sorted order. */
...
}
A TreeMap works with any type of key that implements the Comparable interface, putting them in their "natural" order. For keys that aren't Comparable, or whose natural ordering isn't what you need, you can implement your own Comparator and specify that in the constructor.
You have several options. Listed in order of preference:
Use a SortedMap:
SortedMap<whatever> myNewMap = new TreeMap<whatever>(myOldMap);
This is vastly preferable if you want to iterate more than once. It keeps the keys sorted so you don't have to sort them before iterating.
There is no #2.
There is no #3, either.
SortedSet<whatever> keys = new TreeSet<whatever>(myMap.keySet());
List<whatever> keys = new ArrayList<whatever>(myMap.keySet());
Collections.sort(keys);
The last two will get you what you want, but should only be used if you only want to iterate once and then forget the whole thing.
You can create a sorted collection when iterating but it make more sense to have a sorted map in the first place. (As has already been suggested)
All the same, here is how you do it.
Map<String, Object> map;
for(String key: new TreeSet<String>(map.keySet()) {
// accessed in sorted order.
}
Apart from the methods mentioned in other answers, with Java 8 streams, another shorthand to get a sorted key list from a map would be -
List<T> sortedKeys = myMap.keySet().stream().sorted().collect(Collectors.toList());
One could actually get stuff done after .sorted() as well (like using a .map(...) or a .forEach(...)), instead of collecting it in the list and then iterating over the list.

Categories