ArrayList - add "same" objects (same => equals, hashCode), Threads
No, ArrayList
doesn't attempt to detect duplicates at all - you can have an ArrayList
with the exact same reference appearing multiple times. If you want a collection to avoid duplicates, you need a Set
implementation - and if you also want to preserve insertion order, you probably want LinkedHashSet
.
Note, however, that without locking ArrayList
should not be mutated from multiple threads in the first place - it's simply not meant to be a thread-safe collection in that way. Several threads can read from an ArrayList
without synchronization, but not mutate it. From the docs:
Note that this implementation is not synchronized. If multiple threads access an ArrayList instance concurrently, and at least one of the threads modifies the list structurally, it must be synchronized externally. (A structural modification is any operation that adds or deletes one or more elements, or explicitly resizes the backing array; merely setting the value of an element is not a structural modification.) This is typically accomplished by synchronizing on some object that naturally encapsulates the list. If no such object exists, the list should be "wrapped" using the Collections.synchronizedList method. This is best done at creation time, to prevent accidental unsynchronized access to the list
If you want to mutate a collection from multiple threads without locking, I suggest you look at the collections in java.util.concurrent
.
Does the second object then replace the first object?
No, most developers do explicit checks
if(!list.contains(foo)){ list.add(foo);}
Also, what happens if two threads try to add those objects exactly at the same time to the ArrayList? Is this even possible? If yes, what happens?
Yes, this is possible. If multiple threads write to/read from the same ArrayList
, then use the synchronized
keyword whenever you access this list
public List<Foo> getFoos(){ synchronized(list){ return list; }}public void addFoo(Foo foo){ synchronized(list){ list.add(foo); }}
EDIT
As someone pointed out, I suppose checking whether or not the ArrayList
contains the object to be added is quite expensive. If you want to ensure that the object is only added once, I'd follow the recommendation made below of using a LinkedHashSet. According to the API, when attempting to add to this data structure it
Adds the specified element to this set if it is not already present. More formally, adds the specified element e to this set if this set contains no element e2 such that (e==null ? e2==null : e.equals(e2)). If this set already contains the element, the call leaves the set unchanged and returns false.
It will allow to add simply. List has nothing to do with hashCode()
, equals()
while insertion it doesn't care for duplicate.
ArrayList
isn't thread safe so you might not get desired result. you can have synchronizedList
from Collections
class