乐趣区

关于string:常见包装类ListSetHashMap见解

一. Integer 与 String

1.1 Integer

包装类,就是对根本数据类型的一个包装,赋予一些罕用的办法

比方类型装换等。

int 的包装类,应用 final 润饰类,不可继承。

会主动装箱与主动拆箱。

特地留神:在 -128 到 127 之间, 保护了一个数组(static 初始化,服务器启动就存在。)

比拟值时,如果是这个区间,则默认从数组中拿出值来进行判断。

Integer a = 1;
Integer b = 1;
Integer c = 128;
Integer d = 128;
sout(a == b); // true
sout(c == d); // false

源码局部

 private static class IntegerCache {
     static final int low = -128;
     static final int high;
     static final Integer cache[];
    ​
     static {
         // high value may be configured by property
         int h = 127;
         String integerCacheHighPropValue =
         sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
         if (integerCacheHighPropValue != null) {
            try {int i = parseInt(integerCacheHighPropValue);
                 i = Math.max(i, 127);
                 // Maximum array size is Integer.MAX_VALUE
                 h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
            } catch(NumberFormatException nfe) {// If the property cannot be parsed into an int, ignore it.}
         }
         high = h;
        ​
         cache = new Integer[(high - low) + 1];
         int j = low;
         for(int k = 0; k < cache.length; k++)
         cache[k] = new Integer(j++);
        ​
         // range [-128, 127] must be interned (JLS7 5.1.7)
         assert IntegerCache.high >= 127;
 }
​
 private IntegerCache() {}
 } 
​
 public static Integer valueOf(int i) {if (i >= IntegerCache.low && i <= IntegerCache.high)
     return IntegerCache.cache[i + (-IntegerCache.low)];
     return new Integer(i);
 }

1.2 String

不可变长字符串。

应用 String 字符串拼接时,默认调用 StringBulider 的 append 办法

String str1 = "hello,";
String str2 = "dbc";
String str3 = str1 + str2;
// 理论:String str3 = (new StringBuilder()).append(str1).append(str2).toString();

String,StringBuilder,StringBuffer 的区别

  1. String: 定长字符串
  2. StringBuilder: 可变长字符串、线性不平安、效率高
  3. StringBuffer:可变长字符串、线性平安、效率低

二. List

有序,可反复

2.1 ArrayList

底层保护了一个 数组

会依据存入数据个数和容量, 来 主动扩容

特点:查问快、增加和删除效率低(和 LinkedList 相比)。

源码

 transient Object[] elementData; // non-private to simplify nested class access
 private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
 private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
​
 // 带参的一个构造方法
 public ArrayList(int initialCapacity) {if (initialCapacity > 0) {this.elementData = new Object[initialCapacity];
     } else if (initialCapacity == 0) {this.elementData = EMPTY_ELEMENTDATA;} else {
        throw new IllegalArgumentException("Illegal Capacity:"+
     initialCapacity);
     }
 }
​
 // 增加的一个办法
 public boolean add(E e) {ensureCapacityInternal(size + 1);  // Increments modCount!!
    elementData[size++] = e;
    return true;
 }
​
 // 扩容相干
 private void ensureCapacityInternal(int minCapacity) {ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
 }
​
 private void ensureExplicitCapacity(int minCapacity) {
    modCount++;
​
    // overflow-conscious code
    if (minCapacity - elementData.length > 0)
        grow(minCapacity);
    }
 private void grow(int minCapacity) {
    // overflow-conscious code
    int oldCapacity = elementData.length;
    int newCapacity = oldCapacity + (oldCapacity >> 1); // 扩容 1.5 倍
    if (newCapacity - minCapacity < 0)
        newCapacity = minCapacity;
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        newCapacity = hugeCapacity(minCapacity);
     // minCapacity is usually close to size, so this is a win:
    elementData = Arrays.copyOf(elementData, newCapacity);
 }

2.2 LinkedList

底层保护了一个 链表

特点:查问慢、增加和删除快(和 ArrayList 相比)。

源码

 // 链表的节点
 private static class Node<E> {
     E item;
     Node<E> next;
     Node<E> prev;
    ​
     Node(Node<E> prev, E element, Node<E> next) {
         this.item = element;
         this.next = next;
         this.prev = prev;
     }
 }

三. Map

key-value 型存储格局

key 不可反复

3.1 HashMap

底层是一个 哈希表(数组 + 链表)

key 和 value 能够为 null

与 HashTable 的区别

  1. HashTable 是线性平安的,效率低,而 HashMap 线性不平安。
  2. HashTable 不允许值 (key 和 value) 为 null,HashMap 的值能够为 null

源码

 /**
 * 默认容量(数组长度)*/
 static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;
​
 /**
 * 最大容量
 */
 static final int MAXIMUM_CAPACITY = 1 << 30;
​
 /**
 *  Jdk1.8 后,数组中某个地位的链表长度为 8, 并且总元素个数 >=64, 则将该链表编程红黑树
 *  优化查问效率
 */
 static final int TREEIFY_THRESHOLD = 8;
​
 /**
 * 最小树化容量 
 * 数组中某个地位的链表长度为 8, 并且总元素个数 >=64, 则将该链表编程红黑树
 * 优化查问效率
 */
 static final int MIN_TREEIFY_CAPACITY = 64;
​
 /**
 *  当数据个数低于这个数, 将其转换为链表
 */
 static final int UNTREEIFY_THRESHOLD = 6;
​
 /**
 * 负载因子, 增加元素时,当哈希表中的元素个数为: 数组长度 * 负载因子时,会扩容
 */
 static final float DEFAULT_LOAD_FACTOR = 0.75f;
​
​
 /**
 * 根本的哈希 bin 节点
 */
 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;
     }
 }
​

四. Set

无序、不可反复

底层保护了一个Map

存值时,将增加的值存为 Map 的key, 而 value 就是一个 Object

故要获取值, 只能获取 迭代器 来遍历

4.1 HashSet

底层保护了一个HashMap

存值时,存的为 Map 的key

能够增加 null(HashMap 的 key 能够为 null)

HashSet 如何判断元素是否反复的?

  1. 先判断 hashCode
  2. 再应用 equals 判断

如果 hashCode 的返回值相等 并且 equals 返回 true,则被认为是雷同的元素

源码

 ...
 private transient HashMap<E,Object> map;
 // Dummy value to associate with an Object in the backing Map
 // 要与反对映射中的对象关联的伪值
 private static final Object PRESENT = new Object();
 ...
 
 // 构造方法 
 public HashSet() {map = new HashMap<>();
 }
 ...
 
 // 增加办法 
 public boolean add(E e) {return map.put(e, PRESENT)==null;
 }
​

4.2 LinkedHashSet

HashSet 的子类

双向链表

4.3 TreeSet

底层保护了一个TreeMap

存值时,存的为 Map 的key

不能增加 null

源码

 private transient NavigableMap<E,Object> m;
​
 TreeSet(NavigableMap<E,Object> m) {this.m = m;}
​
 // 构造方法
 public TreeSet() {this(new TreeMap<E,Object>());
 }
​
 // 增加办法
 public boolean add(E e) {return m.put(e, PRESENT)==null;
 }
退出移动版