數(shù)據(jù)結(jié)構(gòu)(順序表)的應(yīng)用——ArrayList、Vector分析

上篇我們提到了順序表在平常開(kāi)發(fā)中的應(yīng)用,現(xiàn)在我們只重點(diǎn)分析ArrayList及Vector的實(shí)現(xiàn)。

ArrayList想必大家都已經(jīng)很熟悉了,但是我們只是在外面調(diào)用接口,有的人并不知道其內(nèi)部的實(shí)現(xiàn)原理。我以前也是遇到集合都用ArrayList,但是用了那么多次也沒(méi)有對(duì)其有深入的了解,現(xiàn)在我們就一起來(lái)分析。

ArrayList是基于數(shù)組實(shí)現(xiàn)的,所以里面有很多操作都是通過(guò)數(shù)組來(lái)操作的,它是一個(gè)動(dòng)態(tài)數(shù)組,其容量能自動(dòng)增長(zhǎng),類(lèi)似于C語(yǔ)言中的動(dòng)態(tài)申請(qǐng)內(nèi)存,動(dòng)態(tài)增長(zhǎng)內(nèi)存。ArrayList不是線(xiàn)程安全的,只能在單線(xiàn)程環(huán)境下,多線(xiàn)程環(huán)境下可以考慮用Collections.synchronizedList(List l)函數(shù)返回一個(gè)線(xiàn)程安全的ArrayList類(lèi),也可以使用concurrent并發(fā)包下的CopyOnWriteArrayList類(lèi)。

(一)ArrayList的繼承關(guān)系與實(shí)現(xiàn)的接口

  public class ArrayList<E> extends AbstractList<E>
            implements List<E>, RandomAccess, Cloneable, java.io.Serializable

  --------------------------------------------------------------------------------------------------

  public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E>

   --------------------------------------------------------------------------------------------------

  public abstract class AbstractCollection<E> implements Collection<E> 

從ArrayList<E>可以看出它是支持泛型的,ArrayList繼承的是AbstractList,而AbstractList又繼承了AbstractCollection,AbstractCollection是Collection接口的實(shí)現(xiàn)類(lèi),里面封裝了一些集合的通用接口;而AbstractList可以說(shuō)是實(shí)現(xiàn)List接口的一個(gè)頂層實(shí)現(xiàn)類(lèi),里面也定義了一些有關(guān)List接口在對(duì)Collection的接口基礎(chǔ)上的拓展接口。我們通常使用的ArrayList就是AbstractList其中的一個(gè)子類(lèi)。

ArrayList實(shí)現(xiàn)了List接口,所以ArrayList必須實(shí)現(xiàn)List接口里面封裝的方法。

ArrayList實(shí)現(xiàn)了RandomAccess接口,支持快速隨機(jī)訪(fǎng)問(wèn)。

ArrayList實(shí)現(xiàn)了Cloneable接口,使得ArrayList能被克隆,

通過(guò)實(shí)現(xiàn) java.io.Serializable 接口以啟用其序列化功能。未實(shí)現(xiàn)此接口的類(lèi)將無(wú)法使其任何狀態(tài)序列化或反序列化。序列化接口沒(méi)有方法或字段,僅用于標(biāo)識(shí)可序列化的語(yǔ)義。

(二)ArrayList的屬性字段

  private static final int DEFAULT_CAPACITY = 10;     //ArrayList默認(rèn)的初始容量

  private static final Object[] EMPTY_ELEMENTDATA = {};  //用于空實(shí)例的共享空數(shù)組實(shí)例

ArrayList定義了兩個(gè)屬性,咋一看這不是我們的順序表的結(jié)構(gòu)嗎?
其中transient關(guān)鍵字表示的字段的生命周期僅存于調(diào)用者的內(nèi)存中而不會(huì)寫(xiě)到磁盤(pán)持久化。

  transient Object[] elementData;    //存放ArrayList的元素?cái)?shù)組

  private int size; 

(三)ArrayList的構(gòu)造函數(shù)

