Map Map
Map also called mapping table or dictionary, stored Map element is a key-value pair key-value
, they are packaged together in the Entry<K,V>
object. We can directly obtain key value, the same as the dictionary.
JDK in, Map implemented in two ways, first hashing technique, the second is a red-black tree.
Common Map implementation
HashMap achieved through hashing techniques. Key target in the Map must be defined equals
and hashCode
methods. High access efficiency of the container, almost equivalent to the array. Under normal circumstances, there are no special requirements, this should be the default option.
LinkedHashMap is HashMap
subclass, slightly worse performance HashMap
. Compared HashMap
, the vessel can be inserted through the elements in a sequence. The principle is to use the list to each Node string together, and therefore its iterative efficient than HashMap
more efficient. His key requirements with HashMap
the same.
TreeMap by red-black tree structure to achieve, so that the elements are ordered. Key elements of the object must implement the Comparable
interface so that red-black trees to sort elements. Because TreeMap
is ordered, also more than the number associated with ordering methods, such as firstKey
, lastKey
, subMap(fromKey,toKey)
, headMap(toKey)
and so on. His query efficiency is much lower than the hash for the \ (log (the n-) \) .
ConcurrentHashMap is a thread-safe the HashMap, mainly through the synchronized
sync blocks and CAS
the way to achieve, does not involve the synchronization lock
WeakHashMap , if a key is not referenced, then the key can be recovered GC. For special purposes.
IdentityHashMap , when making comparative key, use ==
instead equals
. For special purposes.
Summary about the efficiency of the hash is higher than red-black tree, but the elements are ordered red-black tree. Map of using a hash key must cover equals
and hashCode
, using a red-black tree Map must implement Comparable
the interface
Hash and hashCode
As mentioned above, one of Map's implementation is to use hashing techniques HashMap
, LinkedHashMap
hashing techniques are used.
Access time of the array index $O(1)$
, because the memory array is continuous and fixed type. Thus, as long as the first address, and acquires an array of offset (index), the address can be directly calculated element.
Hash is the use of an array of this feature, shown in Figure 1, he will array as the underlying storage element. Given function by using $f(n)$
the calculated hashcode of the key, again hashcode after secondary treatment, typically the array length modulo the array index can be obtained.
In addition, different key can be calculated the same hashCode, but best able to do the hash function hash value uniformly distributed in the array. The worst case is that all the hash values are the same, it will seriously drag down the access speed of the Map.
In summary, we can describe the process of access to the HashMap.
In calling put(key,value)
upon, key-value will first be packaged in Node<K,V>
the. Call key for hash(key)
calculating the hash value, then the hash value modulo the length of the array, the array is considered an index position, is called a slot (slot). Slot actual data bit is not installed, but the sentinel node head
. HashCode the same after each Node are inserted into the head
linked list. Meanwhile, in order to optimize the query speed, when too many nodes list when the list will be converted into red-black tree.
Note that when the number of elements than \ (arr-length * load- factor \) when triggered the Map resize
. At this time, the array expansion doubled, all the elements rehashed. Therefore, this is also part of the performance HashMap most damage. In order to reduce this from happening, it is best initially to have a rough estimate of the capacity requirements of Map.
That inquiry get(key)
process and put
is similar. First, to get through the slot hashCode bit elements, or red-black tree and traversing the list, by the equals
method of comparison by one. This is also why the hash must be covered hashCode
and equals
reason. hashCode
And equals
must uniquely identify an element.
hashCode wording
As mentioned above, a key step is to calculate the hash key's hashCode, so the design of good hash method is also very necessary.
- hashCode consistent results, that the results whenever calculated are the same. This requires calculating a value dependent hashCode immutable
- hashCode should not rely on unique object information, if hashCode dependent information for each object is only this one, we will never be able to create an identical key on the outside to get the value of the
- hashCode must generate a hash code based on the contents of the object
- hashCode generated hash code is preferably distributed uniformly
Some principles above hashCode design, gives Josh Bloch rewrite hashCode advice given
Domain Type | Compute |
---|---|
boolean | c = (f? 0 : 1) |
byte/char/short/int | c = (int)f |
long | c = (int)(f ^ f>>>32) |
float | c = Float.floatToIntBits(f) |
double | long l = Double.doubleToLongBits(f); c = (int)(l ^ l>>>32) |
Object | c = f.hashCode() |
Array | Each element using the above rules |
These are the basic types and object conversion method of hashCode hashCode when we calculate a target because of the time each of his field (not changing) into account. The result is initialized to 17, result multiplied by the hash value together with the current domain and then gives the result 37, namely:
result = 37 * result +c
For example, we custom object CountingString
as a key, hashCode will be defined as follows
public class CountedString {
private static List<String> created = new ArrayList<>();
private String s;
private int id = 0;
public CountedString(String s) {
this.s = s;
created.add(s);
for (String ss : created) {
if (ss.equals(s))//如果s,则他们的id编号必不相同
id++;
}
}
@Override
public String toString() {
return "[s:"+s+"],[id:"+id+"],[hashCode:"+hashCode()+"]";
}
@Override
public int hashCode() {
int result = 17;
result = result * 37 + s.hashCode();
result = result * 37 + id;
return result;
}
@Override
public boolean equals(Object obj) {
return obj instanceof CountedString &&
(s.equals(((CountedString) obj).s)) &&
(id == ((CountedString) obj).id);
}
}
With frame
Finally, to achieve good hashCode and equals are very tricky, we can make use of Apache Commons3
other similar framework, they have built a good tool.
reference
- Effective Java 3
- Java programming ideas