Reputation: 2493
Ive got one question. What happens when I try to add the "same" object twice to an ArrayList. With "the same" I mean an object of an individual class, which is identified as the same with equals() and hashCode(). It has different values for most of the member variables and was created from maybe different threads, but for equals() and hashCode() its the "same". Does the second object then replace the first object?
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?
Thank you! :-)
[EDIT] Thanks for all the answers! Should I use synchronizedList then rather then using "synchronize(list){}"? --> I read the docs, even with synchronizedList, for iterating synchronize(list) shall be used
[EDIT2] Can a synchronizedList be declared as a member variable? I tried, but it didnt work.
Upvotes: 12
Views: 41470
Reputation: 44250
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.
Upvotes: 7
Reputation: 7070
If you try to add the same object twice, it will work, or if you try to add 2 objects with everything the same, it will still work. It is not best practice to do that because its harder to maintain the list.
overall: you shouldn't do it
Upvotes: 1
Reputation: 19877
An ArrayList
can contain multiple references to the same exact object (identity equivalence). It doesn't check equals()
or hashCode()
when adding objects.
You will just end up with two references in your ArrayList.
ArrayList
is NOT thread-safe...so the behaviour if you try to have two threads add at the same time is undefined. Maybe try using a SynchronizedList
if you want to do something like that.
Upvotes: 2
Reputation: 240928
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
Upvotes: 4
Reputation: 1502076
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
.
Upvotes: 16