In Java 5, If i have a Set, and i add two objects to the Set. When I retrieve the objects, will it give me back in the same order as I added?
I am not able to find the answer to this. Does it depend on which Set implementation I use?
Yes, it depends on which implementation you use. For example, LinkedHashSet will preserve insertion order:
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.)
... but HashSet won't:
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.
Straight from the documentation:
The elements are returned in no particular order (unless this set is
an instance of some class that provides a guarantee).
Depends on Set implementation. LinkedHashSet does exactly that.
Yes it does depend on the implementation you choose. HashSet will not guarantee order but LinedHashSet will.
JavaDocs is your best friend. It's implementation specific. For example:
java.util.Set:
Iterator<E> iterator();
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).
and
java.util.TreeSet:
public Iterator<E> iterator();
Returns an iterator over the elements in this set in ascending order.
The Set interface itself is for unordered container implementations. But there might be implementations of Set that do return the elements in a particular order.
Also see the documentation of Set.iterator:
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)
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.
If i create 2 lists from the same set, can I be sure that I get the same ordering in both the lists? (I do not care about the ordering as long as both the lists have the same order and I am not performing any operations on the sets between creating the two lists.)
List l = new ArrayList(set);
List l1 = new ArrayList(set);
I understand that there are guaranteed ways of creating these lists and getting the same order and that there isn't a good reason for me to create two lists this way, but I would like to know why the ordering of elements in a set would change if no modify operations are performed on it.
Edit: The set is an unordered HashSet
You will propably get the same ordering in the lists l and l1. But since most Sets are unordered, you have no guarantee that there will be the same order.
Technically you could write an implementation of the Set interface which changes its order everytime any method is called. This would still fulfil the interface.
Since in the constructor new ArrayList(Collection) the toArray method of the collection is called, we can have a look at the Javadoc of Set#toArray():
Returns an array containing all of the elements in this set. If this set makes any guarantees as to what order its elements are returned by its iterator, this method must return the elements in the same order.
While the Javadoc of Set#iterator() says there is no general guarantee:
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).
Given this, I would strongly advise you not to rely on the ordering of the lists.
As per documentation
public ArrayList(Collection c) Constructs a list
containing the elements of the specified collection, in the order they
are returned by the collection's iterator
So it really depends on the Set interface implementation class, if the order is constant.
For example, if you use LinkedHashSet the iteration order is predictable.
There are structures that their orders are guaranteed or not. If we mention of Set interface implemented by Java, there is no guarantee. Most likely the constructor of ArrayList make uses of iterator of Set. So both list certainly contain always same elements but order. That's actually why Set uses contains keyword instead of find to check an element whether it exists.
It's sub-interface, SortedSet, represents a set that is sorted
according to some criterion. In Java 6, there are two standard
containers that implement SortedSet. They are TreeSet and
ConcurrentSkipListSet.
In addition to the SortedSet interface, there is also the
LinkedHashSet class. It remembers the order in which the
elements were inserted into the set, and returns its elements in that
order.
One way to impose a desired (natural, or otherwise) order on an unordered collection like a Set is to create an ordered Set (in other words, a SortedSet) from the given set. If your sets are not too large and all you care for is a predictable iteration order, you can do:
// set = ...
List<? extends Comparable> list = new TreeSet<>(set).stream().collect(Collectors.toList());
This assumes that the set consists of elements that are comparable. Alternatively, you could use your own comparator in the TreeSet constructor. There may be some issues in creating such a comparator however, if the elements themselves are not comparable.
There are some intertesting and good answers here, I can propose a solution.
List list = new ArrayList(set);
List secondList = new ArrayList(list);
I have some of values in my java program. I just stored those values in HashSet. I have stored it by for loop. The values iterating by loop has been ordered differently after the set formed. How can restrict this order change of HashSet as I get from the loop. Can anyone help me please?
If you want the set to maintain the insertion order, you can use a LinkedHashSet:
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).
Alternatively, if you want your set to be ordered, you can use a TreeSet.
A HashSet is unordered, as the javadocs specify:
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 might want to consider using a LinkedHashSet, which maintains the order of insertions.
An alternative is using one of the NavigableSet implementations, such as the TreeSet which guarantee order according to the natural order or Comparator, if given.
use LinkedHashSet predictable iteration order
Does such a thing exist anywhere? Basically I see java has LinkedHashSet but no type of navigatable hash set?
By its very nature, a hash-based data structure is not ordered. You can write wrappers which supplement it with an additional data structure (this is more or less what LinkedHashMap does). But while it makes some sense to keep a hash set and a list, in order to keep a good ordering, you would need a tree or similar data structure. But the tree can work as a set by itself, so you would essentially be duplicating the information (more than in the case of set plus list, which differ more than two different set implemnentations). So the best solution is to just use TreeSet or another SortedSet if you need order.
It's not a HashSet, but as a descendant of Set you have the TreeSet
This class implements the Set interface, backed by a TreeMap instance. This class guarantees that the sorted set will be in ascending element order
You can traverse the elements using the iterator
public Iterator iterator()
Returns an iterator over the elements in this set. The elements are returned in ascending order
You can use a TreeSet but all the operations in it are lg(n)
You can use a LinkedHashSet, which keeps a linked list on top of hashset, but it only maintains insertion ordering (first inserted will be first element in iterator), you cannot have natural or custom ordering
You could also use TreeSet+HashSet approach but two reference for each element will be kept and while add and remove would still be lg(n) the contains will become expected o(n)
choose wisely :)
I guess there's TreeMap which is...related but definitely not the same :)
I know LinkedHashMap has a predictable iteration order (insertion order). Does the Set returned by LinkedHashMap.keySet() and the Collection returned by LinkedHashMap.values() also maintain this order?
The Map interface provides three
collection views, which allow a map's contents to be viewed as a set
of keys, collection of values, or set
of key-value mappings. The order of
a map is defined as the order in which
the iterators on the map's collection
views return their elements. Some map
implementations, like the TreeMap
class, make specific guarantees as to
their order; others, like the
HashMap class, do not.
-- Map
This linked list defines the iteration
ordering, which is normally the order
in which keys were inserted into the
map (insertion-order).
-- LinkedHashMap
So, yes, keySet(), values(), and entrySet() (the three collection views mentioned) return values in the order the internal linked list uses. And yes, the JavaDoc for Map and LinkedHashMap guarantee it.
That is the point of this class, after all.
Looking at the source, it looks like it does. keySet(), values(), and entrySet() all use the same entry iterator internally.
Don't get confused with LinkedHashMap.keySet() and LinkedHashMap.entrySet() returning Set and hence it should not guarantee ordering !
Set is an interface with HashSet,TreeSet etc beings its implementations. The HashSet implementation of Set interface does not guarantees ordering. But TreeSet does. Also LinkedHashSet does.
Therefore it depends on how Set has been implemented in LinkedHashMap to know whether the returning Set reference will guarantee ordering or not.
I went through the source code of LinkedHashMap, it looks like this:
private final class KeySet extends AbstractSet<K> {...}
public abstract class AbstractSet<E> extends AbstractCollection<E> implements Set<E> {...}
Thus LinkedHashMap/HashMap has its own implementation of Set i.e. KeySet. Thus don't confuse this with HashSet.
Also, the order is maintained by how the elements are inserted into the bucket. Look at the addEntry(..) method of LinkedHashMap and compare it with that of HashMap which highlights the main difference between HashMap and LinkedHashMap.
You can assume so. The Javadoc says 'predictable iteration order', and the only iterators available in a Map are those for the keySet(), entrySet(), and values().
So in the absence of any further qualification it is clearly intended to apply to all of those iterators.
AFAIK it is not documented so you cannot "formally" assume so. It is unlikely, however, that the current implementation would change.
If you want to ensure order, you may want to iterate over the map entires and insert them into a sorted set with an order function of your choice, though you will be paying a performance cost, naturally.