List interface allows us to get the object using get() method at an index.
How can we obtain the object at the particular index in set interface like LinkedHashSet
Set is unordered. There isn't the concept of index.
Therefore, if you want to get a particular element, you are forced to loop over it and break as soon as you find element you wanted.
http://docs.oracle.com/javase/7/docs/api/java/util/Set.html
and here: http://docs.oracle.com/javase/6/docs/api/java/util/LinkedHashSet.html
But a set is only used to check if something is in the list, not where it is.
Short answer is, it is not possible. However, you can get an array that has all datum from the Set you are using and then accessing it via an index. This has to do with the abstraction provided by Set which is different from List.
A Set is simply a collection that does not allow duplicates (no comments on ordering), but a List is a collection that implies ordering, so each value has an associated index.
You can't. There is no indexed acces for a set since it is not ordered.
Related
I have a data structure that is of type List<List<CustomObject>>. I want to be able to find the position of a particular CustomObject in my data structure. The output would show me the index for e.g. 1,0 which means the CustomObject is the 0th element in the 1st list item.
I have thought of the following ways to implement this:
Loop through the list one by one and compare the CustomObject. Of course i'll have to implement the equals method in CustomObject to compare.
Use the indexOf method to figure out the first index of the data structure which has the CustomObject. However in this the parameter to equals would be List<CustomObject>.
Are there any other efficient ways to get the index?
Iterate over the main list and call .contains () to check if object is there. If true, use indexOf() to locate it.
You must properly implement equals() and hashcode() in your object .
You can also use .lastIndexOf(Object o) method to get the index of your object directly in one call. This method will give you -1 if that object does not exist in the list.
Check the doc for more detail.
http://docs.oracle.com/javase/7/docs/api/java/util/List.html#lastIndexOf(java.lang.Object)
The only issue is this method will give you only the last occurrence of the object. If you have duplicate objects in the list, this will not work.
Also you must properly implement equals and hashcode method for proper comparison to occur.
indexOf iterates for you, so 1) and 2) are actually the same. And if the element you're looking for is in the last slot of the last list you iterate over the entire dataset.
To get better then that, you'll have to store the index explicitly in a second datastructure that allows for more efficient searching. Taking the winner in the "search" category for datastructures from http://bigocheatsheet.com/ - a HashMap in java - you could do it as follows:
In a HashMap<CustomObject, Index> you store per object the desired index. That also needs to be updated each time you update the list. Both updating and searching for an item requires only constant time, in other words is independent of the amount of elements you have.
With such a map in place, instead of searching through your list, you'll do map.get(customObject) and you'll have the result.
The question for you to answer: can you keep such a datastructure up to date consistently and with less effort than searching in a list. Because if you update your list in a way that affects multiple elements you may loose all benefit due to constantly redoing the entire map.
Besides using multiple datastructures, maybe there is 1 that fits both needs better than a list and a map. But that depends on your data and how you need to access it and which part thereof needs to be optimized.
I need to store unique objects in some datastructure, but also I need access by index like in ArrayList or plain array. Maybe there is some elegant way to do this without using convertions from set to array, iteration through all elemnts, checking value while adding to ArrayList and others.
I would be grateful for any help and advices.
You should have a look at ListOrderedSet from Apache Commons Collections:
Decorates another Set to ensure that the order of addition is retained and used by the iterator.
If an object is added to the set for a second time, it will remain in the original position in the iteration. The order can be observed from the set via the iterator or toArray methods.
The ListOrderedSet also has various useful direct methods. These include many from List, such as get(int), remove(int) and indexOf(int). An unmodifiable List view of the set can be obtained via asList().
Make your own class containing a HashSet<T> and an ArrayList<T>. For the add/append operation, if the element is not already in the set, append it to the list and add it to the HashSet. You'll use about twice as much memory as a normal ArrayList, but you'll get O(1) random access and contains operations.
I am considering using a Java collection that would work best with random insertions. I will be inserting a lot and only read the collection once at the end.
My desired functionality is adding an element at a specified index, anywhere between <0, current_length>. Which collection would be the most efficient to use?
Useful link for your reference:
http://www.coderfriendly.com/wp-content/uploads/2009/05/java_collections_v2.pdf
Not entirely sure how you will be reading the information post input (and how important it is to you). Hashmap or ArrayList would make sense depending on what you are looking to do. Also not sure if you are looking for something thread safe or not.
Hope it helps.
The inefficiency of using List is endemic to the problem. Every time you add something, every subsequent element will have to be re-indexed - as the javadoc states:
Shifts the element currently at that position (if any) and any
subsequent elements to the right (adds one to their indices).
From your question/comments, it would appear that you have a bunch of Objects, and you're sorting them as you go. I'd suggest a more efficient solution to this problem would be to write a Comparator (or make your object implement Comparable), and then use Collections.sort(list, comparator) (or Collections.sort(list)).
You might suggest that your Objects are being sorted on the basis of other variables. In which case, you could create an extension of the Object, with those other variables as fields and extending Comparable, and with a method like getOriginal(). You add these wrapped objects to your list, sort, and then iterate through the list, adding the original objects (from getOriginal()) to a new list.
For info on the sorting algorithm of collections - see this SO question
If I am going to create a Java Collection, and only want to fill it with elements, and then iterate through it (without knowing the necessary size beforehand), i.e. all I need is Collection<E>.add(E) and Collection<E>.iterator(), which concrete class should I choose? Is there any advantage to using a Set rather than a List, for example? Which one would have the least overhead?
which concrete class should I choose?
I would probably just go with an ArrayList or a LinkedList. Both support the add and iterator methods, and neighter of them have any considerable overhead.
Is there any advantage to using a Set rather than a List, for example?
No, I wouldn't say so. (Unless you rely on the order of the elements, in which case you must use a List, or want to disallow duplicates, in which case you should use a Set.)
(I don't see how any Set implementation could beat a list implementation for add / iterator methods, so I'd probably go with a List even if I don't care about order.)
Which one would have the least overhead?
Sounds like micro benchmarking here, but if I'd be forced to guess, I'd say ArrayList (or perhaps LinkedList in coner cases where ArrayLists need to reallocate memory often :-)
Do not go with a Set. Sets and Lists differ according to their purpose, that you should always consider when choosing the right Collection
a List is there for maintaining elements in the order you added them; and if you insert the same element twice it will be kept twice
a Set is there for holding one specific element exactly once (uniqueness); order is only relevant for specific implementations (like TreeSet), but still elements that are 'the same' would not be added twice
Set is only meaningful if you want to sort your objects and to make sure no duplicate element is 'registered'. Else, an ArrayList is just fine.
However, if you want to add elements while iterating too, an ArrayBlockingQueue is better.
Here are some key points which can help you to choose your collection according to your requirement -
List(ArrayList or LinkedList)
Allowed duplicate values.
Insertion order preserved.
Set
Not allowed duplicate values.
Insertion order is not preserved.
So according to your requirement List seems to be a suitable choice.
Now Between ArrayList and LinkedList -
ArrayList is a random access list. Use if your frequent operation is the retrieval of elements.
LinkedList is the best option if you want to add or remove elements from the list.
What changes to be done in ArrayList to make it behave like a Set (means it should not accept any duplicate values).
There are many ways to accomplish this. Here are a two:
Store the elements of the ArrayList in random order. When inserting a new value, do a linear scan over the elements and see if the element you're adding already exists. If so, don't add it. Otherwise, append it to the elements.
Enforce that the elements of the ArrayList always be stored in sorted order. To insert a new element, do a binary search to find where that element should be placed, and if the element already exists don't insert it. Otherwise, insert it at the given position.
However, you shouldn't be doing this. These approaches are very slow compared to HashSet or TreeSet, which are specialized data structures optimized to handle this efficiently.
Create your own implementation , implement java.util.List
override add(), addAll() , make use of contains()
As the others said, it's unclear why you need this.
Maybe LinkedHashSet is what you need?
http://download.oracle.com/javase/6/docs/api/java/util/LinkedHashSet.html
Other than already said, you could have a look at java.util.concurrent.CopyOnWriteArraySet. If you leave the "CopyOnWrite" part away, you have your ArraySet.