1、运算符
1.1、 a ^ b 异或
二进制比较:相同为0,不同为1
题:a=9,b=21,a^b=?解:9对应二进制为100121对应二进制为10101故 a ^ b ==> 11100(2进制) ==> 28(10进制)
1.2、 a & b 与
二进制比较:都为1则为1
题:a=9,b=21,a&b=?解:9对应二进制为100121对应二进制为10101故 a & b ==> 1(2进制) ==> 1(10进制)
1.3、 a | b 或
二进制比较:有1则为1
题:a=9,b=21,a|b=?解:9对应二进制为100121对应二进制为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 160import java.util.*;public class Text {public enum Style { BOLD, ITALIC, UNDERLINE, STRIKETHROUGH }// Any Set could be passed in, but EnumSet is clearly bestpublic void applyStyles(Set<Style> set) {set.forEach(System.out::println);}// Sample usepublic 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 16static 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];// 初始化tableinitHashSeedAsNeeded(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);}
用户未定义容量就是16