Java collection insertion: Set vs. List

2019-04-06 01:15发布

问题:

I'm thinking about filling a collection with a large amount of unique objects. How is the cost of an insert in a Set (say HashSet) compared to an List (say ArrayList)?

My feeling is that duplicate elimination in sets might cause a slight overhead.

回答1:

There is no "duplicate elimination" such as comparing to all existing elements. If you insert into hash set, it's really a dictionary of items by hash code. There's no duplicate checking unless there already are items with the same hash code. Given a reasonable (well-distributed) hash function, it's not that bad.

As Will has noted, because of the dictionary structure HashSet is probably a bit slower than an ArrayList (unless you want to insert "between" existing elements). It also is a bit larger. I'm not sure that's a significant difference though.



回答2:

You're right: set structures are inherently more complex in order to recognize and eliminate duplicates. Whether this overhead is significant for your case should be tested with a benchmark.

Another factor is memory usage. If your objects are very small, the memory overhead introduced by the set structure can be significant. In the most extreme case (TreeSet<Integer> vs. ArrayList<Integer>) the set structure can require more than 10 times as much memory.



回答3:

If you're certain your data will be unique, use a List. You can use a Set to enforce this rule.

Sets are faster than Lists if you have a large data set, while the inverse is true for smaller data sets. I haven't personally tested this claim.

Which type of List?
Also, consider which List to use. LinkedLists are faster at adding, removing elements.

ArrayLists are faster at random access (for loops, etc), but this can be worked around using the Iterator of a LinkedList. ArrayLists are are much faster at: list.toArray().



回答4:

If the goal is the uniqueness of the elements, you should use an implementation of the java.util.Set interface. The class java.util.HashSet and java.util.LinkedHashSet have O(alpha) (close to O(1) in the best case) complexity for insert, delete and contains check.

ArrayList have O(n) for object (not index) contains check (you have to scroll through the whole list) and insertion (if the insertion is not in tail of the list, you have to shift the whole underline array).

You can use LinkedHashSet that preserve the order of insertion and have the same potentiality of HashSet (takes up only a bit more of memory).



回答5:

You have to compare concrete implementations (for example HashSet with ArrayList), because the abstract interfaces Set/List don't really tell you anything about performance.

Inserting into a HashSet is a pretty cheap operation, as long as the hashCode() of the object to be inserted is sane. It will still be slightly slower than ArrayList, because it's insertion is a simple insertion into an array (assuming you insert in the end and there's still free space; I don't factor in resizing the internal array, because the same cost applies to HashSet as well).



回答6:

I don't think you can make this judgement simply on the cost of building the collection. Other things that you need to take into account are:

  • Is the input dataset ordered? Is there a requirement that the output data structure preserves insertion order?
  • Is there a requirement that the output data structure is ordered (or reordered) based on element values?
  • Will the output data structure be subsequently modified? How?
  • Is there a requirement that the output data structure is duplicate free if other elements are added subsequently?
  • Do you know how many elements are likely to be in the input dataset?
  • Can you measure the size of the input dataset? (Or is it provided via an iterator?)
  • Does space utilization matter?

These can all effect your choice of data structure.



回答7:

Java List:

If you don't have such requirement that you have to keep duplicate or not. Then you can use List instead of Set.

List is an interface in Collection framework. Which extends Collection interface. and ArrayList, LinkedList is the implementation of List interface.

When to use ArrayList or LinkedList

ArrayList: If you have such requirement that in your application mostly work is accessing the data. Then you should go for ArrayList. because ArrayList implements RtandomAccess interface which is Marker Interface. because of Marker interface ArrayList have capability to access the data in O(1) time. and you can use ArrayList over LinkedList where you want to get data according to insertion order.

LinkedList: If you have such requirement that your mostly work is insertion or deletion. Then you should use LinkedList over the ArrayList. because in LinkedList insertion and deletion happen in O(1) time whereas in ArrayList it's O(n) time.

Java Set:

If you have requirement in your application that you don't want any duplicates. Then you should go for Set instead of List. Because Set doesn't store any duplicates. Because Set works on the principle of Hashing. If we add object in Set then first it checks object's hashCode in the bucket if it's find any hashCode present in it's bucked then it'll not add that object.