sorting treemap based on key, where key is variable - java

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.

Related

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);

TreeMap removing all keys greater than a certain key

In a project I need to remove all objects having key value greater than a certain key (key type is Date, if it matters).
As far as I know TreeMap implemented in Java is a red-black tree which is a binary search tree. So I should get O(n) when removing a subtree.
But I can't find any method to do this other than making a tail view and remove one by one, which takes O(logn).
Any good ideas implementing this function? I believe treeMap is the correct dataStructure to use and should be able to do this.
thanks in advance
Quite simple. Instead of removing the entries one-by-one, use Map.clear() to remove the elements. In code:
map.tailMap(key).clear();
public class TreeMapDemo {
public static void main(String[] args) {
// creating maps
TreeMap<Integer, String> treemap = new TreeMap<Integer, String>();
SortedMap<Integer, String> treemapincl = new TreeMap<Integer, String>();
// populating tree map
treemap.put(2, "two");
treemap.put(1, "one");
treemap.put(3, "three");
treemap.put(6, "six");
treemap.put(5, "five");
System.out.println("Getting tail map");
treemap.tailMap(3).clear();
System.out.println("Tail map values: " + treemapincl);
System.out.println("Tree map values: " + treemap);
}
}
This will remove the elements in the tree map.

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.

Map: How to get all keys associated with a value?

Given a Map, how do I look up all keys associated with a particular value?
For example:
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
map.put(1, 5);
map.put(2, 2);
map.put(3, 5);
Collection<Integer> keys = map.values(5); // should return {1, 3}
I'm looking for something similar to Google Collections' BiMap where values are not unique.
With plain java.util.Map implementations, I am afraid you must iterate through the map entries and test each value:
for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
if (entry.getValue().equals(desiredValue) {
keys.add(entry.getKey());
}
}
If you want better performance, you may want to build up a parallel mapping from values to lists of keys. I don't know of any existing collection doing this, but it should not be difficult to implement.
From Java 8 onwards you can use map.forEach:
map.forEach((k,val) -> {
if (val.equals(desiredValue) {
keys.add(k);
}
});

remove key from hash table

I want to remove key from hash Table without using the remove function. so give me some idea.
You can emulate removed keys by supplementing a Map<K,V> map with a Set<K> removedKeys.
To remove a key, just removedKeys.add(key);.
Whenever a K key is queried, you see if removedKeys.contains(key). If it does, then key has effectively been "removed" from map.
Note that this is a very peculiar way of doing things, and keeping the two structures in sync may cause later headaches. It's more acceptable if removedKeys is localized and short-lived, e.g. when you're iterating over the entries of a Map using for-each and want to remove some keys later, while avoiding ConcurrentModificationException.
So you may have something like this:
static void removeEvenKeys(Map<Integer,String> map) {
Set<Integer> removedKeys = new HashSet<Integer>();
for (Map.Entry<Integer,String> entry : map.entrySet()) {
if (entry.getKey() %2 == 0) {
removedKeys.add(entry.getKey());
}
}
map.keySet().removeAll(removedKeys);
}
And then elsewhere:
Map<Integer,String> map = new HashMap<Integer,String>();
map.put(1, "One");
map.put(2, "Two");
map.put(3, "Three");
map.put(4, "Four");
removeEvenKeys(map);
System.out.println(map);
// "{1=One, 3=Three}"
See also
Effective Java 2nd Edition, Item 52: Refer to objects by their interfaces
Related questions
Java hashmap vs hashtable
Java: Efficient Equivalent to Removing while Iterating a Collection
You can call remove() on an Iterator instead of on the Hashtable itself:
Hashtable<String, String> map = new Hashtable<String, String>();
map.put("one", "een");
map.put("two", "twee");
map.put("three", "drie");
for (Iterator<Map.Entry<String, String>> i = map.entrySet().iterator(); i.hasNext(); ) {
Map.Entry<String, String> entry = i.next();
if ("two".equals(entry.getKey())) {
// Removes entry from Hashtable; note, this is not the Hashtable.remove() method
// but the Iterator.remove() method
i.remove();
}
}
System.out.println(map);
(NOTE: You should use HashMap instead of the legacy collection class Hashtable).

Categories

Resources