1、运算符

1.1、 a ^ b 异或

二进制比较:相同为0,不同为1

  1. 题:
  2. a=9,b=21,a^b=?
  3. 解:
  4. 9对应二进制为1001
  5. 21对应二进制为10101
  6. a ^ b ==> 11100(2进制) ==> 28(10进制)

Learning in java - 图1

1.2、 a & b

二进制比较:都为1则为1

  1. 题:
  2. a=9,b=21,a&b=?
  3. 解:
  4. 9对应二进制为1001
  5. 21对应二进制为10101
  6. a & b ==> 1(2进制) ==> 1(10进制)

Learning in java - 图2

1.3、 a | b

二进制比较:有1则为1

  1. 题:
  2. a=9,b=21,a|b=?
  3. 解:
  4. 9对应二进制为1001
  5. 21对应二进制为10101
  6. a | b ==> 11101(2进制) ==> 29(10进制)

Learning in java - 图3


2、集合

Java集合框架主要由Collection和Map两个根接口及其子接口、实现类组成。

2.1、Collection

image.png

2.1.1、set

元素不可以重复

2.1.1.1、TreeSet

1:插入和遍历顺序不一致 2:需要排序

底层:红黑树(自平衡二叉树)

2.1.1.2、HashSet

1:插入遍历顺序不一致 2:可以为null

底层:基于HashMap实现

2.1.1.3、LinkedHashSet

1:插入和遍历顺序一致,采用链表维护内部顺序

继承于HashSet,内部通过LinkedHashMap实现

2.1.1.4、EnumSet

  1. // EnumSet - a modern replacement for bit fields - Page 160
  2. import java.util.*;
  3. public class Text {
  4. public enum Style { BOLD, ITALIC, UNDERLINE, STRIKETHROUGH }
  5. // Any Set could be passed in, but EnumSet is clearly best
  6. public void applyStyles(Set<Style> set) {
  7. set.forEach(System.out::println);
  8. }
  9. // Sample use
  10. public static void main(String[] args) {
  11. Text text = new Text();
  12. text.applyStyles(EnumSet.of(Style.BOLD, Style.ITALIC));
  13. }
  14. }

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

线程不安全 查询访问速度快,增删效率低

底层实现:Object数组

2.1.3.3、Vector

线程安全

底层实现:Object数组

2.1.3.4、Stack


2.2、Map

image.png

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键值对。

  1. static final Entry<?,?>[] EMPTY_TABLE = {};
  2. transient Entry<K,V>[] table = (Entry<K,V>[]) EMPTY_TABLE;

Entry是HashMap中的一个静态内部类。

  1. static class Entry<K,V> implements Map.Entry<K,V> {
  2. final K key;
  3. V value;
  4. Entry<K,V> next;
  5. int hash;
  6. Entry(int h, K k, V v, Entry<K,V> n) {
  7. value = v;
  8. next = n;
  9. key = k;
  10. hash = h;
  11. }
  12. public final K getKey() {return key;}
  13. public final V getValue() {return value;}
  14. public final V setValue(V newValue) {
  15. V oldValue = value;
  16. value = newValue;
  17. return oldValue;
  18. }
  19. public final boolean equals(Object o) {
  20. if (!(o instanceof Map.Entry))
  21. return false;
  22. Map.Entry e = (Map.Entry)o;
  23. Object k1 = getKey();
  24. Object k2 = e.getKey();
  25. if (k1 == k2 || (k1 != null && k1.equals(k2))) {
  26. Object v1 = getValue();
  27. Object v2 = e.getValue();
  28. if (v1 == v2 || (v1 != null && v1.equals(v2)))
  29. return true;
  30. }
  31. return false;
  32. }
  33. public final int hashCode() {
  34. return Objects.hashCode(getKey()) ^ Objects.hashCode(getValue());
  35. }
  36. public final String toString() {
  37. return getKey() + "=" + getValue();
  38. }
  39. void recordAccess(HashMap<K,V> m) {}
  40. void recordRemoval(HashMap<K,V> m) {}
  41. }

