How can I order a HashMap by an Integer key? [duplicate] - java

I have the following hashmap in java:
{B046=0.0, A061=3.0, A071=0.0, B085=0.0, B075=3.0, B076=9.0, B086=3.0, B095=0.0, B096=0.0, A052=0.0, B066=0.0, B056=9.0, B065=0.0, B055=9.0}
How should I go about sorting the hashmap such that the Alphabet, followed by the numerical figures are taken into account?
The resulting hashmap should look like this:
{A052=0.0,A061=3.0,A071=0.0,B046=0.0,B055=9.0,B056=9.0,B065=0.0,B066=0.0,B075=3.0,B076=9.0,B085=0.0,B086=3.0,B095=0.0,B096=0.0}
Appreciate the help!

Use sorted TreeMap:
Map<String, Float> map = new TreeMap<>(yourMap);
It will automatically put entries sorted by keys. I think natural String ordering will be fine in your case.
Note that HashMap due to lookup optimizations does not preserve order.

Use a TreeMap with a custom comparator.
class MyComparator implements Comparator<String>
{
public int compare(String o1,String o2)
{
// Your logic for comparing the key strings
}
}
TreeMap<String, Float> tm = new TreeMap<String , Float>(new MyComparator());
As you add new elements, they will be automatically sorted.
In your case, it might not even be necessary to implement a comparator because String ordering might be sufficient. But if you want to implement special cases, like lower case alphas appear before upper case, or treat the numbers a certain way, use the comparator.

TreeMap is your best bet for these kind of sorting (Natural). TreeMap naturally sorts according to the keys.
HashMap does not preserve insertion order nor does it sort the map. LinkedHashMap keeps the insertion order but doesn't sort the map automatically. Only TreeMap in the Map interface sorts the map according to natural order (Numerals first, upper-case alphabet second, lower-case alphabet last).

Use a TreeMap, although having a map "look like that" is a bit nebulous--you could also just sort the keys based on your criteria and iterate over the map, retrieving each object.

Use TreeMap (Constructor):
Map<String, Float> sortedMap = new TreeMap<>(yourMap);
Use TreeMap (PutAll method):
Map<String, Float> sortedMap = new TreeMap<>();
sortedMap.putAll(yourMap);
Implementation of Map interface:
TreeMap - Automatically sort the keys in ascending order while inserting.
HashMap - Order of insertion won't be maintained.
LinkedHashMap - Order of insertion will be maintained.

Just use a TreeMap. It implements the SortedMap interface, and thus automatically sorts the keys it contains. Your keys can just be sorted alphabetically to get the desired result, so you don't even need to provide a comparator.
HashMaps are never sorted. The only thing you coulkd do with a HashMap is get all the keys, and store them in a sorted set or in a List and sort the List.

Using the TreeMap you can sort the Map.
Map<String, String> map = new HashMap<String, String>();
Map<String, String> treeMap = new TreeMap<String, String>(map);
//show hashmap after the sort
for (String str : treeMap.keySet()) {
System.out.println(str);
}

You can use TreeMap which will store values in sorted form.
Map <String, String> map = new TreeMap <String, String>();

TreeMap will automatically sort in ascending order. If you want to sort in descending order, use the following code:
Copy the below code within your class and outside of the main execute method:
static class DescOrder implements Comparator<String> {
#Override
public int compare(String o1, String o2) {
return o2.compareTo(o1);
}
}
Then in your logic:
TreeMap<String, String> map = new TreeMap<String, String>(new DescOrder());
map.put("A", "test1");
map.put("C", "test3");
map.put("E", "test5");
map.put("B", "test2");
map.put("D", "test4");

Related

How do I create a List<Map.Entry<String, Integer>> out of a Map<String, Integer>?

So I know how to create a List of Map values
new ArrayList<String, Integer>(map.getValues());
Or from entry set map.entrySet()
However there doesn't seem to be a similar way to add a list of Map.Entry<String, Integer>
Is there a way to do this so I can write it all in just a return statement?
Map<String, Integer> map = new TreeMap<String, Integer>();
public List<Map.Entry<String, Integer>> getWordList(){
return new ArrayList<Map.Entry<String, Integer>>(map);
}
This doesn't work. But what does?
entrySet returns a Set and not a List, which means that the map's keys may or may not be in order.
However, in the case of TreeMap the JavaDoc says the following about it:
Returns a Set view of the mappings contained in this map.
The set's iterator returns the entries in ascending key order.
Apparently, entrySet() guarantees the mappings to be in the same order as the TreeMap. In short, you could just use it anywhere where a Collection is required. Creating a List is then trivial:
new ArrayList<>(map.entrySet())
or
List.copyOf(map.entrySet())

