HashMap messes up the order of its own elements [duplicate] - java

This question already has answers here:
Difference between HashMap, LinkedHashMap and TreeMap
(17 answers)
Closed 4 years ago.
Simple as the title, I searched it up already, and I didn't find anything about this issue, I'm pretty sure I just misunderstood how a HashMap works with its own elements.
Super-simplest code:
HashMap<String, Integer> map = new HashMap<String, Integer>();
map.put("first key", 1);
map.put("second key", 2);
map.put("third key", 3);
System.out.println(map.toString());
What does the println() method show?
It shows this:
{third key=3, first key=1, second key=2}
I tough the HashMap stored elements as the programmer put them in.
Even a sorting would sort would place these elements as I put them in origin.
I tried changing the words and similar things happen(only the positions changed, but they were "wrong" anyway). :/
Do you know why?
Thanks in advance :/
EDIT: Rohit Jain is actually the first that answered me as comment, and you guys told me about LinkedHashMap, so you helped me to solve, thank you very much :)

If you want to iterate over your keys by insertion order you need to use a LinkedHashMap instead. The HashMap documentation clearly states that
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.

You are looking for LinkedHashMap which retains insertion order.

HashMap does not guarantee ordering of any kind.
From the java docs:
This class makes no guarantees as to the order of the map
You can use LinkedHashMap if you want to maintain order.

http://docs.oracle.com/javase/7/docs/api/java/util/HashMap.html
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.

HashMap doesn't preserve order:
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. --javadoc
You want LinkedHashMap:
LinkedHashMap<String, Integer> map = new LinkedHashMap<String, Integer>();
map.put("first key", 1);
map.put("second key", 2);
map.put("third key", 3);
System.out.println(map.toString());
output:
{first key=1, second key=2, third key=3}
If all you care about is the toString, you could also use TreeMap.

There are different Map types, giving different guarantees about their key order (see this).
HashMap: Undefined ordering of its elements.
LinkedHashMap: Order defined by insertion.
TreeMap: Order defined by the compareTo() method of their elements.
So, HashMap makes no guarantee about it's iteration order. Once you insert another element, you will get a different ordering. From what you described a LinkedHashMap might be what you need.

Related

What are HashMap and HashSet value's order [duplicate]

This question already has answers here:
Iteration order of HashSet
(9 answers)
Closed 5 years ago.
I was wondering, both HashMap and HashSet do not return values in order?
Please someone clarify.
I am confused and why do you need these two?
In a word - yes. Neither HashMap or HashSet give any guarantee on the order of iteration.
The HashMap API does not define the order of iteration.
However, if you look at the implementation of HashMap, you can deduce that there is a complex transient relationship between the iteration order, the keys' hash values, the order in which the keys were inserted and the size of the hashtable. This relationship gets scrambled if the hashtable resizes itself.
Please refer:
Is the order of values retrieved from a HashMap the insertion order
If you want the values in the order you insert you have to use LinkedHasmap other wise you can use TreeMap where sort by the key. hash does not give any order because it uses the hascode to order values it may vary depend on the object.
A HashMap stores key value pairs. A HashSet is an unordered collection of objects in which each there can be no repeats. Neither are necessarily iterated in order insertion or otherwise. There are ordered implementations but you would not use the standard HashMap or HashSet classes.
Talked about further here
Linked Hash Map does maintain insertion order
HashMap is a implementation of Map interface. Map is a data structure to say that A corresponds to B.
Map<Integer, String> map = new HashMap<Integer, String>();
map.put(new Integer(1), "Test");
In the case above we know that every time that we look for 1, the correspondent is "Test".
Sets are something completely different. Sets ensures that no duplicate object will exists in your collection. HashSet is an implementation of Set interface.
To insert and retrieve something in order you could use LinkedHashMap, LinkedHashSet, ArrayList (implementation of List interface) and others
Wrapping it up:
Map - correspond objects
Set - Ensure unique objects in a collection

java - how to iterate through maps in order [duplicate]

