1. [Mandatory] The usage of hashCode and equals should follow:
1) Override hashCode if equals is overridden.
2) These two methods must be overridden for elements of a Set
since they are used to ensure that no duplicate object will be inserted in Set
.
3) These two methods must be overridden for any object that is used as the key of Map
.
Note:
String
can be used as the key ofMap
sinceString
defines these two methods.
2. [Mandatory] Do not add elements to collection objects returned by keySet()
/values()
/entrySet()
, otherwise UnsupportedOperationException
will be thrown.
3. [Mandatory] Do not add nor remove to/from immutable objects returned by methods in Collections
, e.g. emptyList()
/singletonList()
.
Counter example: Adding elements to
Collections.emptyList()
will throwUnsupportedOperationException
.
4. [Mandatory] Do not cast subList in class ArrayList
, otherwise ClassCastException
will be thrown: java.util.RandomAccessSubList
cannot be cast to java.util.ArrayList
.
Note:
subList
ofArrayList
is an inner class, which is a view ofArrayList
. All operations on theSublist
will affect the original list.
5. [Mandatory] When using subList, be careful when modifying the size of original list. It might cause ConcurrentModificationException
when performing traversing, adding or deleting on the subList.
6. [Mandatory] Use toArray(T[] array)
to convert a list to an array. The input array type should be the same as the list whose size is list.size()
.
Counter example: Do not use
toArray
method without arguments. Since the return type isObject[]
,ClassCastException
will be thrown when casting it to a different array type.Positive example:
List<String> list = new ArrayList<String>(2);
list.add("guan");
list.add("bao");
String[] array = new String[list.size()];
array = list.toArray(array);
Note: When using
toArray
method with arguments, pass an input with the same size as the list. If input array size is not large enough, the method will re-assign the size internally, and then return the address of new array. If the size is larger than needed, extra elements (index[list.size()]
and later) will be set to null.
7. [Mandatory] Do not use methods which will modify the list after using Arrays.asList
to convert array to list, otherwise methods like add/remove/clear will throw UnsupportedOperationException
.
Note: The result of
asList
is the inner class ofArrays
, which does not implement methods to modify itself.Arrays.asList
is only a transferred interface, data inside which is stored as an array.
String[] str = new String[] { "a", "b" };
List<String> list = Arrays.asList(str);
Case 1:
list.add("c");
will throw a runtime exception.
Case 2:str[0]= "gujin";
list.get(0)
will be modified.
8. [Mandatory] Method add
cannot be used for generic wildcard with <? Extends T>
, method get
cannot be used with <? super T>
, which probably goes wrong.
Note: About PECS (Producer Extends Consumer Super) principle:
1)Extends
is suitable for frequently reading scenarios.
2)Super
is suitable for frequently inserting scenarios.
9. [Mandatory] Do not remove or add elements to a collection in a foreach loop. Please use Iterator
to remove an item. Iterator
object should be synchronized when executing concurrent operations.
Counter example:
List<String> a = new ArrayList<String>();
a.add("1");
a.add("2");
for (String temp : a) {
if ("1".equals(temp)){
a.remove(temp);
}
}
Note: If you try to replace “1” with “2”, you will get an unexpected result.
Positive example:
Iterator<String> it = a.iterator();
while (it.hasNext()) {
String temp = it.next();
if (delete condition) {
it.remove();
}
}
10. [Mandatory] In JDK 7 and above version, Comparator
should meet the three requirements listed below, otherwise Arrays.sort
and Collections.sort
will throw IllegalArgumentException
.
Note:
1) Comparing x,y and y,x should return the opposite result.
2) If x>y and y>z, then x>z.
3) If x=y, then comparing x with z and comparing y with z should return the same result.Counter example: The program below cannot handle the case if o1 equals to o2, which might cause an exception in a real case:
new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
return o1.getId() > o2.getId() ? 1 : -1;
}
}
11. [Recommended] Set a size when initializing a collection if possible.
Note: Better to use
ArrayList(int initialCapacity)
to initializeArrayList
.
12. [Recommended] Use entrySet
instead of keySet
to traverse KV maps.
Note: Actually,
keySet
iterates through the map twice, firstly convert toIterator
object, then get the value from theHashMap
by key.EntrySet
iterates only once and puts keys and values in the entry which is more efficient. UseMap.foreach
method in JDK8.Positive example:
values()
returns a list including all values,keySet()
returns a set including all values,entrySet()
returns a k-v combined object.
13. [Recommended] Carefully check whether a k/v collection can store null value, refer to the table below:
Collection | Key | Value | Super | Note |
---|---|---|---|---|
Hashtable | Null is not allowed | Null is not allowed | Dictionary | Thread-safe |
ConcurrentHashMap | Null is not allowed | Null is not allowed | AbstractMap | Segment lock |
TreeMap | Null is not allowed | Null is allowed | AbstractMap | Thread-unsafe |
HashMap | Null is allowed | Null is allowed | AbstractMap | Thread-unsafe |
Counter example: Confused by
HashMap
, lots of people think null is allowed inConcurrentHashMap
. Actually,NullPointerException
will be thrown when putting in null value.
14. [For Reference] Properly use sort and order of a collection to avoid negative influence of unsorted and unordered one.
Note: Sorted means that its iteration follows specific sorting rule. Ordered means the order of elements in each traverse is stable. e.g.
ArrayList
is ordered and unsorted,HashMap
is unordered and unsorted,TreeSet
is ordered and sorted.
15. [For Reference] Deduplication operations could be performed quickly since set stores unique values only. Avoid using method contains of List
to perform traverse, comparison and de-duplication.