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.
Related
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);
I'm trying to remove a particular key from Map and reposition all keys index wise. For example: My map is like Map<Integer,String>
0,"A"
1,"B"
2,"C"
3,"D"
if i remove key 1 then output should be
0,"A"
1,"C"
2,"D"
How do i keep keys in index wise (0 to size-1) and assign next value to previous key after remove?
This is required because before insertion in map i need to check whether key exists or not. This scenario required for my recycler view adapter to hold unique positions to avoid reloading of items if exists in map
In your situation, if u want the index to be in that behavior. Map is not the answer. use List - can use ArrayList[insertion is often] or LinkedList[fast when reading].
Sample:
List<String> items = new ArrayList<>();
items.add("A");
items.add("B");
items.add("C");
items.add("D");
So if you remove index 1 or B;
items.remove(1);
The index of C will automatically be 1. Just like you wanted above.
Maps inherently have no order. There is no way to change the keys without taking all the values out of the Map and reinserting them with new keys.
It sounds like you may be better off using a List instead of a Map.
ArrayList<String> strings = new ArrayList(Arrays.asList("A", "B", "C"));
// 0 => "A", 1 => "B", 2 => "C"
strings.remove(1);
// 0 => "A", 1 => "C"
You can't order the keys on deletion by updating key values. In MAP only way to update keys is removing the key and and re-insert it with new value. That is tricky and expensive. You can go with ArrayList for the desired result as suggested.
The TreeMap<K,V> in the jdk java.util package can meet your needs. Whatever key you delete , the sort will never change.
If you want to define yourself sort method, just use its custom comparator to over-write construction method TreeMap(Comparator<? super K> comparator) to achieve key sorting.
public static void main(String[] args) {
Map<Integer, String> map = new TreeMap<Integer, String>();
map.put(0, "A");
map.put(1, "B");
map.put(2, "C");
map.put(3, "D");
// whatever key you delete , the sort will not change...
for (Map.Entry<Integer, String> entry : resultMap.entrySet()) {
System.out.println(entry.getKey() + " " + entry.getValue());
}
}
you choose a very bad way to implement this in adapter
but you can solve it with below code:
final Map<Integer, String> myStupidMap = new HashMap<>();
myStupidMap.put(1, "A");
myStupidMap.put(2, "B");
myStupidMap.put(3, "C");
myStupidMap.put(4, "D");
final int[] count = {0};
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
myStupidMap.forEach(new BiConsumer<Integer, String>() {
#Override
public void accept(Integer integer, String s) {
if (count[0] == 1){
myStupidMap.remove(integer);
}
count[0]++;
}
});
}
i hope useful for you But my suggestion is not to use the map.
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");
When I need to sort a HashMap by value, the advice seems to be to create the HashMap and then put the data into a TreeMap which is sorted by value.
For example: Sort a Map<Key, Value> by values (Java)
My question: why is it necessary to do this? Why not create a TreeMap(which is sorted by keys) and then sort it in place by value?
If you know your values to be unique, you can use Guava's BiMap (bidirectional map) to store the data. Create a HashBiMap as you would your HashMap, then create a new TreeMap from its inverse:
new TreeMap<>(biMap.inverse());
That map will then be sorted by the values. Remember that what you're thinking of as "keys" and "values" will be swapped.
If your values are not unique, you can create a multimap of the inverse. A multimap is essentially a mapping from each key to one or more values. It's usually implemented by making a map from a key to a list. You don't have to do that though, because Google did it for you. Just create a multimap from your existing map, and ask Guava to invert it for you into a TreeMultimap, which, as you can guess, is a TreeMap that can hold multiple values per key.
Multimaps.invertFrom(Multimaps.forMap(myMap), new TreeMultimap<V, K>());
Multimap documentation is provided.
Because you can't reorder the entries of a TreeMap manually. TreeMap entries are always sorted on the keys.
I'm going to throw out Map that could be iterated in the order of values as another answer to "How to do it," though...specifically, a solution which doesn't return a map that chokes (by throwing exceptions) on queries to keys not in your original map.
I have this very small code which is working fine:
public class SortMapByValues {
public static void main(String[] args) {
Map<Integer, String> myMap = new LinkedHashMap<Integer, String>();
myMap.put(100, "hundread");
myMap.put(500, "fivehundread");
myMap.put(250, "twofifty");
myMap.put(300, "threehundread");
myMap.put(350, "threefifty");
myMap.put(400, "fourhundread");
myMap = sortMapByValues(myMap);
for (Map.Entry<Integer, String> entry : myMap.entrySet()) {
System.out.println(entry.getKey() + " " + entry.getValue());
}
}
public static Map<Integer, String> sortMapByValues(
Map<Integer, String> firstMap) {
Map<String, Integer> SecondyMap = new TreeMap<String, Integer>();
for (Map.Entry<Integer, String> entry : firstMap.entrySet()) {
SecondyMap.put(entry.getValue(), entry.getKey());
}
firstMap.clear();
for (Map.Entry<String, Integer> entry : SecondyMap.entrySet()) {
firstMap.put(entry.getValue(), entry.getKey());
}
return firstMap;
}
}
Output:
500 fivehundread
400 fourhundread
100 hundread
350 threefifty
300 threehundread
250 twofifty
I wrote the following one-liner using Java 8 Stream API to sort any given map by value:
List<Map.Entry<String, String>> sortedEntries = map.entrySet().stream()
.sorted((o1, o2) -> o1.getValue().compareTo(o2.getValue())).collect(Collectors.toList());
I want to sort the tree map based on the key where key is a variable,so sorting should be based on variable value, How can we achieve this? I want use in built sort method rathar implementing it through code, any reply with example is of great help.
TreeMap (which implements SortedMap) stores automatically the keys in the correct order:
Map<Integer, String> map = new TreeMap<Integer, String>();
map.put(1, "one");
map.put(3, "three");
map.put(2, "two");
// prints one two three
for(Integer key : map.keySet()) {
System.out.println(map.get(key));
}
As Key-Type (in that case Integer) you can use any class which implements Comparable (or you can provide a Comparator when creating the TreeMap)
Edit: Okay, here is a suggestion how to re-map your map.
Map<Integer, String> oldMap; // get oldMap from somewhere
// Prepare remapping
Map<Integer, String> newMap = new TreeMap<Integer, String>();
Map<Integer, Integer> keyMap = new HashMap<Integer, Integer>();
// Store a new key for each old key
keyMap.put(oldKey, newKey);
// fill the newMap
for(Integer oldKey : keyMap.keySet()) {
newMap.put(keyMap.get(oldKey), oldMap.get(oldKey));
}
oldMap = newMap; // if needed
A treemap is a Red-black tree, which is a balanced binary search tree. In other words, the tree is already sorted (or rather, arranged as per the binary search tree rules) with its height balanced so that tree operations have a O(lg n) complexity. However, I think what you want is to print all the keys in sorted order. This is as simple as implementing an inorder traversal on the treemap, or you could use the keySet() method to get a Set and iterate over the values.
e.g. of inorder traversal
void inorderTraversal( Node root ){
if( root == null ) return;
inorderTraversal( root.getLeft() );
root.printValue();
inorderTraversal( root.getRight() );
}
EDIT:
Okay, I'm pretty sure this is what you want. You want to sort by values:
Map<String, Integer> map = new TreeMap<String, Integer>();
map.put("one", 8);
map.put("two", 10);
map.put("three", 9);
map.put("hundred", 1);
System.out.println(map.values());
Output:
[1, 8, 9, 10]
So this works even for sorting string values:
Map<Integer, String> map = new TreeMap<Integer, String>();
map.put(8, "one");
map.put(10, "two");
map.put(9, "three");
map.put(1, "hundred");
System.out.println(map.values());
Output:
[hundred, one, three, two]
Also, sachin take note that having "variable keys" and variable values are completely different things.
TreeMap implements the SortedMap interface and is sorted by its key without you having to do anything:
The map is sorted according to the natural ordering of its keys, or by
a Comparator provided at map creation time, depending on which
constructor is used.