This question already has answers here:
Java Class that implements Map and keeps insertion order?
(8 answers)
Closed 6 years ago.
This is the code:
for(String key : mymap.stringPropertyNames()) {
//mycode
}
This works correctly but I noticed I get the values I need in random order, is there a way to loop through the map using a particular order?
EDIT: Mymap is a properties object.
This is because you are using a Map without sorting like 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.
Instead of this, you can use some concrete implementation like:
TreeMap:
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.
LinkedHashMap if you need no duplicates...
Hash table and linked list implementation of the Map interface, with predictable iteration order.
If you want predictable iteration order (insertion order) then use a LinkedHashMap
If you want the elements to be sorted you need to use a TreeMap , in this case the Keys need to implement Comparable interface
Either change the Map implementation into one of the ones that support ordering or sort the keys before iterating over them. I am a bit confused though, normally one gets the keys of a map by the keySet method. I am not familiar with stringPropertyNames but if it is a Map you should be able to do something like (untested code):
List keys = new ArrayList(mymap.keySet())
Collections.sort(keys)
for ( String key : keys ) {
[...]
}

Get first and last element from a HashMap

I have the following code and I'd like to get able to get the first and last element from the Map and assign each to a String.
String result1stElement = null;
String resultLastElement = null;
Map<String, String> result = new HashMap<String, String>();
result = myModel.getSampleResults();
Any ideas.
Thanks in advance.
First of all, Maps are not ordered so you wont really have a first and last element.
However, if you wish to get the first and last element of this anyways you could just get the values and convert this into an array. This isn't really pretty, but it'll work.
Map<String, String> result = new HashMap<String, String>();
result = myModel.getSampleResults();
map.values().toArray()[0]; //First result
map.values().toArray()[result.size()-1]; //Last result
Note: This is not tested with a compiler.
First and last element concepts not applicable to Hash-based structures like HashMap and HashSet.
Insertion or deletion of key may cause element reordering on-the-fly.
I guess your model results is an key-value pairs list, not hash map. In this case element ordering is in place. LinkedHashMap keeps insertion order of elements.
Replace HashMap to LinkedHashMap (and modify .getSampleResults()) to return LinkedHashMap and check this question for futher details Java LinkedHashMap get first or last entry .
HashMap has no such thing as order. From HashMap 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.
You'll have to use LinkedHashMap. Take a look at entrySet() method and this question+answer
"toArray" method of Set interface can be used.
But iterating over the entries in the entry set and getting the first and last entry is a better approach.
This example might be helpful:
public static void main(final String[] args) {
final Map<Integer,String> orderMap = new LinkedHashMap<Integer,String>();
orderMap.put(6, "Six");
orderMap.put(7, "Seven");
orderMap.put(3, "Three");
orderMap.put(100, "Hundered");
orderMap.put(10, "Ten");
final Set<Entry<Integer, String>> mapValues = orderMap.entrySet();
final int maplength = mapValues.size();
final Entry<Integer,String>[] test = new Entry[maplength];
mapValues.toArray(test);
System.out.print("First Key:"+test[0].getKey());
System.out.println(" First Value:"+test[0].getValue());
System.out.print("Last Key:"+test[maplength-1].getKey());
System.out.println(" Last Value:"+test[maplength-1].getValue());
}
// the output geneated is :
First Key:6 First Value:Six
Last Key:10 Last Value:Ten
There is no such a thing as a first and last element in a HashMap. This is the price you have to pay for O(1) lookup: internally the implementation will chuck your entries into a list of buckets in no easily identifiable (but deterministic) order. This process puts the Hash in HashMap, and in fact the more chaotic it is, the better the performance.
You can use a TreeMap if you want a map sorted by the natural order of its keys (or a custom comparator) or you can have a LinkedHashMap if you want the elements to be arranged in the order of insertion.
P.s.: even if you choose a Map implementation that maintains some kind of order, calling toArray() just to get the first and last elements is a massive overkill, I wouldn't do it. TreeMap has firstEntry() and lastEntry() methods, and even with LinkedHashMap, it's a lot cheaper to just manually iterate across the elements and keep the first and last one instead of allocating a potentially huge array.
Your comment to #Nikolay's answer shows an important detail of your question that was hidden until now.
So, you want to test a method which uses a HashMap structure for refering to some added objects and you want to test, if this method delivers some ordering in this structure? First added object shall remain at a "first position", last added object at a "last position"?
As the other answers already show, there is no way without refactoring that method. HashMap doesn't deliver any meaningful ordering at all and if that method should deliver some ordering, it is simply broken - implementation is faulty.
Of course, you can write a unit test using the algorithm provided by #Sander. This test will fail most of the time. And this again shows the fact, that the tested method has to be refactured like #Nikolay showed in his answer, for instance.

