Reputation: 24068
I have a list of objects.
List<MyObject> myList;
This list is populated in the beginning and no update is done after that.
The order of objects in the list is significant because I need to iterate over this list in that order later.
During execution of my program, I frequently need to find the index of a given MyObject
in myList
;
I know that I can use myList.indexOf(object)
but I am worried about the performance. So I am going to use a HashMap
to map each MyObject
in myList
to its index in myList
so that I can find the index much efficiently.
But I am not sure whether I am missing something trivial and I am going to use two containers with redundant data where I could get this done much easily using a different container.
So, can anybody see a better way to do this?
Upvotes: 0
Views: 556
Reputation: 12939
With ArrayList<MyObject> myList;
it takes O(n)
to find index by myList.indexOf(object)
(I don't know about other implementations of List
) so I wouldn't use it unless you can guarantee that the list will be small.
One alternative would be to use LinkedHashMap<MyObject, Integer>
which indeed would preserve the order of elements in which you inserted them to the map, however you would lose the ability to get object from index easily.
You could use LinkedHashMap<MyObject, Integer>
in addition to your original List<MyObject> myList;
so you can both get index from object and vise versa, as well as iterate through the object in the order you added them, however now the LinkedHashMap<MyObject, Integer>
can be replaced by normal HashMap<MyObject, Integer>
as you suggested in the first place.
There is also BiMap from Google's Guava so you can have a look into that.
Upvotes: 0
Reputation: 4256
You can use LinkedHashMap
instead of List
which will solve all your problems. Initially you can initialize you Map
like this:
Map<MyObject, Integer> map = new LinkedHashMap<>();
//...
map.put(myObject1, map.size()); //saves myObject1 and index as 0
map.put(myObject2, map.size()); //saves myObject2 and index as 1
map.put(myObject3, map.size()); //saves myObject3 and index as 2
//...
If MyObject.hashCode()
method implementation is good, map.get(myObject)
will give you good performance and will save you from creating additional collection.
Upvotes: 0
Reputation: 3186
Using hashMap has a time complexity of O(1) for lookup, and accessing an array with a known index also has O(1), which means that finding and accessing an object will result in O(1). You can't do it faster then that.
When it comes to space you are off course doubling your space while having two structures, and a HashMap will even take more space as it needs to fill a whole hash range, but it's still only in O(n).
I think this is a OK approach, but as have been said already LinkedHashMap
will do this automatically for you.
Upvotes: 0
Reputation: 52185
You can use a LinkedHashMap
to contain your MyObject
instances.
Map<String, MyObject> map = new LinkedHashMap<String, MyObject>();
Hash table and linked list implementation of the Map interface, with predictable iteration order.
This will allow you have 1 collection which does both.
Upvotes: 3