java基礎知識 一

一.String 

1.1string源碼中,幾個變量 :

  String類有final修飾,所以String類不能被繼承

@Stable
private final byte[] value;  final 是不可變的;因爲private是私有的,並且沒有提供修改value數組的方法,所以一旦確定值是不可變的;

構造函數:

public String() {
    this.value = "".value;
    this.coder = "".coder;
}
public String(String original) {
    this.value = original.value;
    this.coder = original.coder;
    this.hash = original.hash;
}

1.2 方法:

1.2.1 equals 方法

public boolean equals(Object anObject) {
    if (this == anObject) {
        return true;
    }
    if (anObject instanceof String) {
        String aString = (String)anObject;
        if (coder() == aString.coder()) {
            return isLatin1() ? StringLatin1.equals(value, aString.value)
                              : StringUTF16.equals(value, aString.value);
        }
    }
    return false;
}
latin1碼下的比較
public static boolean equals(byte[] value, byte[] other) {
    if (value.length == other.length) {
        for (int i = 0; i < value.length; i++) {
            if (value[i] != other[i]) {
                return false;
            }
        }

2.StringBuffer 繼承自abstractStringBuffer

變量:

byte[] value;

不是final的可以改變,並且權限是默認的;

繼承自abstractStringBuilder

append方法:

擴容的新容量爲當前value的容量2倍加2,如果擴容後的容量還是比需要的最小容量小,則直接擴容爲需要的最小容量,再將當前value內容複製給一個新的長度爲newCapacity的字符數組,再將value指向這個擴容後的新數組。即擴容是通過開闢新數組完成的,返回的也是新創建的新數組。

先擴容,將原先的數組複製到新數組中;

 */
public AbstractStringBuilder append(String str) {
    if (str == null) {
        return appendNull();
    }
    int len = str.length();
    ensureCapacityInternal(count + len);
    putStringAt(count, str);
    count += len;
    return this;
}
 */
private void ensureCapacityInternal(int minimumCapacity) {
    // overflow-conscious code
    int oldCapacity = value.length >> coder;
    if (minimumCapacity - oldCapacity > 0) {
        value = Arrays.copyOf(value,
                newCapacity(minimumCapacity) << coder);
    }
}
private int newCapacity(int minCapacity) {
    // overflow-conscious code
    int oldCapacity = value.length >> coder;
    int newCapacity = (oldCapacity << 1) + 2;
    if (newCapacity - minCapacity < 0) {
        newCapacity = minCapacity;
    }
    int SAFE_BOUND = MAX_ARRAY_SIZE >> coder;
    return (newCapacity <= 0 || SAFE_BOUND - newCapacity < 0)
        ? hugeCapacity(minCapacity)
        : newCapacity;
}

3.String與StringBuffer與StringBuilder三者介紹和三者的區別:

string 是不可變的,每次對string的操作其實是生成一個新的string對象;

tringBuffer與StringBuilder,是對自己本身操作的,並不產生新對象;

因爲在源碼中,string的值存放在value的char[] 數組中,這個value變量值final的並且是private,並且源碼中並沒有可以改變value數組的方法,同時stringbuffer的value數組權限是默認的且非final的;

StringBuilder是線程非安全的,stringbuffer是線程安全方法加鎖的;

二.list

1.ArrayList

底層由數組實現,

最主要的方法:

add(): 初始 默認是10; 先查詢是否進行擴容,如果擴容Array.copyof()方法,擴到1.5倍,;

remove() 其實底層用的是system.arraycopy; 

 public int size() {
        return size;
    }

返回的size是變量,是list的長度,而不是數組的長度;

2. ArrayList 的安全問題 

ArrayList 採用fail-fast 機制,是java集合的一中失敗檢測機制,在迭代過程中報錯;

具體場景是:

    List<String> list = new ArrayList<>();
           for (int i = 0 ; i < 10 ; i++ ) {
                list.add(i + "");
           }
           Iterator<String> iterator = list.iterator();
           int i = 0 ;
           while(iterator.hasNext()) {
                if (i == 3) {
                     list.remove(3);  //改成iterator.remove(3)方法代替就可以解決
                }
                System.out.println(iterator.next());
                i ++;
           }

 //這個時候就會報錯,因爲當ArraList在添加或者刪除操作時,會有個專門的記錄修改次數的變量+1,而在執行iterator.next()操作時候,會 進行一個判讀 expectedModCount和門的記錄修改次數的變量的判斷,這個時候就會報錯;

解決方法 :     list.remove(3);  //改成iterator.remove(3)方法代替就可以解決;

2.linkedList

雙向鏈表

變量:

 Node : first last;

方法 :

get(int index) //獲取指定位置的節點:

會把index 與size/2比,小於,從頭開始遍歷查找,大於從尾部查找開始;

也同時實現了普通隊列和棧的功能:

//出隊(從前端),如果不存在會返回null,存在的話會返回值並移除這個元素(節點)
    public E poll() {
        final Node<E> f = first;
        return (f == null) ? null : unlinkFirst(f);
    }
    //出隊(從前端),如果不存在會拋出異常而不是返回null,存在的話會返回值並移除這個元素(節點)
    public E remove() {
        return removeFirst();
    }
 構造函數:

其中有個構造函數

public LinkedList(Collection<? extends E> c) {
    this();
    addAll(c);
}

addAll方法把c轉換成數組,然後遍歷數組一個個添加,

三. map

1.hashMap

hashMap 是數組+鏈表的形式,根據key的hashcode 來確定放到哪個桶,當兩個key的hashcode相同時候,需要放在一個桶中,這個時候就用鏈表,如果鏈表長度超過(默認),就轉成紅黑樹;

如果數組越長 那麼hash衝突的概率就越小,而查找效率越快,但空間的佔用就越多,所以這個時候,出現了擴容機制;

擴容機制是 根據默認負載因子0.75,threshold=負載因子 * length; //判斷是否需要擴容,每次擴容*2;HashMap是先插入數據再進行擴容的,但是如果是剛剛初始化容器的時候是先擴容再插入數據。

擴容之後的hash計算   :只需要看看原來的hash值新增的那個bit是1還是0就好了,是0的話索引沒變,是1的話索引變成“原索引+oldCap”,

put()方法

檢測table[]是否爲空,

檢測table[i]是否爲插入過,選擇直接插入,或者遍歷

然後看是否鏈表超過8,編程紅黑樹;

如果key相同覆蓋,如果不是插入,

2.hashtable

hashtable 相對來說是線程安全的,加了鎖; 初始容量11 每次擴容2n+1;ashMap的迭代器(Iterator)是fail-fast迭代器;

Map m = Collections.synchronizeMap(hashMap);(讓hashmap變線程安全);

3.

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章