Occurred order in the iteration at run-time in a map

In the piece of code similar to
//something before
Iteration<String> iterator = hashMap.keySet().iterator();// HashMap<String, Document>
while(iterator.hasNext()){
System.out.println(iterator.next());
}
//something after
I know that the order of print can be different by the order of insertion of entry key, value; all right.
But if I call this piece in another moment, with re-create the variable hashMap and putting them the equal elements, can the second-moment time print be different from the first-time print?
My question was born by a problem with a web-app: I have a list of String in a JSP, but, after some years, the customer call because the order of the String was different in the morning, but it shows the usual order at the afternoon.
The problem is happened in only one day: the web-app uses the explained piece of code for take a Map and populate an ArrayList.
This ArrayList does'nt any explicit changement of order (no Comparator or similar classes).
I think (hope) that the cause of different order of print derives by a different sequence of iteration in the same HashMap at run-time and I looking for a validation by other people.
In the web, I read that the iteration order by a HashMap changes if the HashMap receives a modification: but what happens if the HashMap remains the same?
Hash map document says HashMap makes no guarantees as to the order of the map; in particular, it does not guarantee that the order will remain constant over time.
that explains though the hashmap is same it can not guaranatee on order. for Ordered map you can use TreeMap or LinkedHashMap
TreeMap API says 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.
HashMap API documentation states that
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.
For a Map that keeps its keys in original insertion order, use LinkedHashMap.
For a Map that keeps its keys in sorted order (either natural order or by you passing a Comparator), use either TreeMap or ConcurrentSkipListMap. If multi-threaded, use the second.
For a Map where the key an enum, use EnumMap if you want the entries ordered by the definition order of the enum's objects.
The other six Map implementations bundled with Java 11 do not promise any order to their entries.
See this graphic table of mine as an overview.
Use a LinkedHashMap instead, to preserve insertion order. From the javadoc: "Hash table and linked list implementation of the Map interface, with predictable iteration order."
If you just want a Map with predictable ordering, then you can also use TreeMap. However, a LinkedHashMap is faster, as seen here: "TreeMap has O(log n) performance for containsKey, get, put, and remove, according to the Javadocs, while LinkedHashMap is O(1) for each."
As Octopus mentioned, HashMap "makes no guarantees as to the order of the map," and you shouldn't use it if order must remain consistent.

Behaviour of LinkedHashMap's keySet() and values() methods [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Is the order guaranteed for the return of keySet() of a LinkedHashMap object?
Consider I create a LinkedHashMap, like the following:
Map<String, String> map = new LinkedHashMap<String, String>();
map.put("a", "aa");
map.put("b", "bb");
map.put("c", "cc");
When I call keySet(), does that give me an ordered set? And if I call values(), are these ordered too?
EDIT
Sry, meant ordered, not sorted.
First of all LinkedHashMap is ordered but not sorted. TreeMap is sorted (and hence ordered as well).
That being said you can not expect the output of keySet() and values() to be sorted. Actually the JavaDoc says nothing about the order (as it turns out, the order is guaranteed by JavaDoc: Is the order guaranteed for the return of keys and values from a LinkedHashMap object?) of these collections, however looking at the implementation they should follow the order of underlying Map.
To address recent edit to your question: it is not part of the contract, in fact LinkedHashMap does not even implement keySet() and values() but uses base classes's (HashMap) version. Even though based on the implementation you can see the order is preserved, you should not depend on it if you want your application to be portable.
You don't get a SortedSet or a sorted collection when retrieving the key set or the values. However, the returned implementations use the map's key/value iterators and thus would return the values in the order of insertion, e.g. when being used in a foreach loop.
Thus you get the order as defined by the LinkedHashMap but you can not necessarily consider that to be sorted (and you can't resort those collections either).

Categories