I know HashSet Internally work as HashMap and HashMap internally - java

I know HashSet internally work as HashMap and HashMap internally use LinkedList as FIFO etc. So my Question is when I insert values in StudentRecord class object in pattern like..
StudentsRecord record=new StudentsRecord(1, "Pramod", "UNA");
StudentsRecord record2=new StudentsRecord(2, "Pankaj","Lucknow");
StudentsRecord record3=new StudentsRecord(3, "Santosh","Chennai");
HashSet<StudentsRecord> set=new HashSet<StudentsRecord>();
set.add(record);
set.add(record2);
set.add(record3);
Iterator<StudentsRecord> iterator=set.iterator();
while(iterator.hasNext())
{
StudentsRecord result=(StudentsRecord)iterator.next();
System.out.println(result.getId()+","+result.getName()+","+result.getAddress());
}
After this why my result does not follow FIFO or LIFO order pattern?
My Output is:
3,Santosh,Chennai
1,Pramod,UNA
2,Pankaj,Lucknow

Use LinkedHashSet instead of HashSet. because LinkedHashSet maintains insertion order.
public static void main(String[] args) {
StudentsRecord record=new StudentsRecord(1, "Pramod", "UNA");
StudentsRecord record2=new StudentsRecord(2, "Pankaj","Lucknow");
StudentsRecord record3=new StudentsRecord(3, "Santosh","Chennai");
Set<StudentsRecord> set=new LinkedHashSet<StudentsRecord>();
set.add(record);
set.add(record2);
set.add(record3);
Iterator<StudentsRecord> iterator=set.iterator();
while(iterator.hasNext())
{
StudentsRecord result=(StudentsRecord)iterator.next();
System.out.println(result.getId()+","+result.getName()+","+result.getAddress());
}
}

LinkedHashMap can be used for this purpose.
It is same as HashMap, except that when you iterate over it, it presents the items in the insertion order.
Basically it preserves the insertion order.
from 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.

LinkedHashSet will preserve insertion order for you.

Since none of the other answers actually answered "why":
HashMap stores objects into buckets, and then only uses the lists in the bucket. This is how it is able to find objects fast, as it can go straight to the correct bucket and then only needs to scan the entries inside that bucket.
In this example 3. has been added into an earlier bucket than 2 or 3 and as a result comes back in a different order.
HashMap and HashSet should never be relied upon to provide any particular ordering. You can use LinkedHashMap to retain insertion order or TreeMap to sort the entries.

Related

Create a List of unique values in java

I have data of which the sequence is as important as its unique elements. Meaning if something has already been added it should not be added again and the sequence must be remembered.
Set does not remember the sequence in which it was added (either hash or sort), and List is not unique.
What is the best solution to this problem?
Should one have a list and loop through it to test for uniqueness - which I'm trying to avoid?
Or should one have two collections, one a List and one a Set - which I'm also trying to avoid?
Or is there a different solution to this problem altogether.
In the bellow code was your reference
LinkedHashSet<String> al=new LinkedHashSet<String>();
al.add("guru");
al.add("karthik");
al.add("raja");
al.add("karthik");
Iterator<String> itr=al.iterator();
while(itr.hasNext()){
System.out.println(itr.next());
}
output
guru
karthik
raja
Use LinkedHashSet. It serves as both a List and a Set. It has the uniqueness quality of a set but still remembers the order in which you inserted items to it which allows you to iterate it by order of insertion.
From the Docs:
Hash table and linked list implementation of the Set interface, with predictable iteration order. This implementation differs from HashSet in that it maintains a doubly-linked list running through all of its entries. This linked list defines the iteration ordering, which is the order in which elements were inserted into the set (insertion-order). Note that insertion order is not affected if an element is re-inserted into the set. (An element e is reinserted into a set s if s.add(e) is invoked when s.contains(e) would return true immediately prior to the invocation.)
You can use SortedSet
or LinkedHashSet
LinkedHashSet is the best possible way out

ArrayList to HashMaps in Java

I am trying to get values from an ArrayList that is sorted and want to store it in a HashMap, where the values of the ArrayList become keys of the HashMap. Will the order of the values in the HashMap still be the same as that of ArrayList?
No. Use a TreeMap instead. This will preserve the order of insertion.
HashMap makes no guarantees as to the order the mappings are stored or iterated, so simply running through the ArrayList and putting them into the HashMap as keys will very likely result in unordered iterations.
As others have pointed out, LinkedHashMap does preserve insertion order for iterations. An additional run of insertions will result in unordered iterations again, though. Both HashMap and LinkedHashMap support constant time lookup - LinkedHashMap pays for its extra feature in space (by maintaining pointers between the keys).
As others have also pointed out, TreeMap preserves order after updates, so this might be a better option for you, or not. Of course, if the ArrayList is sorted with a specific Comparator, you must feed that same Comparator to the TreeMap on construction for the sorting to be the same. Note that TreeMap does not have constant time lookup, due to being implemented as a Red-Black search tree.
As your ArrayList has been ordered, no need to use a TreeMap because this will compare to order again and it's not necessary. You should use a LinkedHashMap that will keep the exact order of your ArrayList when you put your value in.
Check This: Insert Values of ArrayList into HashMap
HashMap<String, Item> itemMap = new HashMap<String, Item>();
for (Item item : itemList)
{
itemMap.put(item.getitemCode(), item);
}