(1)帶有初始容量的構(gòu)造函數(shù)

      public ArrayList(int initialCapacity) {
            super();          //調(diào)用分類(lèi)AbstractList的空構(gòu)造
            if (initialCapacity < 0)
                  throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity);
            this.elementData = new Object[initialCapacity];      //根據(jù)傳進(jìn)來(lái)的初始容量建表
       }

(2)無(wú)參構(gòu)造函數(shù)

     public ArrayList(){    //可能有些Api的寫(xiě)法不一樣,但思想都是構(gòu)造了一個(gè)初始容量為10的數(shù)組
        super();
        this.elementData = EMPTY_ELEMENTDATA;   
     }

(3)無(wú)參構(gòu)造函數(shù)

    //將集合c中的元素全部復(fù)制到表中
    public ArrayList(Collection<? extends E> c){
        elementData = c.toArray();
        size = elementData.length;
        // c.toArray might (incorrectly) not return Object[] (see 6260652)
        //這個(gè)是谷歌工程師寫(xiě)的,他說(shuō)c的toArray方法有可能不返回一個(gè)數(shù)組,這里是一個(gè)bug
        if(elementData.getClass() != Object[].class){
            //數(shù)組的copy操作在這里就不分析了,可以查看Arrays的源碼
            elementData = Arrays.copyOf(elementData,size,Object[].class);
        }
    }

(四)ArrayList的增刪改查

(1)添加操作

    //在數(shù)組尾部添加元素e
    public boolean add(E e) {
        ensureCapacityInternal(size + 1);  //先確保數(shù)組容量是否夠用
        elementData[size++] = e;
        return true;
    }

    //在指定的位置index添加元素e
    public void add(int index,E e){
        rangeCheckForAdd(index);   //查看要添加的index是否越界
        ensureCapacity(size+1);
        //將index位置(包含)之后的數(shù)組全部往右移動(dòng)一位
        System.arraycopy(elementData,index,elementData,index+1,size-index);   //性能慢就是體現(xiàn)在這里
        elementData[index] = e;
        size++;
    }

    //將集合c添加到ArrayList中的指定位置
    public boolean addAll(int index,Collection<? extends E> c){
        rangeCheckForAdd(index);
        Object[] o = c.toArray();
        int numNew = o.length;  
        int numMoved = size - index; //數(shù)組要移動(dòng)的位數(shù)
        if(numMoved>0){
            //將index位置(包含)之后的數(shù)組全部往右移動(dòng)numNew位
            System.arraycopy(elementData,index,elementData,index+numNew,numMoved);
        }
        System.arraycopy(o,0,elementData,index,numNew);
        size += numNew;
        return numMoved != 0;
    }

    private void ensureCapacityInternal(int minCapacity) {
        if (elementData == EMPTY_ELEMENTDATA) {  //如果空表
             //取默認(rèn)容量和數(shù)組要達(dá)到的最小容量的最大值
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); 
        }

        ensureExplicitCapacity(minCapacity);    //確保容量
    }

    private void ensureExplicitCapacity(int minCapacity) {
        modCount++;      //這個(gè)是List的改變次數(shù),在ArrayList的父類(lèi)上定義的,可以不必太過(guò)理會(huì)

        // overflow-conscious code
        if (minCapacity - elementData.length > 0)  //如果傳進(jìn)來(lái)的容量大于數(shù)組長(zhǎng)度,就說(shuō)明數(shù)組的容量不夠用了
            grow(minCapacity);    //增長(zhǎng)容量
        }

      //ArrayList的擴(kuò)容機(jī)制
      private void grow(int minCapacity) {
          // overflow-conscious code
          int oldCapacity = elementData.length;    //原來(lái)的容量
          int newCapacity = oldCapacity + (oldCapacity >> 1);    //定義新的容量為原來(lái)的3/2倍
          if (newCapacity - minCapacity < 0)    //如果新的容量都不夠用,直接將要增長(zhǎng)的容量作為數(shù)組的新的容量
              newCapacity = minCapacity;    
          if (newCapacity - MAX_ARRAY_SIZE > 0)    //如果新的容量超過(guò)了最大值,
              newCapacity = hugeCapacity(minCapacity);
         // minCapacity is usually close to size, so this is a win:
          elementData = Arrays.copyOf(elementData, newCapacity);  //把原來(lái)的數(shù)組復(fù)制到新的數(shù)組中,還是用elementData 表示,并指定新的容量
      }
      
      //MAX_ARRAY_SIZE=Integer.MAX_VALUE - 8;
      private static int hugeCapacity(int minCapacity) {
          if (minCapacity < 0) // overflow
              throw new OutOfMemoryError();
          return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE;
      }
    
      private void rangeCheckForAdd(int index){
          if(index<0 || index>size){
              throw new IndexOutOfBoundsException("Index:"+index+",Size:"+size);
          }
      }

