ordering a hashset example? - java

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!)

Related

Order of elements in a set in java

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);

Acessing a element in Treeset using index

Suppose there is a string treeset (ts)of elemnent 1,2,3,4,5,6,7,8,9,10.
Is there is any in built method in treeset so that i can access an element.
For eg accessing 3 can i do ts.[2]and accessing 8 ts.[7].(something like that).
i used this method:
Iterator<String> it = ts.iterator();
int i=0;
while(it.hasNext()) {
String ele=it.next();
if(i==2){
System.out.println(ele+"");
}
i++;
}
though when i ran it didn't showed any o/p but if i did i=0 then it showed all the o/p i.e 1,2,3,4,5,6,7,8,9,10.
Secondly can anyone tell me that when it is best to use hashset,treeset and linkedhashset
If you wanna access elements in your collection like ts[2], then you should better convert your collection into array using collection inbuilt method.
Otherwise, using iterator is the standard and efficient way to access elements in collection.
For second question, Hashset is used as hash table ; LinkedHashSet is used as hash table with elements stored in same way as inserted; TreeSet is used for collection using navigations.
For complete knowledge you must check Oracle documentation.
TreeSet is a NavigableSetwhich means you have an order of items (natural ordering as default, but you can define your own ordering relationship by using Comparator or Comparable interface) and you can navigate through items by this order. However there is no index mechanism. Basically a TreeSet is based on a TreeMap which is a red-black tree. In such a data structure indexes (element indexes, not indexes in the sense of efficient access) are not much meaningfull.
HashSet on the other hand is based on a HashMap which is a classical hash table implementation. In this data structure there is no order defined. You can look up each item at O(1) time though due to hash function used.
LinkedHashSet is a subclass of HashSet. Other then HashSet methods no new method is defined, so LinkedHashSet does not allow any more capability like natural order or indexes. However it has an auxilary linked list that keeps track of the order in which elements are inserted. In this way when you iterate over a LinkedHashSet by .iterator() method or a for loop you get elements in the order you inserted.
So basically a HashSet is more appropriate if you will access elements individually. Or being the simplest Set implementation you can use HashSet in generic cases. If you need to keep the order of insertion you need to use LinkedHashSet and if you have to enforce any custom ordering or natural ordering of items you should use TreeSet.

copy elements of arraylist in a set with the same order java

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.

How do i keep a hashset alphabetically ordered?

I have a collection of a big number of objects that are defined by name/value pairs.
I need to have fast access to any of their values and to be able to return them ordered alphabetically by name. First I thought I might use a HashMap to get fast access. But it gave me no ordering. I decided to switch to LinkedHashSet.
The problem with it is that I need to be able to insert new Objects in the right places of the list, but LinkedHashSet doesn't allow that. I also need to be able to access Objects by their index as well as by name.
Will be thankful for any ideas.
Why not try TreeSet. Does your list not allow duplicates? If so then the Set should be ok. As you are adding strings and this implements Comparator the set will be automatically sorted for you
If you had
Set<String> s = new TreeSet<String>();
s.add("B");
s.add("C");
s.add("A");
then the contents of the set would be A, B, C
You can use TreeMap
A Red-Black tree based NavigableMap implementation. 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.
I would use a TreeSet which is a SortedSet. You need to define your custom class as Comparable based on the name and your collection will always be sorted.
Note: sorted collections have an O(log N) access time.
Have you looked at TreeMap? It's based off of Red-Black trees which help maintain ordering, but still gives fast access.
A TreeMap should address your requirements. If your keys are not literals then use appropriate Comparator in TreeMap constructor.

does java sortedhashset type collection exist?

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 :)

Categories