Sorting keys alphabetically in LinkedHashMap - java

I have a LinkedHashMap and I want to sort its keys (which are Strings) alphabetically. However, it won't work with the Collections.sort() method, because it won't take either the LinkedHashMap itself nor the LinkedHashMap's keyset.
My only option is to sort them manually while filling the LinkedHashMap, but before doing that I wanted to know if anyone knows a better way.

The better way is to use a Map which supports an order, like TreeMap.
However, if you have a broken design you can't fix you can do this.
LinkedHashMap<String, String> map = ...
TreeMap<String, String> copy = new TreeMap<>(map);
map.clear();
map.putAll(copy);
This will happen to work, but if you add a key, your map won't be sorted any more.

Related

Java: Check if a Key is contained in two HashMap

Is there a way to search and get a subset of keys that are contained in two HashMap objects?
Until now I have always made an iteration from a hashmap and looking for matches in the second.
I just wanted to know if there was a smarter way to do this comparison.
How about
List<String> listOne = new ArrayList<String>(mapOne.keySet());
List<String> listTwo = new ArrayList<String>(mapTwo.keySet());
List<String> listThree = new ArrayList<String>(listTwo);
listThree.retainAll(listOne);
Or
Commons Collections
CollectionUtils.intersection(java.util.Collection a, java.util.Collection b)
There is no way to do that in a complexity less than O(N). The only thing you can do, is to iterate the smallest hashmap.
Another thing you could do is to use the key sets of the hashmaps and use the method retainAll, which perform the intersection for you, but the complexity doesn't change.
Use a HashSet. If your use case needs to have (key, value) pairs, then maintain a HashMap and a HashSet both, and whenever a key is inserted in the HashMap, insert it in the HashSet as well. Otherwise, just maintain a HashSet.
Then you can use retainAll() function to find the intersection of the two sets.
HashSet intersection = hashSet1.retainAll(hashSet2);
The time complexity will be O(n) amortised. This is almost the same as that of what you are doing, but this would make your code much cleaner and readable.
Note that you can maintain a List instead of Set and call the retainAll() method of list. However, retainAll() of List will run in O(n^2) complexity, because the contains() method of List runs in O(n) whereas contains() of HashSet runs in O(1) amortised.
You can create the newMap by removing all keys using removeAll as shown below with inlin comments:
Map<String, String> map1 = new HashMap<>();
Map<String, String> map2 = new HashMap<>();
Set<Entry<String, String>> set1 = map1.entrySet();//get the entries from Map1
set1.removeAll(map2.entrySet());/remove all matched entries mateched in map2
Map<String, String> newMap = set1.stream().//convert set1 to Map using stream
collect(Collectors.toMap(Entry::getKey, Entry::getValue));
This example uses Map<String, String>, but can be applied to any types (of course for custom classes, you need to override equals() and hashcode() methods from java.lang.Object).
Probably not the most efficient way to do it, but this Java 8 one-liner works
Map<Integer,Integer> mapA = ..... // your first map
Map<Integer,Integer> mapB = ..... // your second map
List<Integer> keys = mapA.entrySet().stream().filter((v) -> mapB.containsKey(v.getKey()))
.map(v -> v.getKey()).collect(Collectors.toList());

How to remove first element from a TreeMap?

I need to implement a container which contains maximum 32 values where elements are sorted by key. In C++ it's kinda easy, cause every map is sorted by it's key, in Java I'm not that sure.
So I read some and came with a TreeMap.
How to efficently remove the oldest element from a TreeMap (the first one)?
Thanks!
You said
The key here is a 'sequenceNumber' which is being incremented in the same loop.
By TreeMap documentation it states
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.
So you can easily remove the first element after sorted.
Example:
TreeMap<Integer, String> map = new TreeMap<>();
map.put(1, "ac");
map.put(2, "ef");
map.put(3, "bd");
map.remove(map.firstKey());
Use LinkedHashMap, which has method removeEldestEntry.

Java How do I get all map values within specific keys?