(2)刪除操作

    //刪除數(shù)組中指定位置的元素
    public E remove(int index){
        rangeCheck(index);    //為要?jiǎng)h除和查找的Index查看是否越界
        E oldValue = (E)elementData[index];
          //需要復(fù)制元素的個(gè)數(shù),也就是index后面的元素個(gè)數(shù)
        int numMoved = size - index -1;
        if(numMoved>0){
            //將index后面的元素全部往前移動(dòng)1個(gè)位置
            System.arraycopy(elementData,index+1,elementData,index,numMoved);
        }
        //經(jīng)過(guò)arraycopy的移位,數(shù)組容器的最個(gè)位置被騰空,但是仍然持有某個(gè)對(duì)象的引用,需要把這個(gè)多余的引用置為null.
        elementData[--size] = null;
        return oldValue;
    }

    //刪除數(shù)組中的對(duì)象
    public boolean remove(Object o){
        if(o == null){    //對(duì)象為Null的刪除方法
            for(int index=0;index<size;index++){
                fastRemove(index);
                return true;
            }
        }else{
            for(int index=0;index<size;index++){
                if(elementData[index].equals(o)){
                    fastRemove(index);
                    return true;
                }
             }
        }
        return false;
    }

    //快速刪除 這是個(gè)內(nèi)部方法,數(shù)組越界已經(jīng)在上個(gè)方法中判斷,這里就不再進(jìn)行判斷了
    private void fastRemove(int index){
        int numMoved = size - index -1;
        if(numMoved > 0){
            System.arraycopy(elementData,index+1,elementData,index,numMoved);
        }
        elementData[--size] = null;
    }

    private void rangeCheck(int index){
        if(index<0 || index>=size){
            throw new IndexOutOfBoundsException("Index:"+index+",Size:"+size);
        }
    }

(3)修改操作

    public E set(int index,E e){
        rangeCheck(index);    //檢查下標(biāo)越界問(wèn)題
        E oldValue = (E)elementData[index];
        elementData[index] = e;    //直接將當(dāng)前位置的元素進(jìn)行替換
        return oldValue;
    }

(4)查詢(xún)操作

    public E get(int index){
        rangeCheck(index);
        E oldValue = (E)elementData[index];
        return oldValue;
    }

(五)ArrayList定義的一些集合方法和數(shù)組的下表查詢(xún)方法

    public int size() {
        return size;
    }

    public boolean isEmpty() {
        return size == 0;
    }

    //清空數(shù)組
    public void clear() {
        // clear to let GC do its work
        for (int i = 0; i < size; i++)
            elementData[i] = null;
        size = 0;
    }

    //將當(dāng)前容量值設(shè)置為實(shí)際元素個(gè)數(shù)
    public void trimToSize() {
        modCount++;
        if (size < elementData.length) {
            elementData = (size == 0) ? EMPTY_ELEMENTDATA : Arrays.copyOf(elementData, size);
        }
    }
    
    //判斷數(shù)組中是否包含這個(gè)對(duì)象
    public boolean contains(Object o) {
        return indexOf(o) >= 0;
    }

    //返回對(duì)象在數(shù)組中的下標(biāo)(第一次出現(xiàn)的)
    public int indexOf(Object o) {
        if (o == null) {
            for (int i = 0; i < size; i++)
                if (elementData[i]==null)
                    return i;
        } else {
            for (int i = 0; i < size; i++)
                if (o.equals(elementData[i]))
                    return i;
        }
        return -1;
    }

    //返回對(duì)象在數(shù)組中最后一次出現(xiàn)的下標(biāo)位置
    public int lastIndexOf(Object o) {
        if (o == null) {
            for (int i = size-1; i >= 0; i--)
                if (elementData[i]==null)
                    return i;
        } else {
            for (int i = size-1; i >= 0; i--)
                if (o.equals(elementData[i]))
                    return i;
        }
        return -1;
    }