How to sort HashMap by referring another HashMap

I have two HashMap in Java.
First one contains a key and its value. Where second contains an evaluation index (order) of that keys. I want to sort the first map by referring to the second map.
First HashMap <key, value>
<"C","ccc">
<"D","ddd">
<"A","aaa">
<"B","bbb">
Second HashMap <key, value>
<"0","A">
<"1","B">
<"2","C">
<"3","D">
Result should be
<"A","aaa">
<"B","bbb">
<"C","ccc">
<"D","ddd">
Looping this two map and checking comparing keys is simple but not efficient. Any efficient idea?
You can use Java Stream API. First, sort the second map entrySet by key then map second map's value as key and get first map's value by value of the second map and then collect as LinkedHashMap using Collectors.toMap
secondMap.entrySet().stream()
.sorted(Comparator.comparing(Map.Entry::getKey))
.collect(Collectors.toMap(Map.Entry::getValue, k -> firstMap.get(k.getValue()),
(x, y) -> y, LinkedHashMap::new));
If you use LinkedHashMap/TreeMap ordered by key for the second map then you don't need to sort the keys. See demo here
First of all HashMap is not ordered collections. The key-value pairs in HashMap are ordered based on the value of hashCode() result of keys. So I would say you can't keep sorted values in HashMap.
Instead, you can use LinkedHashMap - it will be ordered with order of insertion.
And for your solution, i would do:
HashMap<String, String> firstMap = ...
HashMap<String, String> secondMap = ...
LinkedHashMap<String, String> orderedMap = new LinkedHashMap<>();
for (int i = 0; i < secondMap.size(); ++i) {
String key = secondMap.get(String.valueOf(i));
orderedMap.put(key, firstMap.get(key));
}
Did not run this code, but it should work.
Alternatively, you can use TreeMap that is ordered based on Comparable interface of the keys.
And to answer what is better to use - TreeMap or LinkedHashMap - depends on how actually you are using this map later. In most cases LinkedHashMap is enough, although if you need to, for example, get the closest greater element to some key, then TreeMap is a choice.
There are some comparison between HashMap and TreeMap
What is the difference between a HashMap and a TreeMap?
Traverse the values of secondMap and collect the related key, value set in the map:
Map<String, String> result = secondMap.values().stream()
.collect(Collectors.toMap(Function.identity(), firstMap::get, (x,y)-> x, LinkedHashMap::new));
Try this:
Map<String, String> firstMap = new HashMap<>();
firstMap.put("C", "ccc");
firstMap.put("D", "ddd");
firstMap.put("A", "aaa");
firstMap.put("B", "bbb");
Map<String, String> secondMap = new HashMap<>();
secondMap.put("0", "A");
secondMap.put("1", "B");
secondMap.put("2", "C");
secondMap.put("3", "D");
Map<String, String> result = secondMap.values().stream()
.collect(Collectors.toMap(Function.identity(), firstMap::get, (x,y)-> x, LinkedHashMap::new));
System.out.println(result);

How to iterate hashmap in reverse order in Java