Maintaining order in HashMap [duplicate]

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.

Why do we not get the ordered sequence in HashSet

I am using the HashSet for adding the elements and retrieving them, I know that I will not retrieve the data in sequence in which I added them, but I want to know the exact reason why Is it happeing?
import java.util.HashSet;
import java.util.Iterator;
public class HS {
public static void main(String args[]) {
HashSet h=new HashSet();
h.add("Mayank");
h.add("Mayank");
h.add("Vashist");
h.add("Dinesh");
h.add("Vashist");
Iterator itr=h.iterator();
while(itr.hasNext()) {
System.out.println(itr.next());
}
}
}
This is just the contract for a Set in java, from the javadoc
Returns an iterator over the elements in this set.
The elements are returned in no particular order (unless this set is an instance of some class that provides a guarantee). So an implementation of Set isn't required to maintain any order in the values.
In order to return values in order the Set needs to maintain the order. This has costs for speed and space.
A LinkedHashSet maintains insertion order.
HashSet does not preserve the element addition order. First it computes the object hash code that should stay constant but is difficult to predict, and then uses it to select a bucket that is a list of objects that have had the same bucket selected. As an Iterator just iterates over all buckets, the iteration order is largely unpredictable.
Use LinkedHashSet instead if you need to preserve the order. However LinkedHashSet maintains an additional linked list so needs more resources.
A HashSet uses what is referred to as a hash table to store items.
A hash table is made up of several "slots" into which your items are put. Deciding what slot to put an item into is determined by that item's hash code which generally has no relationship to the natural ordering of the item.
A TreeSet, on the other hand, stores items based on their natural ordering which allows an in-order traversal of its contents. This order will be based on the natural ordering of the objects and not the order in which they were inserted. Another difference between a TreeSet and HashSet is that a HashSet provides O(1) lookup, insertion and removal where as a TreeSet provides O(log(n)) lookup, insertion and removal.
A LinkedHashSet maintains insertion order of items by constructing links between the elements as they are inserted.
Because in HashSet there is a hash value calculated for each object and this hash value determines the array index of the particular object in the container. So the order of inserted elements are naturally not preserved.
This allows for accessing desired elements with O(1) complexity but it costs a lot of memory.
http://en.wikipedia.org/wiki/Hash_table
From the official documentation:
This class implements the Set interface, backed by a hash table
(actually a HashMap instance). 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. [...] The iterators returned
by this class's iterator method are fail-fast: if the set is modified
at any time after the iterator is created
Here is ordered version:
import java.util.Set;
import java.util.Iterator;
import java.util.Collections;
import java.util.LinkedHashSet;
public class HS {
public static void main(String args[]) {
Set<String> h=Collections.synchronizedSet(new LinkedHashSet<String>());
h.add("Mayank");
h.add("Mayank");
h.add("Vashist");
h.add("Dinesh");
h.add("Vashist");
Iterator<String> itr=h.iterator();
while(itr.hasNext()) {
System.out.println(itr.next());
}
}
}

Java Map question

I have one Map that contains some names and numbers
Map<String,Integer> abc = new HashMap<String,Integer>();
It works fine. I can put some values in it but when I call it in different class it gives me wrong order. For example:
I putted
abc.put("a",1);
abc.put("b",5);
abc.put("c",3);
Iterator<String> iter = abc.keySet().iterator();
while (iter.hasNext()) {
String name = iter.next();
System.out.println(name);
}
some time it returns the order (b,a,c) and some time (a,c,b).
What is wrong with it? Is there any step that I am missing when I call this map?
Edit:
I changed to HashMap and result is still same
The only thing that's wrong is your expectations. The Map interface makes no guarantees about iteration order, and the HashMap implementation is based on hash functions which means the iteration order is basically random, and will sometimes change completely when new elements are added.
If you want a specific iteration order, you have thee options:
The SortedMap interfaces with its TreeMap implementation - these guarantee an iteration order according to the natural ordering of the keys (or an ordering imposed by a Comparator instance)
The LinkedHashMap class iterates in the order the elements were added to the map.
Use a List instead of a Map - this has a well-defined iteration order that you can influence in detail.
I think you need LinkedHashMap.
A TreeMap will always have keys in their natural order (unless you provide a comparator) If you are seeing the order any differently it will be the way you are looking at the map and what you are doing with it. If in doubt, use a debugger and you will see the order is sorted.
If you wish to get map values in the same order you used to insert them use LinkedHashMap instead.

Categories

Resources