這些就是ArrayList的大概了,還有遍歷和迭代器沒(méi)分析,但是我覺(jué)得那不是最重要的,重要的是了解ArrayList的數(shù)據(jù)結(jié)構(gòu)和增刪改查操作還有擴(kuò)容機(jī)制。這些也是面試中可能遇到的問(wèn)題,只有了解了其中的實(shí)現(xiàn)原理,我們才能在面試官面前對(duì)答如流,還有提升自己。有些方法可能在個(gè)版本的不一樣,我這里是在用Android SDK里面的源碼進(jìn)行分析的,除非有版本變了數(shù)據(jù)結(jié)構(gòu),否則實(shí)現(xiàn)原理都是一樣的。對(duì)于Vector我們不必太過(guò)深究,因?yàn)楝F(xiàn)在基本看不到使用了。

(六)ArrayList和Vector
還有Vector沒(méi)分析,但其實(shí)Vector的實(shí)現(xiàn)原理和ArrayList基本上是一模一樣的,只是Vector在實(shí)現(xiàn)增刪改查等等操作時(shí)添加了synchronized關(guān)鍵字,在多線(xiàn)程情況下是安全的。

List接口下一共實(shí)現(xiàn)了三個(gè)類(lèi):ArrayList,Vector,LinkedList。LinkedList就不多說(shuō)了,它一般主要用在保持?jǐn)?shù)據(jù)的插入順序的時(shí)候。ArrayList和Vector都是用數(shù)組實(shí)現(xiàn)的,主要有這么三個(gè)區(qū)別:

1、Vector是多線(xiàn)程安全的,而ArrayList不是,這個(gè)可以從源碼中看出,Vector類(lèi)中的方法很多有synchronized進(jìn)行修飾,這樣就導(dǎo)致了Vector在效率上無(wú)法與ArrayList相比;

2、兩個(gè)都是采用的線(xiàn)性連續(xù)空間存儲(chǔ)元素,但是當(dāng)空間不足的時(shí)候,兩個(gè)類(lèi)的增加方式是不同的,很多網(wǎng)友說(shuō)Vector增加原來(lái)空間的一倍,ArrayList增加原來(lái)的1.5倍。

    //ArrayList的擴(kuò)容
       private void grow(int minCapacity) {
           // overflow-conscious code
          int oldCapacity = elementData.length;
          int newCapacity = oldCapacity + (oldCapacity >> 1);
          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);
      }

     // Vector擴(kuò)容,這個(gè)擴(kuò)容需要做個(gè)判斷:如果容量增量初始化的不是0,即使用的public Vector(int initialCapacity,int capacityIncrement)構(gòu)造方法進(jìn)行的初始化,那么擴(kuò)容的容量是(oldCapacity+capacityIncrement),就是原來(lái)的容量加上容量增量的值; 
      //如果沒(méi)有設(shè)置容量增量,那么擴(kuò)容后的容量就是(oldCapacity+oldCapacity),就是原來(lái)容量的二倍。
      private void grow(int minCapacity) {
         // overflow-conscious code
         int oldCapacity = elementData.length;
         int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
                                     capacityIncrement : oldCapacity);
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

3、Vector可以設(shè)置增長(zhǎng)因子,而ArrayList不可以,最開(kāi)始看這個(gè)的時(shí)候,我沒(méi)理解什么是增量因子,不過(guò)通過(guò)對(duì)比一下兩個(gè)源碼理解了這個(gè),先看看兩個(gè)類(lèi)的構(gòu)造方法:
ArrayList有三個(gè)構(gòu)造方法:

    public ArrayList(int initialCapacity)//構(gòu)造一個(gè)具有指定初始容量的空列表。  
    public ArrayList()//構(gòu)造一個(gè)初始容量為10的空列表。  
    public ArrayList(Collection<? extends E> c)//構(gòu)造一個(gè)包含指定 collection 的元素的列表  

