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.
Related
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.
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 would you go about maintaining an order of collection business objects
<BO1, BO2, BO3, BO4>
so that when you remove BO2, amd BO4 you get
<BO1, BO3>
and then when you add BO2
<BO1, BO2, BO3>
You have several ways of doing that but it depends of the type of collection you want to use. Obviously, you don't want to maintain the order of insertions but an order based on the type of elements in the list.
So, before saying use this or that, ask yourself the following question:
Can my collection hold duplicate elements?
1) If YES: then you could use an implementation of a List object (ArrayList, LinkedList, etc). But you will need to sort the list after each insertion:
List<MyObj> list = ...
list.add(myObjInstance);
Collections.sort(list);
To avoid having to sort the list on each insertion you could use the TreeList implementation from Apache Commons Collections.
2) If the answer to the previous question is NO. Then use a TreeSet, you won't need sort the collection on each insertion with that implementation.
Be aware that your object elements have to implement the Comparable interface in order to be sortable.
Unless you use a sorted order, I don't see how the collection is supposed to know that BO2 should go in the middle.
This will do what you want if your Business object implement Comparable
SortedSet<BusObj> bos = new TreeSet<>();
bos.addAll(Arrays.asList(bo1, bo2, bo3, bo4));
bos.removeAll(Arrays.asList(bo2, bo4));
bos.add(bo2);
Make your business object Comparable and use a sorted collection (like TreeSet which is a SortedSet).
Use a SortedSet
http://docs.oracle.com/javase/7/docs/api/java/util/SortedSet.html
There are 2 options: use a List and do the sorting yourself by inserting at the proper location or use a sorted collection.
The sorted collection I think you want is SortedSet http://docs.oracle.com/javase/6/docs/api/java/util/SortedSet.html.
The SortedSet requires entries to implement the Comparable interface.
There is also another question that you should look at: Sorted collection in Java
Aswering my question:
I guess also PriorityQueue would be a solution, if one were not interested in the random access.
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 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!)