目录
1. 常用的集合
List、Map、Set以及其子类
List、Set实现了collection接口,Map实现单独接口——AbstractMap
2. 概念差别:
List有序,有序指的是插入的顺序;其中可以存放重复的值以及null值。
Set无序,其中元素各不相同,其中只能存放一个null值。
Map存放键值对,键是唯一的,所以map中只能存放一个键为null的值。
3. 说一说hashMap的理解
他的key通过hashcode进行存储
内部数据结构有三种:数组、链表以及jdk8中为了提升查询速度所加入的红黑树结构
- 首先hashmap中维护了一个数组,数组中存储的元素类型为entry。
- 当每个entry要被添加到数组中时,首选需要用hash算法计算出hash code
- 然后对hash code进行取模操作,用以获取entry在数组中的位置
jdk8中,当一个数组的节点上所挂载的节点数量超过8时,或者数组空间大于64,会将链表转成红黑树,红黑树查找的复杂度是O(logn)
4. hashmap的实现方式
4.1 node节点
hashmap中维护了一个数组,数组中存储的元素类型为entry。entry是接口,node是他的实现类。
从下发源码可以看出,node重写了object的hashCode方法以及equals方法。
/**
* Basic hash bin node, used for most entries. (See below for
* TreeNode subclass, and in LinkedHashMap for its Entry subclass.)
*/
static class Node<K,V> implements Map.Entry<K,V> {
final int hash;
final K key;
V value;
Node<K,V> next;
Node(int hash, K key, V value, Node<K,V> next) {
this.hash = hash;
this.key = key;
this.value = value;
this.next = next;
}
public final K getKey() { return key; }
public final V getValue() { return value; }
public final String toString() { return key + "=" + value; }
public final int hashCode() {
return Objects.hashCode(key) ^ Objects.hashCode(value);
}
public final V setValue(V newValue) {
V oldValue = value;
value = newValue;
return oldValue;
}
public final boolean equals(Object o) {
if (o == this)
return true;
if (o instanceof Map.Entry) {
Map.Entry<?,?> e = (Map.Entry<?,?>)o;
if (Objects.equals(key, e.getKey()) &&
Objects.equals(value, e.getValue()))
return true;
}
return false;
}
}
4.2 成员属性
/* ---------------- Fields -------------- */
/**
* The table, initialized on first use, and resized as
* necessary. When allocated, length is always a power of two.
* (We also tolerate length zero in some operations to allow
* bootstrapping mechanics that are currently not needed.)
*/
transient Node<K,V>[] table;
/**
* Holds cached entrySet(). Note that AbstractMap fields are used
* for keySet() and values().
*/
transient Set<Map.Entry<K,V>> entrySet;
/**
* The number of key-value mappings contained in this map.
*/
transient int size;
/**
* The number of times this HashMap has been structurally modified
* Structural modifications are those that change the number of mappings in
* the HashMap or otherwise modify its internal structure (e.g.,
* rehash). This field is used to make iterators on Collection-views of
* the HashMap fail-fast. (See ConcurrentModificationException).
*/
transient int modCount;
/**
* The next size value at which to resize (capacity * load factor).
*
* @serial
*/
// (The javadoc description is true upon serialization.
// Additionally, if the table array has not been allocated, this
// field holds the initial array capacity, or zero signifying
// DEFAULT_INITIAL_CAPACITY.)
int threshold;
/**
* The load factor for the hash table.
* 负载因子,默认值是0.75
* @serial
*/
final float loadFactor;
4.3 transient 的作用
java中有一个Serializable接口,当一个类实现了该接口,该类就可以实现自动序列化。
所谓序列化,指的是java进程之间在进行对象传输时,或者对对象进行持久化操作时,需要将对象转成二进制流,便于传输或存储。
transient修饰了一个属性之后,该数据将不会被自动序列化,比如一些敏感字段。即:
对象中有两个属性:
private int a;
transient int b;
将对象进行序列化和反序列化后,b会消失。
5 hashMap扩容机制
/**
* The default initial capacity - MUST be a power of two.
*/
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16
/**
* The maximum capacity, used if a higher value is implicitly specified
* by either of the constructors with arguments.
* MUST be a power of two <= 1<<30.
*/
static final int MAXIMUM_CAPACITY = 1 << 30;
/**
* The load factor used when none specified in constructor.
*/
static final float DEFAULT_LOAD_FACTOR = 0.75f;
6. 线程安全情况
线程不安全。因为其方法都没有使用synchronized实现同步。