1、运算符
1.1、 a ^ b
异或
二进制比较:相同为0,不同为1
题:
a=9,b=21,a^b=?
解:
9对应二进制为1001
21对应二进制为10101
故 a ^ b ==> 11100(2进制) ==> 28(10进制)
1.2、 a & b
与
二进制比较:都为1则为1
题:
a=9,b=21,a&b=?
解:
9对应二进制为1001
21对应二进制为10101
故 a & b ==> 1(2进制) ==> 1(10进制)
1.3、 a | b
或
二进制比较:有1则为1
题:
a=9,b=21,a|b=?
解:
9对应二进制为1001
21对应二进制为10101
故 a | b ==> 11101(2进制) ==> 29(10进制)
2、集合
Java集合框架主要由Collection和Map两个根接口及其子接口、实现类组成。
2.1、Collection
2.1.1、set
元素不可以重复
2.1.1.1、TreeSet
1:插入和遍历顺序不一致 2:需要排序
2.1.1.2、HashSet
1:插入遍历顺序不一致 2:可以为null
2.1.1.3、LinkedHashSet
1:插入和遍历顺序一致,采用链表维护内部顺序
继承于HashSet,内部通过LinkedHashMap实现
2.1.1.4、EnumSet
// EnumSet - a modern replacement for bit fields - Page 160
import java.util.*;
public class Text {
public enum Style { BOLD, ITALIC, UNDERLINE, STRIKETHROUGH }
// Any Set could be passed in, but EnumSet is clearly best
public void applyStyles(Set<Style> set) {
set.forEach(System.out::println);
}
// Sample use
public static void main(String[] args) {
Text text = new Text();
text.applyStyles(EnumSet.of(Style.BOLD, Style.ITALIC));
}
}
2.1.2、Queue
2.1.2.1、ArrayDeque
2.1.2.2、PriorityQueue
2.1.3、list
元素可以重复
2.1.3.1、LinkedList
线程不安全 适合频繁插入删除的操作
2.1.3.2、ArrayList
线程不安全 查询访问速度快,增删效率低
2.1.3.3、Vector
线程安全
2.1.3.4、Stack
2.2、Map
2.2.1、EnumMap
2.2.2、IdentityHashMap
2.2.3、HashMap
2.2.3.1、1.7
HashMap的主干是一个Entry数组,Entry是HashMap的基本组成单元,每一个Entry包含一个key-value键值对。
static final Entry<?,?>[] EMPTY_TABLE = {};
transient Entry<K,V>[] table = (Entry<K,V>[]) EMPTY_TABLE;
Entry是HashMap中的一个静态内部类。
static class Entry<K,V> implements Map.Entry<K,V> {
final K key;
V value;
Entry<K,V> next;
int hash;
Entry(int h, K k, V v, Entry<K,V> n) {
value = v;
next = n;
key = k;
hash = h;
}
public final K getKey() {return key;}
public final V getValue() {return value;}
public final V setValue(V newValue) {
V oldValue = value;
value = newValue;
return oldValue;
}
public final boolean equals(Object o) {
if (!(o instanceof Map.Entry))
return false;
Map.Entry e = (Map.Entry)o;
Object k1 = getKey();
Object k2 = e.getKey();
if (k1 == k2 || (k1 != null && k1.equals(k2))) {
Object v1 = getValue();
Object v2 = e.getValue();
if (v1 == v2 || (v1 != null && v1.equals(v2)))
return true;
}
return false;
}
public final int hashCode() {
return Objects.hashCode(getKey()) ^ Objects.hashCode(getValue());
}
public final String toString() {
return getKey() + "=" + getValue();
}
void recordAccess(HashMap<K,V> m) {}
void recordRemoval(HashMap<K,V> m) {}
}
原始属性。
//初始化容量,MUST be a power of two.
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16
static final int MAXIMUM_CAPACITY = 1 << 30;// 最大容量,2的30次方
static final float DEFAULT_LOAD_FACTOR = 0.75f;// 加载因子
int threshold;// 扩容阀值
transient int hashSeed = 0;
transient int modCount;
构造函数。
public HashMap(int initialCapacity, float loadFactor) {
// 校验初始容量值是否合法
if (initialCapacity < 0) throw new IllegalArgumentException("Illegal initial capacity: " + initialCapacity);
if (initialCapacity > MAXIMUM_CAPACITY) initialCapacity = MAXIMUM_CAPACITY;
// 校验加载因子值是否合法
if (loadFactor <= 0 || Float.isNaN(loadFactor)) throw new IllegalArgumentException("Illegal load factor: " + loadFactor);
this.loadFactor = loadFactor;
// 【临时赋值】扩容阀值等于初始容量,在真正构建数组的时候,其值为 容量*负载因子
threshold = initialCapacity;
init();// init方法在HashMap中没有实际实现,不过在其子类如 linkedHashMap中就会有对应实现
}
在进行put操作的时候才真正构建table数组。
public V put(K key, V value) {
if (table == EMPTY_TABLE) {
// 初始化数组
inflateTable(threshold);
}
if (key == null) return putForNullKey(value);
// 根据key计算哈希值
int hash = hash(key);
// 计算数组下标 h & (length-1)
int i = indexFor(hash, table.length);
for (Entry<K,V> e = table[i]; e != null; e = e.next) {
Object k;
// 哈希值相同再比较key是否相同,相同的话值替换,否则将这个槽转成链表
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
}
modCount++; // fast-fail,迭代时响应快速失败,还未添加元素就进行modCount++,将为后续留下很多隐患
addEntry(hash, key, value, i); // 添加元素,注意最后一个参数i是table数组的下标
return null;
}
inflateTable(threshold),此时threshold值为构造函数的临时赋值
用户定义容量就是用户传的入参 用户未定义容量就是16
private void inflateTable(int toSize) {
int capacity = roundUpToPowerOf2(toSize); // 计算出大于等于toSize的最小2的次方数
// 计算出阈值
threshold = (int) Math.min(capacity * loadFactor, MAXIMUM_CAPACITY + 1);
table = new Entry[capacity];// 初始化table
initHashSeedAsNeeded(capacity);// 选择合适的Hash因子
}
private static int roundUpToPowerOf2(int number) {
return number >= MAXIMUM_CAPACITY ?
MAXIMUM_CAPACITY : (number > 1) ? Integer.highestOneBit((number - 1) << 1) : 1;
}
// 计算出小于等于i的最大2的次方数
public static long highestOneBit(long i) {
i |= (i >> 1);
i |= (i >> 2);
i |= (i >> 4);
i |= (i >> 8);
i |= (i >> 16);
i |= (i >> 32);
return i - (i >>> 1);
}
hash。
final int hash(Object k) {
int h = hashSeed;
//这里针对String优化了Hash函数,是否使用新的Hash函数和Hash因子有关
if (0 != h && k instanceof String) {
return sun.misc.Hashing.stringHash32((String) k);
}
h ^= k.hashCode();
h ^= (h >>> 20) ^ (h >>> 12);
return h ^ (h >>> 7) ^ (h >>> 4);
}