Fail-fast and fail-safe iterators
Most collection implementation doesn't support modification during looping across iterator. It doesn't matter if modification come from same thread or another.
In some cases implementation can detect such situation and throw
java.util.ConcurrentModificationException
. This is called fail-fast iterator behavior.
From documentation:
Note that fail-fast behavior cannot be guaranteed as it is, generally speaking, impossible to make any hard guarantees in the presence of asynchronous concurrent modification. Fail-fast operations throw ConcurrentModificationException on a best-effort basis. Therefore, it would be wrong to write a program that depended on this exception for its correctness: ConcurrentModificationException should be used only to detect bugs.
Fail-safe iterators are those that allow modification of collection during looping across iterator.
Usually this is done operating on collection copy by iterator. Examples of such collections is
java.util.concurrent.ConcurrentHashMap
and java.util.concurrent.CopyOnWriteArrayList
.
ArrayList vs LinkedList vs Vector
It is typical question on difference between ArrayList
, LinkedList
, and Vector
which
implement List
interface.
ArrayList
and Vector
uses arrays in implementation and Vector
methods are synchronized.
So in single threaded environment there is no need for Vector
and ArrayList
is preferred.
LinkedList
has double linked list underneath hence insertion of element in a middle of the list
is cheap operation. For ArrayList
and Vector
such operation may require coping of many
elements. However these classes allow indexed access to elements in constant time, while for
LinkedList
this means a scan through list up to required index.
char[] or String for password
Best security practice means to remove password from memory as fast as possible whenever password no longer needed.
With String
data type it is not possible in any predicable time and portable way because
String
is immutable type and hide its content from modification for erasing purpose. Garbage
collection doesn't erase memory, it only will happen in uncertain time in a future if this area
will be used by other class instance.
On other hand char[]
data type can be erased easily by:
Arrays.fill(password, '\0');
Why calling abstract methods is dangerous in constructor
Subclass constructor calls superclass constructor before any other instructions. Abstract methods may depends of fields that is not fully populated by subclass constructor.
In following example cache
always initialized by 0
during Sub(int value)
constructor
call:
public abstract Super { private int cache; public Super() { cache = calculate(); } protected abstract int calculate(); } public Sub extends Super { private int value; public Sub(int value) { this.value = value; } @Override protected int calculate() { return value; } }
HashSet vs TreeSet
HashSet
have O(1)
for add
, remove
, contains
versus O(log(N))
for
TreeSet
.
But TreeSet
has many efficient (O(log(N))
) additional methods for queried ranges of elements
based on elements order (defined by NavigableSet
and SortedSet
interfaces).
Why should you override hashCode() when you override equals()?
hashCode()
has contract that if:
ob1.equals(ob2) == true
then:
ob1.hashCode() == ob2.hashCode()
Changing default behavior of equals()
you may violate this contract.