原始属性。

  1. //初始化容量,MUST be a power of two.
  2. static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16
  3. static final int MAXIMUM_CAPACITY = 1 << 30;// 最大容量,2的30次方
  4. static final float DEFAULT_LOAD_FACTOR = 0.75f;// 加载因子
  5. int threshold;// 扩容阀值
  6. transient int hashSeed = 0;
  7. transient int modCount;

构造函数。

  1. public HashMap(int initialCapacity, float loadFactor) {
  2. // 校验初始容量值是否合法
  3. if (initialCapacity < 0) throw new IllegalArgumentException("Illegal initial capacity: " + initialCapacity);
  4. if (initialCapacity > MAXIMUM_CAPACITY) initialCapacity = MAXIMUM_CAPACITY;
  5. // 校验加载因子值是否合法
  6. if (loadFactor <= 0 || Float.isNaN(loadFactor)) throw new IllegalArgumentException("Illegal load factor: " + loadFactor);
  7. this.loadFactor = loadFactor;
  8. // 【临时赋值】扩容阀值等于初始容量,在真正构建数组的时候,其值为 容量*负载因子
  9. threshold = initialCapacity;
  10. init();// init方法在HashMap中没有实际实现,不过在其子类如 linkedHashMap中就会有对应实现
  11. }

在进行put操作的时候才真正构建table数组。

  1. public V put(K key, V value) {
  2. if (table == EMPTY_TABLE) {
  3. // 初始化数组
  4. inflateTable(threshold);
  5. }
  6. if (key == null) return putForNullKey(value);
  7. // 根据key计算哈希值
  8. int hash = hash(key);
  9. // 计算数组下标 h & (length-1)
  10. int i = indexFor(hash, table.length);
  11. for (Entry<K,V> e = table[i]; e != null; e = e.next) {
  12. Object k;
  13. // 哈希值相同再比较key是否相同,相同的话值替换,否则将这个槽转成链表
  14. if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
  15. V oldValue = e.value;
  16. e.value = value;
  17. e.recordAccess(this);
  18. return oldValue;
  19. }
  20. }
  21. modCount++;  // fast-fail,迭代时响应快速失败,还未添加元素就进行modCount++,将为后续留下很多隐患
  22. addEntry(hash, key, value, i);  // 添加元素,注意最后一个参数i是table数组的下标
  23. return null;
  24. }

inflateTable(threshold),此时threshold值为构造函数的临时赋值

用户定义容量就是用户传的入参image.png 用户未定义容量就是16

  1. private void inflateTable(int toSize) {
  2. int capacity = roundUpToPowerOf2(toSize); // 计算出大于等于toSize的最小2的次方数
  3. // 计算出阈值
  4. threshold = (int) Math.min(capacity * loadFactor, MAXIMUM_CAPACITY + 1);
  5. table = new Entry[capacity];// 初始化table
  6. initHashSeedAsNeeded(capacity);// 选择合适的Hash因子
  7. }
  8. private static int roundUpToPowerOf2(int number) {
  9. return number >= MAXIMUM_CAPACITY ?
  10. MAXIMUM_CAPACITY : (number > 1) ? Integer.highestOneBit((number - 1) << 1) : 1;
  11. }
  12. // 计算出小于等于i的最大2的次方数
  13. public static long highestOneBit(long i) {
  14. i |= (i >> 1);
  15. i |= (i >> 2);
  16. i |= (i >> 4);
  17. i |= (i >> 8);
  18. i |= (i >> 16);
  19. i |= (i >> 32);
  20. return i - (i >>> 1);
  21. }

hash。

  1. final int hash(Object k) {
  2. int h = hashSeed;
  3. //这里针对String优化了Hash函数,是否使用新的Hash函数和Hash因子有关
  4. if (0 != h && k instanceof String) {
  5. return sun.misc.Hashing.stringHash32((String) k);
  6. }
  7. h ^= k.hashCode();
  8. h ^= (h >>> 20) ^ (h >>> 12);
  9. return h ^ (h >>> 7) ^ (h >>> 4);
  10. }

2.2.3.1.1、加载因子

2.2.3.2、1.8

2.2.3.1、LinkedHashMap

2.2.4、HashTable

2.2.4.1、Properties

2.2.5、Treemap