right now I have a Map like this:
Map<Double, MyObject> map = new HashMap<Double, MyObject>();
I want to get all values of keys that are between 2.0 and 7.0. I have thousands of different values in my Map, so looping through every key-value set will be heavy for performance. Is there any way to solve this? (Or is there some sort of special map, that is used to have number keys?) Thanks for helping ;)
Use a TreeMap instead. Through its NavigableMap interface, you can perform range operations.
NavigableMap<Double, MyObject> map = new TreeMap<>();
Collection<MyObject> keys = map.subMap(2D, 7D).values();

Sort a TreeMap by either Key Or Value

Situation:
I have a Map, a TreeMap to be more exact that looks like
TreeMap<String, Integer>
I have to be able to sort it on either the key OR the value in an ascending OR descending way. The result must be a Map like
Map<String, Integer>
Not an ArrayList or anything like that because the rest (read: allot) of my code won't work anymore. I've searched but couldn't find anything that suits my needs. Is this even possible? Double values may not be lost.
If you use two BiMaps which each back each other, then you effectively have one map.
Somthing like:
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
private BiMap<Integer, String> localid = HashBiMap.create();
private BiMap<String, Integer> inverse = localid.inverse();
you can treat each reference, localid & inverse, as their own map, but changes to one are reflected in the other. The only slight downside is that now both the keys and values must be unique, as the values of one are the keys of the other. For most cases this is not a problem.
For sorting it, you can at any time make a local copy which is a treeMap, and that imposes an ordering. E.g.
ImmutableMap.copyOf(Maps.newTreeMap(bimap))
Now if you are never making changes to your map, this will provide a sorted view, and you can do it by either.
EDIT: A TreebasedTable has two keys for each value, and you can sort either keyset with a comparator. I am not sure that this is exactly what you need, here as the keysets are independent, but you might be able to refactor your code slightly to make this a viable solution.
If the map is small and iterating over it is an infrequent operation, one solution would be to just use a HashMap (for lookup speed) and then sort the entries every time you iterate.
Another solution, if you do these iterations frequently compared to direct map lookups, and if the values (and not just the keys) are unique, would be to maintain two sorted maps, one <String, Integer> and one <Integer, String>.
Guava has the concept of BiMap. Is that what you're looking for?
A TreeMap's keys are sorted by it's comparable.
Try a SortedMap
A Map that further provides a total ordering on its keys. The map is ordered according to the natural ordering of its keys, or by a Comparator typically provided at sorted map creation time. This order is reflected when iterating over the sorted map's collection views (returned by the entrySet, keySet and values methods). Several additional operations are provided to take advantage of the ordering. (This interface is the map analogue of SortedSet.)

HashMap returns value in non sequential order

I am inserting four values with different keys in a HashMap.
Code Snippet :
HashMap<Integer, String> choice = new HashMap<Integer, String>();
choice.put(1, "1917");
choice.put(2, "1791");
choice.put(3, "1902");
choice.put(4, "1997");
But when I am printing that map values,it returns a result something like :
{4=1997, 1=1917, 2=1791, 3=1902}
How can I get the map values in a sequential order the way I have put/inserted?
You can use a LinkedHashMap instead, which will keep the insertion order:
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).
You can modify your code like this:
Map<Integer, String> choice = new LinkedHashMap<Integer, String>();
//rest of the code is the same
LinkedHashMap, which is a Hash table and linked list implementation of the Map interface can be used.
It maintains the same order in which the values are inserted using doubly linked list.
Reference : http://docs.oracle.com/javase/1.4.2/docs/api/java/util/LinkedHashMap.html
[Edit]What the OP asks is not entirely clear to me. The OP could be asking, "How do I retrieve items from a map in insertion order?" If that is what the OP meant, then the following information is not a solution.
If the OP is asking, "How do I retrieve items from a Hash sorted by the key?" then the following is on-point. Getting the sorted keys of a hash/associative array is a common operation.
The answer can be found in how to sort Map values by key in Java:
List sortedKeys=new ArrayList(yourMap.keySet());
Collections.sort(sortedKeys);
If you care about the order in which the keys are stored and retrieved, consider using a TreeMap instead. Unless you have a very large number of elements (millions+), the performance difference is not likely to be noticeable.

Categories