I am trying this for some hour but not finding any best approach to achieve iteration of hashmap in reverse order, this is the hashmap I have.
Map<Integer, List<String>> map = new HashMap<Integer, List<String>>();
for(Integer key : map.keySet()) {
List<String> value = map.get(key);
List<Map<String,?>> security = new LinkedList<Map<String,?>>();
for(int ixy = 0; ixy < value.size()-1; ixy++){
security.add(createItem(value.get(ixy), value.get(ixy+1)));
}
adapter.addSection(Integer.toString(key), new SimpleAdapter(getApplicationContext(), security, R.layout.list_complex, new String[] { ITEM_TITLE, ITEM_CAPTION }, new int[] { R.id.list_complex_title, R.id.list_complex_caption }));
}
I have seen example of TreeMap as well,
Map<Integer, List<String>> sortedMap = new TreeMap<Integer, List<String>>(map);
But treemap also gives in ascending order, what I want is in descending order.
best approach to acheive iteration of hashmap in reverse order
HashMap does not define any particular ordering of its element. Therefore the "reverse" order isn't defined either.
For a TreeMap, you can use descendingMap().
Hashmap does not have specific order. But you can use TreeMap.
Perhaps this simple example can help you :
Map<Integer, String> map = new TreeMap<Integer, String>();
map.put(1, "abc1");
map.put(2, "abc2");
map.put(3, "abc3");
ArrayList<Integer> keys = new ArrayList<Integer>(map.keySet());
for(int i=keys.size()-1; i>=0;i--){
System.out.println(map.get(keys.get(i)));
}
A HashMap doesn't maintain eny order between keys.
A TreeMap orders its keys by their natural order, or by the order imposed by a comparator that you pass when constructing the map. So if you want to have Integer keys ordered in reverse order, construct the TreeMap this way:
Map<Integer, List<String>> sortedMap =
new TreeMap<Integer, List<String>>(Collections.reverseOrder());
Map<Integer, List<String>> sortedMap = new TreeMap<Integer, List<String>>(Collections.reverseOrder());
Collections.reverseOrder() keeps the map sorted in descending order.
You can use TreeMap#descendingKeySet method.
Map<Integer, List<String>> map = new TreeMap<Integer, List<String>>();
for(Integer key : map.descendingKeySet()) {
List<String> value = map.get(key);
List<Map<String,?>> security = new LinkedList<Map<String,?>>();
for(int ixy = 0; ixy < value.size()-1; ixy++){
security.add(createItem(value.get(ixy), value.get(ixy+1)));
}
adapter.addSection(Integer.toString(key), new SimpleAdapter(getApplicationContext(), security, R.layout.list_complex, new String[] { ITEM_TITLE, ITEM_CAPTION }, new int[] { R.id.list_complex_title, R.id.list_complex_caption }));
}
Reference:
https://docs.oracle.com/javase/8/docs/api/java/util/TreeMap.html#descendingKeySet--
You can't iterate over a HashMap in reverse because of this:
This class makes no guarantees as to the order of the map; in
particular, it does not guarantee that the order will remain constant
over time.
What you should use is a LinkedHashMap:
This implementation differs from HashMap in that it maintains a
doubly-linked list running through all of its entries. This linked
list defines the iteration ordering, which is normally the order in
which keys were inserted into the map (insertion-order). Note that
insertion order is not affected if a key is re-inserted into the map.
(A key k is reinserted into a map m if m.put(k, v) is invoked when
m.containsKey(k) would return true immediately prior to the
invocation.)
The hashmap is not an ordered collection. Use TreeMap instead, which has descendingKeySet for reverse iteration. See the javadocs. LinkedHashMap is also a good choice.
TreeMap<Integer, String> map = new TreeMap<Integer, String>();
map.put(1, "abc1");
map.put(2, "abc2");
map.put(3, "abc3");
NavigableMap<Integer, String> nmap = map.descendingMap();
for (NavigableMap.Entry<Integer, String> entry : nmap.entrySet()) {
System.out.println("Key : " + entry.getKey() + " Value : " + entry.getValue());
}
An implementation of NPE idea.
Perhaps you need a NavigableMap, like a TreeMap.
But treemap also gives in asecding order, what i want is in descending order.
Implement a Comparator that will compare it reverse than natural order and then just iterate normally you will have reverse iteration
Use insted:
new TreeMap<>(Collections.reverseOrder())
and you will get what you want.
I've found that the Iterators obtained from Java Hashtable via:
Hashtable.values().iterator() and Hashtable.keys().asIterator()
are both in reverse order by default. One oddity, The values().iterator has a first final value of "0" which I didn't add when populating it.

Implementation of sorting in Vector

