This question already has answers here:
How to avoid items being re-ordered when put into java HashMap
(4 answers)
Closed 8 years ago.
HashMap<Integer, String> map = new HashMap<Integer, String>();
map.put(5,a);
map.put(4,b);
map.put(3,c);
map.put(2,d);
map.put(1,e);
System.out.println(map);
Why the result is equal {1=e, 2=d, 3=c, 4=b, 5=a}?
Java HashMap doesn't keep any order. API says
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.
From HashMap's javadoc:
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.
A LinkedHashMap would suffice for ordering by insertion order, and a TreeMap may be used when order through a key's comparator is needed.
Related
This question already has answers here:
How to get a immutable collection from java HashMap?
(5 answers)
Closed 2 years ago.
I wanted to create an immutable hashMap inline using the new factory method Map.ofEntries() in Java 9, for example:
Map<Integer, String> map = Map.ofEntries(
Map.entry(1, "One"),
Map.entry(2, "Two"),
Map.entry(3, "Three"));
Then to my surprise, I found I could not create an immutable hashMap the same way! For example, the following code would not work.
HashMap<Integer, String> map = HashMap.ofEntries( //not work
Map.entry(1, "One"),
Map.entry(2, "Two"),
Map.entry(3, "Three"));
Then when I want to check what type of map is returned by the factory method, I found the following note:
Callers should make no assumptions about the identity of the returned instances.
So my question is, is the access time complexity of an immutable map the same as a hashMap which is o(1)? If not, how to create a map that is both immutable and access o(1) at the same time? It would be best if it can be created inline.
Mutability or immutability are not directly related to the complexity of the access operation in a Map. For instance, a HashMap will always be O(1) for the get() operation, whereas a TreeMap will be O(log n). It's the implementing class of the Map interface that determines the complexity of the operations.
Besides it's always been possible to create unmodifiable maps, because we can make any Map of any concrete type immutable after we put items on it, like this:
Map<Integer, String> immutableMap = Collections.unmodifiableMap(mutableMap);
To be clear, HashMap.ofEntries() won't work because the ofEntries() method is static and defined in the Map interface, not in any of its implementing classes.
And you should not worry about being unable to declare the type of a map as HashMap or some other concrete class, anyway the best practice is to declare the map as being of a Map interface.
Also, if you were using a version older than Java 9 and don't mind using an external library, you can use ImmutableMap from Guava:
Map<Integer, String> immutableMap = ImmutableMap.of(key1, val1, key2, val2);
Perhaps reading this article will clarify things a bit more.
This question already has an answer here:
why the output of the Hashmap is arbitary, not in a specific order? why its sorting order gets change on insertion & deletion of new node?
(1 answer)
Closed 8 years ago.
Items displayed as unsorted
map.put("California", "Sacramento");
map.put("Oregon", "Salem");
map.put("Washington", "Olympia");
System.out.println(map);
map.put("Alaska", "Juneau");
System.out.println(map);
HashMaps in java aren't sorted!
HashMap makes absolutely no guarantees about the iteration order. It
can (and will) even change completely when new elements are added.
TreeMap will iterate according to the "natural ordering" of the keys
according to their compareTo() method (or an externally supplied
Comparator). Additionally, it implements the SortedMap interface,
which contains methods that depend on this sort order.
LinkedHashMap will iterate in the order in which the entries were put
into the map
I try it, my print is :
{California=Sacramento, Oregon=Salem, Washington=Olympia}
{California=Sacramento, Oregon=Salem, Washington=Olympia, Alaska=Juneau}
Alaska=Juneau is displayed at the end.
but TreeMap is order.print:
{Alaska=Juneau, California=Sacramento, Oregon=Salem, Washington=Olympia}
This question already has answers here:
How to Maintain order of insertion [duplicate]
(3 answers)
Closed 9 years ago.
I have a list which I convert to a map to do some work. After that, i convert the map back again to a list, but this time the order is random. I need the same initial order retained in my second list.
the obvious reason is that a HashMap doesn't maintain order. But I need to do something so that it does. I cannot change the Map implementation.How can I do that ?
Consider the given code:
import java.util.*;
public class Dummy {
public static void main(String[] args) {
System.out.println("Hello world !");
List<String> list = new ArrayList<String>();
list.add("A");list.add("B");list.add("C");
list.add("D");list.add("E");list.add("F");
Map<String,String> map = new HashMap<String, String>();
for(int i=0;i<list.size();i=i+2)
map.put(list.get(i),list.get(i+1));
// Use map here to do some work
List<String> l= new ArrayList<String>();
for (Map.Entry e : map.entrySet()) {
l.add((String) e.getKey());
l.add((String) e.getValue());
}
}
}
For ex - Initially, when I printed the list elements, it printed out
A B C D E F
Now, when I print the elements of List l, it printed out
E F A B C D
HashMap itself doesn't maintain insertion order - but LinkedHashMap does, so use that instead.
As documented... HashMap:
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.
And LinkedHashMap:
Hash table and linked list implementation of the Map interface, with predictable iteration 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).
Use LinkedHashMap instead of HashMap to maintain order.
Map<String,String> map = new LinkedHashMap<String, String>();
Why can't you change the Map implementation (to LinkedHashMap for example)?
If there's a logical ordering, you could sort the List with a custom Comparator.
HashMap doesn't preserve order of insertion
Hash table based implementation of the Map interface. This implementation provides all of the optional map operations, and permits null values and the null key. (The HashMap class is roughly equivalent to Hashtable, except that it is unsynchronized and permits nulls.) 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.
Use LinkedHashMap if you want to preserve order of keys
Consider making your items sortable. In the case of strings, there is already a natural ordering; alphabetical. You can make objects that use the sortable class, and therefore you can use sorting algorithms to put these objects in a nice order, no matter what order you get them in from hash!
It's time for a LinkedHashMap, it is meant exactly to preserve insertion order.
Mind that even a TreeMap exists, which allows you to keep your desired order by using Comparable interface. It is not an hash map anymore, but a tree.
If you truly are unable to switch to another Map implementation (LinkedHashMap is exactly what you want), then the only other possibility is to retain the original List, and use it to create the new List from the Map.
public <T> List<T> listFromMapInOrder(final Map<T, T> map, final List<T> order) {
List<T> result = new ArrayList<T>();
for (T key : order) {
if (map.containsKey(key)) {
result.add(key);
result.add(map.get(key));
}
}
return result;
}
But I would refactor the code until it was possible to switch to a LinkedHashMap.
This question already has answers here:
Is the order of values retrieved from a HashMap the insertion order
(6 answers)
Closed 9 years ago.
I have a Map with values and get a Set using Map.keySet method.
In this code:
Map<String, String> map = new HashMap<>();
map.put("1", "a");
map.put("2", "b");
map.put("3", "c");
Set<String> set = map.keySet();
for (int i = 0; i < 5; i++) {
for (String key : set) {
System.out.println(key);
}
}
am I guaranteed to get
1
2
3
written out every time? Where is this guarantee written down ? In Javadoc?
EDIT: Actually I don't care about the insertion order, but I care about the fact that using for-each loop on a set will produce the same result over and over, providing that the undelying map does not change (I don't call put, remove).
No, you are not. But you can use LinkedHashMap (http://docs.oracle.com/javase/6/docs/api/java/util/LinkedHashMap.html) and then you will be guaranteed.
LinkedHashMap for order of additionn (put), and TreeMap (interface SortedMap) for order of keys.
Unfortunately the docs for HashMap state that keySet() method does not return a SortedSet, it just returns a Set, for which the ordering is not guaranteed.
See HashMap.keySet()
Read, in particular: It makes no guarantees as to the iteration order of the set; in particular, it does not guarantee that the order will remain constant over time.
Use LinkedHashMap if you want to retrieve in order in which you put key .
No you're not guaranteed a specific order, unless you use a HashMap which implements a custom set that can give you this guarantee. The Set the HashMap gives you back have an Iterator() method which iterates over the elements in "no particular order".
Read the java documentation: http://docs.oracle.com/javase/1.5.0/docs/api/java/util/Set.html#iterator()
If you want the guarantee that the elements are iterated over in-order, i.e. ascending order, use something that implements SortedMap like TreeMap.
TreeMap Documentation: http://docs.oracle.com/javase/6/docs/api/java/util/TreeMap.html
On this page you find the getSet() method which says "The set's iterator returns the keys in ascending order".
I'm creating a new Map and pushing strings into it (no big deal) -but I've noticed that the strings are being re-ordered as the map grows. Is it possible to stop this re-ordering that occurs so the items in the map retain the order the were put in with?
Map<String,String> x = new HashMap<String, String>();
x.put("a","b");
x.put("a","c");
x.put("a","d");
x.put("1","2");
x.put("1","3");
x.put("1","4");
//this shows them out of order sadly...
for (Map.Entry<String, String> entry : x.entrySet()) {
System.out.println("IN THIS ORDER ... " + entry.getValue());
}
If you care about order, you can use a SortedMap. The actual class which implements the interface (at least for most scenarios) is a TreeMap. Alternatively, LinkedHashMap also maintains its order, while still utilizing a hashtable-based container.
You can keep it with LinkedHashMap.
A HashMap in java is not sorted http://download.oracle.com/javase/1,5.0/docs/api/java/util/HashMap.html. If you want predictable iteration order use a LinkedHashMap instead: http://download.oracle.com/javase/1.4.2/docs/api/java/util/LinkedHashMap.html
Heres a good discussion on the difference: How is the implementation of LinkedHashMap different from HashMap?
The previous answers are correct in that you should use an implementation of Map that maintains ordering. LinkedHashMap and SortedMap each do these things.
However, the takeaway point is that not all collections maintain order and if order is important to you, you should choose the appropriate implementation. Generic HashMaps do not maintain order, do not claim to do so and cannot be set to do so.