Vector有四個(gè)構(gòu)造方法:

    public Vector()//使用指定的初始容量和等于零的容量增量構(gòu)造一個(gè)空向量。  
    public Vector(int initialCapacity)//構(gòu)造一個(gè)空向量,使其內(nèi)部數(shù)據(jù)數(shù)組的大小,其標(biāo)準(zhǔn)容量增量為零。  
    public Vector(Collection<? extends E> c)//構(gòu)造一個(gè)包含指定 collection 中的元素的向量  
    public Vector(int initialCapacity,int capacityIncrement)//使用指定的初始容量和容量增量構(gòu)造一個(gè)空的向量  

(七)ArrayList總結(jié)

(1)ArrayList是線(xiàn)性表中的順序存儲(chǔ)結(jié)構(gòu)的順序表,因?yàn)閮?nèi)部維護(hù)的是一個(gè)數(shù)組,數(shù)組是一個(gè)擁有連續(xù)存儲(chǔ)地址的存儲(chǔ)塊。

(2)ArrayList因?yàn)閮?nèi)部維護(hù)的是一個(gè)數(shù)組,查詢(xún)和修改的效率很高,尾部插入效率也高,但是插入添加和刪除的效率比較低,性能變慢具體體現(xiàn)在數(shù)組的copy上,特別是數(shù)據(jù)量大的情況下必較明顯。

(3)ArrayList在添加元素的時(shí)候是允許加入null元素的。但我們?cè)谔砑訑?shù)據(jù)的時(shí)候最好對(duì)數(shù)據(jù)進(jìn)行非空判斷,否則取出來(lái)的數(shù)據(jù)在使用的時(shí)候空指針?lè)址昼娊棠阕鋈恕?/p>

(4)ArrayList的是線(xiàn)程不安全的,盡量不要在多線(xiàn)程環(huán)境下使用ArrayList。

請(qǐng)老司機(jī)指出不足之處,謝謝!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,527評(píng)論 6 544
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,687評(píng)論 3 429
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 178,640評(píng)論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 63,957評(píng)論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,682評(píng)論 6 413
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 56,011評(píng)論 1 329
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,009評(píng)論 3 449
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 43,183評(píng)論 0 290
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,714評(píng)論 1 336
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,435評(píng)論 3 359
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,665評(píng)論 1 374
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,148評(píng)論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,838評(píng)論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 35,251評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 36,588評(píng)論 1 295
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,379評(píng)論 3 400
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,627評(píng)論 2 380

推薦閱讀更多精彩內(nèi)容

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法,類(lèi)相關(guān)的語(yǔ)法,內(nèi)部類(lèi)的語(yǔ)法,繼承相關(guān)的語(yǔ)法,異常的語(yǔ)法,線(xiàn)程的語(yǔ)...
    子非魚(yú)_t_閱讀 31,737評(píng)論 18 399
  • 面向?qū)ο笾饕槍?duì)面向過(guò)程。 面向過(guò)程的基本單元是函數(shù)。 什么是對(duì)象:EVERYTHING IS OBJECT(萬(wàn)物...
    sinpi閱讀 1,082評(píng)論 0 4
  • Java源碼研究之容器(1) 如何看源碼 很多時(shí)候我們看源碼, 看完了以后經(jīng)常也沒(méi)啥收獲, 有些地方看得懂, 有些...
    駱駝騎士閱讀 1,006評(píng)論 0 22
  • 昨天晚上,做完飯,小妞邀請(qǐng)我一起玩兒,我看到她自己做的泡泡水,居然吹出了超級(jí)無(wú)敵大的泡泡,欣喜。還教我一些新花樣,...
    如水心情_(kāi)3473閱讀 184評(píng)論 0 0
  • 其實(shí)大概一個(gè)月前我才在喜馬拉雅上把《盜墓筆記》聽(tīng)完。聽(tīng)了差不多一個(gè)月,每晚睡覺(jué)前把音頻下載好,第二天起來(lái)去上班的路...
    賤賤小姐閱讀 347評(píng)論 0 0