I have a Collection as
Vector<HashMap<String, String>>
Actually I am using this as list items of list view in android.I used SortedMap but I did not get correct result. I think this is because HashMap's structure is
hashMap.add("Name","value_of_name");
hashMap.add("Counts","value_of_counts");
Now I am adding it to Vector.
I want to sort vector's element by Name key of hashMap.
I know about Collection.sort and I can sort this using ArrayList and POJO class. But I do not know how to use it with adapter of my ListView
How can I sort elements. And is there any better solution (Regarding my data-structure of collection, which can be use with adapter easily) ?
You need to a implement a Comparator<HashMap<String,String> > and place the logic of your sort ordering inside its compare method.
Not sure I understand correctly. This will sort the vector on one key of the maps.
Collections.sort(yourVector, new Comparator<HashMap<String,String>>() {
public int compare(HashMap<String,String> a, HashMap<String,String> b) {
return a.get(yourKey).compareTo(b.get(yourKey));
}
});
Have you never thought about taking a look at collections in java.util package ?
You would then have discovered that Treemap already implements balanced tree sorting for Comparable items, like String is.
So, to have your items sorted, just repalce your HashMap with a TreeMap, and all the work will be done.
BTW what does this vector does here ? They're sooo Java 1.1 (fifteen years old, in other words)
If you want to sort the maps in the array, use a SortedMap implementation like TreeMap or ConcurrentSkipListMap. This takes a vector of HashMaps and returns a ArrayList (a non-synchronized and faster collection than Vector) of SortedMaps.
public ArrayList<SortedMap<String, String>> sortMaps(Vector<HashMap<String, String> maps) {
ArrayList<TreeMap<String, String>> returnMaps = new ArrayList<TreeMap<String, String>>();
for(HashMap<String, String> theMap : maps) {
// TreeMap is a sorted map and this will use the default String.compareTo
TreeMap<String, String> newMap = new TreeMap<String, String>();
// put all the items from the HashMap into the TreeMap, which will autosort
newMap.putAll(theMap);
returnMaps.add(newMap);
}
return returnMaps;
}
To sort the Vector by the first keys (lowest keys, first alphabetically) of the hash map try the following before the return line:
// this sorts the vector by first keys
Collections.sort(returnMaps, new Comparator<SortedMap<String,String>>() {
public int compare(SortedMap<String,String> a, HashMap<String,String> b) {
return a.firstKey().compareTo(b.firstKey());
}
});
Or if you want to sort by last key (highest keys, last alphabetically):
// this sorts the vector by first keys
Collections.sort(returnMaps, new Comparator<SortedMap<String,String>>() {
public int compare(SortedMap<String,String> a, HashMap<String,String> b) {
return a.lastKey().compareTo(b.lastKey());
}
});
To return one sorted map of all keys (will stomp on any duplicates):
public SortedMap<String, String> singledSortedMap(Vector<HashMap<String, String> maps) {
// this will end up with all the values, sorted by natural string ordering
SortedMap<String, String> returnMap = new TreeMap<String, String>();
for(HashMap<String, String> theMap : maps) {
returnMap.putAll(theMap);
}
return returnMap;
}
The best (fastest) way it to use a TreeMap instead. If you supply it with the correct Comperator all the items in the TreeMap will be sorted.
The important question: Why do you have a Vector of HashMaps?

TreeMap: Sort values of a map with keys moving along with values

i have the following TreeMap:
TreeMap<Integer, Double> map;
the Double values are not unique.
i iterate through the map using Integer keys and the functions firstEntry() and higherEntry() and modify the Double values.
Now i want to list the values of the pairs in the order of decreasing Double values.
what is the best way to do this?
those Integer keys are important to me and because the Double values are not unique, i cannot have a Double key.
Update:
More Explanation
it is the classic problem. lets say rollnos of students is the key and their percentage is the value. now sort by percentage and then we should be able to tell whose percentage is it. therefore i need the integer key.
The obvious solution is to obtain a collection of the doubles (possibly via the entrySet and then getValue - the TreeMap class has a values() method, you can just use that), and proceed to sort them (using Collections.sort or Arrays.sort) - this would, however, take O(n logn) time.
I'm not sure you can do it in a smarter (== faster) way, unless you completely change the data structure. However, the only way in which I see this happening with another data structure is keeping a wrapper over the integer and the double and writing two comparators - one which compares the integer and one which compares first by the double and then by the integer. The original TreeMap you're using would be the same but you would be able to detach another TreeMap from it, sorted by the second comparator. Detaching would still take O(n logn) time though.
you can build a TreeSet, that guarantees insertion order:
#Test
public void treeMapSortedByValue() {
// given the following map:
TreeMap<Integer, Double> map = new TreeMap<Integer, Double>();
map.put(2, Math.E);
map.put(1, Math.PI);
map.put(3, 42.0);
// build a TreeSet of entries
Set<Map.Entry<Integer, Double>> sortedEntries = new TreeSet<Map.Entry<Integer, Double>>(new DoubleComparator());
sortedEntries.addAll(map.entrySet());
// optionally you can build a List<Double> with the sorted
List<Double> doubles = new LinkedList<Double>();
for (Map.Entry<Integer, Double> entry : sortedEntries) {
doubles.add(entry.getValue());
}
}
this should give you: [2.718281828459045, 3.141592653589793, 42.0] (nb: [Math.E, Math.PI, Math.UNIVERSAL_ANSWER] :-).
PS
the Comparator:
class DoubleComparator implements Comparator<Map.Entry<Integer, Double>> {
#Override
public int compare(Entry<Integer, Double> o1, Entry<Integer, Double> o2) {
return Double.compare(o1.getValue(), o2.getValue());
}
}
What you can do is the following : use entrySet to iterate through the entries. Put them into a list. Sort the date with the right comparator then.

Categories

Resources