Does hashMapObj.values() return the list in the same order when called nth time as it returned the 1st time?
I understand that the order of values will be different than the insertion order. But will the order differ even when multiple calls are made to values() with no alteration to the 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
http://docs.oracle.com/javase/7/docs/api/java/util/HashMap.html#values()
You can't wait that values() will return the list in the same order, it could happen but is just not a good idea because it depends on the implementation
A HashMap makes no guarantee about the order its values are iterated when iterating a Collection through .values(). Only that they are in sync:
Returns a Collection view of the values contained in this map. The collection is backed by the map, so changes to the map are reflected in the collection, and vice-versa. If the map is modified while an iteration over the collection is in progress (except through the iterator's own remove operation), the results of the iteration are undefined. The collection supports element removal, which removes the corresponding mapping from the map, via the Iterator.remove, Collection.remove, removeAll, retainAll and clear operations. It does not support the add or addAll operations.
docs
If your elements are comparable, and the speed penalty is acceptable. You can always sort the values into another collection and then obtain deterministic order.
The other answer talks about the order of the keys which is irrelevant here.
The answer depends on what happens in between of the two calls to values():
If no modifications are made to the HashMap<K,V>, the order would be the same, because the algorithm that is used to traverse the buckets of the hash map does not have a random component. The order is arbitrary with respect to the items inserted into the map, but it remains the same between iterations.
If you make modifications to the map, the order may change, even if the content of the map remains the same (e.g. because you remove and re-insert an item, or insert and then remove an item).
Deleting an re-inserting an item can change the order of items in the same hash bucket, so the order of iteration of values() will change accordingly.
Inserting an item may grow the number of cache buckets and re-hashing, which will not be undone when the same item is removed. That will change the order of values() as well.
No it is not guaranteed, you need a TreeMap :
https://docs.oracle.com/javase/8/docs/api/java/util/TreeMap.html
Related
This question already has answers here:
Is the order of values retrieved from a HashMap the insertion order
(6 answers)
Closed 7 years ago.
I have read in java 1.7 docs that "It makes no guarantees as to the iteration order of the set".
what is meaning of this?
I created a HashSet print its elements 1000 times. but every time i get a fixed order.
however order is not same as insertion order of element.
Set<String> hashSet = new HashSet<>();
for (int i = 0; i < 10; i++) {
hashSet.add("Item+" + i);
}
for (String s : hashSet) {
System.out.println(s);
}
You should try adding a lot more elements (say, 10.000) to the set. The HashSet has a default capacity of 16, but once you add more elements to the set, it is internally reconstructed. In that case, the order might change.
It means that you can not be sure that the order will be the same, for instance if you run the same code on another JVM.
The fact that the order is always the same on your machine, using one specific JVM is irrelevant. If order is important, consider using a TreeSet, a TreeSet will guarantee that the order is always the same, no matter where you run your code.
Of course: a TreeSet requires that the items can be ordered in some way (e.g. alphabetically). If you want to preserve the order in which elements are added, you may prefer a List such as an ArrayList.
The order of the entries in a HashMap or HashSet is predictable in theory for current generation and older implementations.
However, the prediction depends on at least:
the hash values of the keys,
the initial capacity of the set or map,
the precise sequence in which the keys were added to and removed from the set / map,
the specific implementation of HashSet or HashMap used (the behaviour is Java version dependent, and possibly depended on patch level), and
for Java 8 and later, whether or not the keys are Comparable.
If you have all of that information (and you are prepared to emulate the insertion / removal sequence), you can accurately predict the iteration order. However, it would be tricky to implement, and expensive to run ...
In your example, the hash values are the same, the initial HashSet capacity is the same, the insertion order is the same, and the HashSet implementation is the same. In those circumstances (and given the precise algorithms used) the iteration order is going to repeatable ... even if though it would difficult to predict.
In this case, the order is not "random" because there is no randomness in the process that builds the HashSet. Just calculations that are complicated and opaque ... but deterministic.
I have read in java 1.7 docs that "It makes no guarantees as to the iteration order of the set". what is meaning of this?
What is means is that the javadoc is not committing to any specific behaviour vis-a-vis the ordering. Certainly, there is no commitment to portable behaviour.
See also: Order of values retrieved from a HashMap
In hash collections, entries appear sorted by result of some internal hashing function.
For the same set of entries added to the same collection in the same order, returning order will be always the same though hash function values also remains the same, except if internal structure is reorganized between calls (i. e. by expanding or shrinking of the collection) - on reorganization, values of internal hashing function are recalculated and entries take another places in internal hash table.
BTW, entry iterator of hash collection guarantees only that you will receive all entries you've put there which wasn't removed.
Maybe you can see same "sorting" but this is not real, it's up to the JVM so, if you want a sorted list
If you have a logical sorting use Collections.sort() or implement your own Comparator
If you want the Collection sorted by insertion order use a List and Iterator
List iterators guarantee first and foremost that you get the list's elements in the internal order of the list (aka. insertion order). More specifically it is in the order you've inserted the elements or on how you've manipulated the list. Sorting can be seen as a manipulation of the data structure, and there are several ways to sort the list.
What are the practical scenario for choosing among the linkedhashmap and hashmap? I have gone through working of each and come to the conclusion that linkedhashmap maintains the order of insertion i.e elements will be retrieved in the same order as that of insertion order while hashmap won't maintain order.
So can someone tell in what practical scenarios selection of one of the collection framework and why?
LinkedHashMap will iterate in the order in which the entries were put into the map.
null Values are allowed in LinkedHashMap.
The implementation is not synchronized and uses double linked buckets.
LinkedHashMap is very similar to HashMap, but it adds awareness to the order at which items are added or accessed, so the iteration order is the same as insertion order depending on construction parameters.
LinkedHashMap also provides a great starting point for creating a Cache object by overriding the removeEldestEntry() method. This lets you create a Cache object that can expire data using some criteria that you define.
Based on linked list and hashing data structures with linked list (think of indexed-SkipList) capability to store data in the way it gets inserted in the tree. Best suited to implement LRU ( least recently used ).
LinkedHashMap extends HashMap.
It maintains a linked list of the entries in the map, in the order in which they were inserted. This allows insertion-order iteration over the map. That is,when iterating through a collection-view of a LinkedHashMap, the elements will be returned in the order in which they were inserted. Also if one inserts the key again into the LinkedHashMap, the original order is retained. This allows insertion-order iteration over the map. That is, when iterating a LinkedHashMap, the elements will be returned in the order in which they were inserted. You can also create a LinkedHashMap that returns its elements in the order in which they were last accessed.
LinkedHashMap constructors
LinkedHashMap( )
This constructor constructs an empty insertion-ordered LinkedHashMap instance with the default initial capacity (16) and load factor (0.75).
LinkedHashMap(int capacity)
This constructor constructs an empty LinkedHashMap with the specified initial capacity.
LinkedHashMap(int capacity, float fillRatio)
This constructor constructs an empty LinkedHashMap with the specified initial capacity and load factor.
LinkedHashMap(Map m)
This constructor constructs a insertion-ordered Linked HashMap with the same mappings as the specified Map.
LinkedHashMap(int capacity, float fillRatio, boolean Order)
This constructor construct an empty LinkedHashMap instance with the specified initial capacity, load factor and ordering mode.
Important methods supported by LinkedHashMap
Class clear( )
Removes all mappings from the map.
containsValue(object value )>
Returns true if this map maps one or more keys to the specified value.
get(Object key)
Returns the value to which the specified key is mapped, or null if this map contains no mapping for the key.
removeEldestEntry(Map.Entry eldest)
Below is an example of how you can use LinkedHashMap:
Map<Integer, String> myLinkedHashMapObject = new LinkedHashMap<Integer, String>();
myLinkedHashMapObject.put(3, "car");
myLinkedHashMapObject.put(5, "bus");
myLinkedHashMapObject.put(7, "nano");
myLinkedHashMapObject.put(9, "innova");
System.out.println("Modification Before" + myLinkedHashMapObject);
System.out.println("Vehicle exists: " +myLinkedHashMapObject.containsKey(3));
System.out.println("vehicle innova Exists: "+myLinkedHashMapObject.containsValue("innova"));
System.out.println("Total number of vehicles: "+ myLinkedHashMapObject.size());
System.out.println("Removing vehicle 9: " + myLinkedHashMapObject.remove(9));
System.out.println("Removing vehicle 25 (does not exist): " + myLinkedHashMapObject.remove(25));
System.out.println("LinkedHashMap After modification" + myLinkedHashMapObject);
Shopping Cart is a real life example, where we see cart number against Item we have chosen in order we selected the item. So map could be LinkedHashMap<Cart Number Vs Item Chosen>
HashMap makes absolutely no guarantees about the iteration order. It can (and will) even change completely when new elements are added.
LinkedHashMap will iterate in the order in which the entries were put into the map
LinkedHashMap also requires more memory than HashMap because of this ordering feature. As I said before LinkedHashMap uses doubly LinkedList to keep order of elements.
In most cases when using a Map you don't care whether the order of insertion is maintained. Use a HashMap if you don't care, and a LinkedHashMap is you care.
However, if you look when and where maps are used, in many cases it contains only a few entries, not enough for the performance difference of the different implementations to make a difference.
LinkedHashMap maintain insertion order of keys, i.e the order in which keys are inserted into LinkedHashMap. On the other hand HashMap doesn't maintain any order or keys or values. In terms of Performance there is not much difference between HashMap and LinkedHashMap but yes LinkedHashMap has more memory foot print than HashMap to maintain doubly linked list which it uses to keep track of insertion order of keys.
A HashMap has a better performance than a LinkedHashMap because a LinkedHashMap needs the expense of maintaining the linked list. The LinkedHashMap implements a normal hashtable, but with the added benefit of the keys of the hashtable being stored as a doubly-linked list.
Both of their methods are not synchronized.
Let's take a look their API documentation:
The HashMap is a hash table with buckets in each hash slot.
API documentation:
This implementation provides constant-time performance for the basic
operations (get and put), assuming the hash function disperses the
elements properly among the buckets. Iteration over collection views
requires time proportional to the "capacity" of the HashMap instance
(the number of buckets) plus its size (the number of key-value
mappings). Thus, it's very important not to set the initial capacity
too high (or the load factor too low) if iteration performance is
important.
LinkedHashMap is a linked list implementing the map interface. As
said in the API documentation:
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).
One way that I have used these at work are for cached backend REST queries. These also have the added benefit of returning the data in the some order for the client. You can read more about it in the oracle docs:
https://docs.oracle.com/javase/8/docs/api/java/util/LinkedHashMap.html
This technique is particularly useful if a module takes a map on input, copies it, and later returns results whose order is determined by that of the copy. (Clients generally appreciate having things returned in the same order they were presented.)
A special constructor is provided to create a linked hash map whose order of iteration is the order in which its entries were last accessed, from least-recently accessed to most-recently (access-order). This kind of map is well-suited to building LRU caches. Invoking the put, putIfAbsent, get, getOrDefault, compute, computeIfAbsent, computeIfPresent, or merge methods results in an access to the corresponding entry (assuming it exists after the invocation completes). The replace methods only result in an access of the entry if the value is replaced. The putAll method generates one entry access for each mapping in the specified map, in the order that key-value mappings are provided by the specified map's entry set iterator. No other methods generate entry accesses. In particular, operations on collection-views do not affect the order of iteration of the backing 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.
Is LinkedHashMap LIFO or FIFO in nature?
If my map is of the form:
map.put(1,"one");
map.put(2,"two");
what would be the order if I was to iterate on the map using keyset??
EDIT: I think I did actually confuse two different concepts. Let me rephrase the question. What would be the order in which I encounter the quantities using entryset?Thanks for pointing that out btw. I do not intend to remove any entry.
In a linked hash map the elements in the backing doubly-linked list are added at the end (clearly: for preserving iteration order), but can be removed from any part in the list as the elements get removed from the map, it's incorrect to label the backing list (and by extension: the map) as LIFO or FIFO, it's neither - there's no concept of removal order in a map, and consequently no removal order can be assumed for the backing list in a linked hash map.
What a linked hash map does guarantee is that iterating over its contents (be it: the keys or the entries) will occur in the same order in which the elements were inserted in the map; from the documentation:
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).
EDIT :
Regarding the last edit to the question, a LinkedHashMap guarantees that the iteration order of the keySet() will be the same order in which the elements were inserted: 1, 2 for the example in the question. This has nothing to do with FIFO/LIFO, those concepts deal with the order in which elements are removed from a data structure, and they're not related with the iteration order after inserting elements.
LinkedHashMap to quote from the javadocs is "Hash table and linked list implementation of the Map interface, with predictable iteration order" . So the keySet will return keys based on the order of insertion, esssentially a FIFO.
When access order is not utilized (standard case) you can consider LHM as a linked list w/ very fast access O(1) by key.
In that aspect it is FIFO when access order is unused (look at the c-tors). When access order is used the insertion order doesn't matter if there are any get() operations as they reorder the Entries. Look at protected boolean removeEldestEntry(Map.Entry<K,V> eldest) eldest=FIFO.
Essentially the LHM is a good doubly linked list of Map.Entry<Key, Value> with a hash index over the keys.
I myself never use the vanilla HashMap as in its current impl. it has very little benefit over LHM - lower memory footprint but horrid iteration. Java8 (or 9) perhaps may finally fix HashMap, hopefully Doug Lea will push his impl.
According to Java docs, if you were to iterate over the map, the keyset would be in insertion-order. So the first key you get is the first key entered, over the existing keys. Note, reinserting a key-value pair does not change the original key position.
I am using a linkedHashMap to guarantee order when someone tries to access it. However, when it comes time to iterate over it, does using entrySet() to return key/value pairs guarantee order as well? No changes will be made while iterating.
EDIT: Also, are there any adverse effects from iterating through the map by iterating through its keys and calling get?
According to the Javadocs, yes.
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).
As for the edit, no, it should work just fine. But the entry set is somewhat faster since it avoids the overhead of looking up every key in the map during iteration.
If you're sure no changes will be made during the iteration, then proper ordering with entrySet() is guaranteed, as stated in the API.
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.)