I want to know that in which manner, the data is retrieve in HashSet
I have inserted data in different order and output data is in another order.
Can someone please tell the logic behind this?
Code is like this :-
class Test
{
public static void main(String[]args)
{
HashSet<String> h = new HashSet<String>();
// Adding elements into HashSet using add()
h.add("India");
h.add("Australia");
h.add("South Africa");
System.out.println(h);
}
}
Output:- [South Africa, Australia, India]
From Javadoc of HashSet
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.
HashSet works same as HashMap with Value. Moreover It internally uses HashMap With value constant Object called "PRESENT". By doing this HashSet guarantee uniqueness but not order It locate the set elements similarly as what Hashmap do.
You can see the implementation of HashSet on internet.
As said, the ordering of elements in a HashSet is not guaranteed to be anything, nor to be constant over time.
This is due to the nature of the underlying data structure.
In your case, it looks like the Strings were stored in a LIFO queue, but another implementation of HashSet may well do things differently (and even this one might as more items get inserted, start to behave differently).
As per the above, please see the Javadoc for HashSets - the order is not guaranteed. https://docs.oracle.com/javase/7/docs/api/java/util/HashSet.html
Use the LinkedHashSet if you want it to maintain the order of elements.
Related
my question was why does iterator work on set?
Here is my example code,
public class Staticex {
public static void main(String[] args) {
HashSet set = new HashSet();
set.add(1);
set.add(2);
set.add(3);
set.add(4);
set.add(5);
Iterator iter = set.iterator();
while (iter.hasNext()) {
System.out.println(iter.next());
}
}
}
I understand, set is unordered, In contrast List
So, How can get the values one by one through an iterator?
Is iterator changing set into like list which ordered data structure?
How can Iterator can using in set?
Like you are using it.
How can get the values one by one through an iterator?
Your code is doing that.
Is iterator changing set into like list which ordered data structure?
No.
The thing that you are missing is what "unordered" means. It means that the order in which the (set's) elements are returned is not predictable1, and not specified in the javadocs. However each element will be returned once and (since the elements of a set are unique!) only once for the iteration.
1 - Actually, this is not strictly true. If you have enough information about the element class, the element values, how they were created and how / when they were added to the HashSet, AND you analyze the specific HashSet implementation ... it is possible that you CAN predict what the iteration order is going to be. For example if you create a HashSet<Integer> and add 1, 2, 3, 4, ... to it, you will see a clear (and repeatable) pattern when you iterate the elements. This is in part due to the way that Integer.hashCode() is specified.
Referring to the documentation, we see that:
Iterator<E> iterator()
Returns an iterator over the elements in this collection. There are no guarantees concerning the order in which the elements are returned (unless this collection is an instance of some class that provides a guarantee).
Since there are no guarantees concerning the order in which the elements are returned for iterator, it is not a problem for iterator to apply to Set, which is unordered.
Further, it is not changing the Set into a List
Set is unordered in a logical sense. When you have a bag of things, there isn't a sense of order when they are inside the bag. But when you take each thing out of the bag, one at a time, you end up with some order. And like the other answer has mentioned, you cannot rely on that order since it is purely accidental.
I understand, set is unordered, In contrast List
This is not necessarily true. SortedSet is a subinterface of Set. As the name implies, instances of this interface are ordered in some fashion. For example, TreeSets are ordered using their natural ordering, or by a Comparator provided at set creation time, depending on which constructor is used. Also, the main distinction between Set and List is that List allows for duplicate objects to be contained, whereas Set does not.
Now, if you are talking specifically about HashSet, then you are correct about being unordered.
I think your confusion is because you are asking yourself "why is the print out showing the numbers in numeric (insertion) order?" This is sort of a complicated answer for someone of your familiarization level, but the order in which they are printed out is because you are inserting integers and their hash code are basically their numeric values. And, although there is no guarantee as to the order in which the elements of the hash set are returned when iterating, the implementation of HashSet is backed by a hash table. In fact, if you change the insertion order of those same values, most likely the numbers will be printed out in the same numeric order. Now, remember that with all that, the order is not guaranteed. This may not be true, for instance, if you change the set elements to be String objects.
Our existing code using HashSet to store data's.I know Nature of the Set interface is giving random order.But i need the same insertion order.Is there any way to get the insertion order from the set???
Please guide me get out of this issue?
I also used LinkedHashSet, it also giving elements in some other order and not insertion order that i wanted...
Set attachmentSet=new HashSet();
attachmentSet.add("dfsdfsd");
attachmentSet.add("erwerwer");
attachmentSet.add("vcvcvcv");
attachmentSet.add("ytytyt");
Iterator attachItr=attachmentSet.iterator();
while(attachItr.hasNext())
{
System.out.println("SET Item::"+attachItr.next());
}
LinkedHashSet newCopy = new LinkedHashSet();
newCopy.add("dfsdfsd");
newCopy.add("erwerwer");
newCopy.add("vcvcvcv");
newCopy.add("ytytyt");
Iterator attachItr2=copy.iterator();
while(attachItr2.hasNext())
{
System.out.println("NEW LinkedHashSet Item::"+attachItr2.next());
}
I would say that it is not possible because of the way hash set works:
When you insert something into a hash set, its hash is computed (a special unique value obtained through some maths) and it is then stored as a mapping from its hash to its value. No 'history' of insertion is kept.
If you do want to achieve what you describe, you better choose another data structure such as a linked list.
Edit: as suggested by llogiq and Sasikumar Murugesan, a good data structure that could fit your needs and keep the rest of your software as is would be to use a LinkedHashSet. This allows your software to still use HashSet elsewhere.
Seelenvirtuose has it right: LinkedHashSet maintains insertion order. Also your code has an error, in that you iterate copy instead of newCopy. Perhaps that is the reason why you did not see the correct ordering?
Also if you wanted to test that it does not sort by natural order, it would be good to add elements so that natural order differs from insertion order.
You have to use LinkedHashSet to retain insertion order and see below sample code
LinkedHashSet lhs = new LinkedHashSet();
lhs.add("a");
lhs.add("b");
lhs.add("c");
lhs.add("d");
lhs.add("e");
Iterator iterator=lhs.iterator();
while(iterator.hasNext())
{
String value=(String)iterator.next();
System.out.println("Value :"+value);
}
Output:
a
b
c
d
e
I've sorted an arraylist of int in ascending order, but when I copy it in a set, the elements are not sorted anymore.
I'm using this :
HashSet<Integer> set = new HashSet<Integer>(sortedArray);
why is like that?
LinkedHashSet will keep the order. TreeSet will sort based either on an external Comparator or natural ordering through Comparable.
A general point of a Set is that order is irrelevant. Hashing is intended to put the elements in as random an order as possible. LinkedHashSet maintains a linked-list between references to the elements, so can maintain an order.
BitSet (which is not a Set) may, or may not, provide a more efficient data structure.
HashSet's don't sort or maintain order, and the API will tell you this:
it does not guarantee that the order will remain constant over time.
Consider using another type of Set such as a TreeSet.
If you just care about uniqueness, use the HashSet. If you're after sorting, then consider the TreeSet.
you need to use TreeSet and implement a Comparator object or Comparable interface for your data. you can read about Object ordering here
hash set is designed for quick access to unique data, not for maintaining a particular order.
I have a code in which for-each-loops on a Set need to rely on the fact that the iterator returns the elements always in the same order, e.g.
for(ParameterObject parameter : parameters) {
/* ... */
}
The iterators returned by HashSet are not guaranteed to have this property, however it is documented that the iterators of LinkedHashSet do have this property. So my code uses a LinkedHashSet and everything works fine.
However, I am wondering if I could endow the my code with a check that the set passed to it conforms to the requirement. It appears as if this is not possible (except of a direct test on LinkedHashSet). There is no interface implemented by LinkedHashSet which I could test on and there is no interface implemented by LinkedHashSet.iterator() which I could test on. It would be nice if there is an interface like OrderConsistentCollection or OrderConsistentIterator.
(I need this property here).
There isn't a way you can check for it -- but you can ensure it anyway, by simply copying the set into a collection that does have that property. A LinkedHashSet would do the trick, but if all you need is the iteration, an ArrayList would probably serve you better.
List<Foo> parameters = new ArrayList<>(parametersSet);
Now parameters will always return an iterator with the same ordering.
That said, you'd probably be fine with Evgeniy Dorofeev's suggestion, which points out that even the sets that don't guarantee a particular ordering usually do have a stable ordering (even if they don't guarantee it). HashSet acts that way, for instance. You'd actually have to have a pretty funky set, or take active randomization measures, to not have a stable ordering.
HashSet's ordering is not guaranteed, but it depends on the hash codes of its elements as well as the order in which they were inserted; they don't want to guarantee anything because they don't want to lock themselves into any one strategy, and even this loose of a contract would make for essentially random order if the objects' hash codes came from Object.hashCode(). Rather than specifying an ordering with complex implications, and then saying it's subject to change, they just said there's no guarantees. But those are the two factors for ordering, and if the set isn't being modified, then those two factors are going to be stable from one iteration to the next.
'HashSet.iterator does not return in any particular order' means that the elements returned by iterator are not sorted or ordered like in List or LinkedHashSet. But the HashSet.iterator will always return the elements in one and the same order while the HashSet is the same.
HashSet iterator is actually predictable, see this
HashSet set = new HashSet();
set.add(9);
set.add(2);
set.add(5);
set.add(1);
System.out.println(set);
I can foretell the output, it will be 1, 2, 5, 9. Because the elements kind of sorted by hashCode.
I need an example on how to use a comparable class on a HashSet to get an ascending order. Let’s say I have a HashSet like this one:
HashSet<String> hs = new HashSet<String>();
How can I get hs to be in ascending order?
Use a TreeSet instead. It has a constructor taking a Comparator. It will automatically sort the Set.
If you want to convert a HashSet to a TreeSet, then do so:
Set<YourObject> hashSet = getItSomehow();
Set<YourObject> treeSet = new TreeSet<YourObject>(new YourComparator());
treeSet.addAll(hashSet);
// Now it's sorted based on the logic as implemented in YourComparator.
If the items you have itself already implements Comparable and its default ordering order is already what you want, then you basically don't need to supply a Comparator. You could then construct the TreeSet directly based on the HashSet. E.g.
Set<String> hashSet = getItSomehow();
Set<String> treeSet = new TreeSet<String>(hashSet);
// Now it's sorted based on the logic as implemented in String#compareTo().
See also:
Object ordering tutorial
Collections tutorial - Set Implementations
HashSet "makes no guarantees as to the iteration order of the set." Use LinkedHashSet instead.
Addendum: I would second #BalusC's point about implementing Comparable and express
a slight preference for LinkedHashSet, which offers "predictable iteration order ... without incurring the increased cost associated with TreeSet."
Addendum: #Stephen raises an important point, which favors #BalusC's suggestion of TreeMap. LinkedHashSet is a more efficient alternative only if the data is (nearly) static and already sorted.
HashSets do not guarantee iteration order:
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. This class permits the null
element.
You probably need to choose a different datastructure if you want to be able to control the iteration order (or indeed have one at all!)