專門為了面試而學(xué)的 Java

1. hashmap hashtable

HashMap 是一個散列表架忌,它存儲的內(nèi)容是鍵值對(key-value)映射混聊。
HashMap 繼承于AbstractMap行贪,實現(xiàn)了Map牵咙、Cloneable芬为、java.io.Serializable接口萄金。
HashMap 的實現(xiàn)不是同步的,這意味著它不是線程安全的媚朦。它的key氧敢、value都可以為null。此外询张,HashMap中的映射不是有序的孙乖。
HashMap 的實例有兩個參數(shù)影響其性能:“初始容量” 和 “加載因子”。容量 是哈希表中桶的數(shù)量份氧,初始容量 只是哈希表在創(chuàng)建時的容量唯袄。加載因子 是哈希表在其容量自動增加之前可以達(dá)到多滿的一種尺度。當(dāng)哈希表中的條目數(shù)超出了加載因子與當(dāng)前容量的乘積時蜗帜,則要對該哈希表進(jìn)行 rehash 操作(即重建內(nèi)部數(shù)據(jù)結(jié)構(gòu))越妈,從而哈希表將具有大約兩倍的桶數(shù)。


HashMap繼承關(guān)系

hashmap底層就是一個數(shù)組钮糖,然后數(shù)組里每個元素裝了個鏈表梅掠。
這個數(shù)組元素稱為bucket桶


圖例

HashTable和HashMap區(qū)別
第一酌住,繼承不同。

public class Hashtable extends Dictionary implements Map
public class HashMap  extends AbstractMap implements Map

第二阎抒,Hashtable 中的方法是同步的酪我,而HashMap中的方法在缺省情況下是非同步的。在多線程并發(fā)的環(huán)境下且叁,可以直接使用Hashtable都哭,但是要使用HashMap的話就要自己增加同步處理了,對HashMap的同步處理可以使用Collections類提供的synchronizedMap靜態(tài)方法逞带,或者直接使用JDK 5.0之后提供的java.util.concurrent包里的ConcurrentHashMap類欺矫。

第三,Hashtable中展氓,key和value都不允許出現(xiàn)null值穆趴。在HashMap中,null可以作為鍵遇汞,這樣的鍵只有一個未妹;可以有一個或多個鍵所對應(yīng)的值為null。當(dāng)get()方法返回null值時空入,即可以表示 HashMap中沒有該鍵络它,也可以表示該鍵所對應(yīng)的值為null。因此歪赢,在HashMap中不能由get()方法來判斷HashMap中是否存在某個鍵化戳,而應(yīng)該用containsKey()方法來判斷。

第四埋凯,兩個遍歷方式的內(nèi)部實現(xiàn)上不同点楼。
Hashtable、HashMap都使用了 Iterator递鹉。而由于歷史原因盟步,Hashtable還使用了Enumeration的方式 藏斩。

第五躏结,哈希值的使用不同,HashTable直接使用對象的hashCode狰域。而HashMap重新計算hash值( indexFor )媳拴。

第六,Hashtable和HashMap它們兩個內(nèi)部實現(xiàn)方式的數(shù)組的初始大小和擴(kuò)容的方式兆览。HashTable中hash數(shù)組默認(rèn)大小是11屈溉,增加的方式是 old*2+1。HashMap中hash數(shù)組的默認(rèn)大小是16抬探,而且一定是2的指數(shù)子巾。

2. 為什么用枚舉實現(xiàn)的單例是最好的方式

  • 枚舉寫法簡單
public enum Singleton{
    INSTANCE帆赢;
}
  • 枚舉自己處理序列化
    在序列化的時候Java僅僅是將枚舉對象的name屬性輸出到結(jié)果中,反序列化的時候則是通過java.lang.Enum的valueOf方法來根據(jù)名字查找枚舉對象线梗。

3. jvm 內(nèi)存模型

內(nèi)存模型架構(gòu)圖
內(nèi)存模型架構(gòu)圖
  • 程序計數(shù)器
    每個線程有要有一個獨立的程序計數(shù)器椰于,記錄下一條要運行的指令。線程私有的內(nèi)存區(qū)域仪搔。如果執(zhí)行的是JAVA方法瘾婿,計數(shù)器記錄正在執(zhí)行的java字節(jié)碼地址,如果執(zhí)行的是native方法烤咧,則計數(shù)器為空偏陪。
  • 虛擬機(jī)棧
    線程私有的,與線程在同一時間創(chuàng)建煮嫌。管理JAVA方法執(zhí)行的內(nèi)存模型笛谦。
  • 本地方法區(qū)
    和虛擬機(jī)棧功能相似,但管理的不是JAVA方法立膛,是本地方法
  • 方法區(qū)
    線程共享的揪罕,用于存放被虛擬機(jī)加載的類的元數(shù)據(jù)信息:如常量、靜態(tài)變量宝泵、即時編譯器編譯后的代碼好啰。也稱為永久代。
  • JAVA 堆
    線程共享的儿奶,存放所有對象實例和數(shù)組框往。垃圾回收的主要區(qū)域〈成樱可以分為新生代和老年代(tenured)椰弊。

4. jdk 線程池

package cn.gaialine.threadpool;  
  
import java.util.concurrent.ArrayBlockingQueue;  
import java.util.concurrent.BlockingQueue;  
import java.util.concurrent.ThreadPoolExecutor;  
import java.util.concurrent.ThreadPoolExecutor.AbortPolicy;  
import java.util.concurrent.TimeUnit;  
  
/** 
 * 線程池測試用例 
 * @author yangyong 
 * 
 */  
public class TestThreadPool {  
    //線程池維護(hù)線程的最少數(shù)量  
    private static final int COREPOOLSIZE = 2;  
    //線程池維護(hù)線程的最大數(shù)量  
    private static final int MAXINUMPOOLSIZE = 5;  
    //線程池維護(hù)線程所允許的空閑時間  
    private static final long KEEPALIVETIME = 4;  
    //線程池維護(hù)線程所允許的空閑時間的單位  
    private static final TimeUnit UNIT = TimeUnit.SECONDS;  
    //線程池所使用的緩沖隊列,這里隊列大小為3  
    private static final BlockingQueue<Runnable> WORKQUEUE = new ArrayBlockingQueue<Runnable>(3);  
    //線程池對拒絕任務(wù)的處理策略:AbortPolicy為拋出異常;CallerRunsPolicy為重試添加當(dāng)前的任務(wù)瓤鼻,他會自動重復(fù)調(diào)用execute()方法秉版;DiscardOldestPolicy為拋棄舊的任務(wù),DiscardPolicy為拋棄當(dāng)前的任務(wù)  
    private static final AbortPolicy HANDLER = new ThreadPoolExecutor.AbortPolicy();  
  
    public static void main(String[] args) {  
        // TODO 初始化線程池  
        ThreadPoolExecutor threadPool = new ThreadPoolExecutor(COREPOOLSIZE, MAXINUMPOOLSIZE, KEEPALIVETIME, UNIT, WORKQUEUE, HANDLER);  
        for (int i = 1; i < 11; i++) {  
            String task = "task@"+i;  
            System.out.println("put->"+task);  
            //一個任務(wù)通過 execute(Runnable)方法被添加到線程池茬祷,任務(wù)就是一個 Runnable類型的對象清焕,任務(wù)的執(zhí)行方法就是 Runnable類型對象的run()方法  
            //處理任務(wù)的優(yōu)先級為:核心線程corePoolSize、任務(wù)隊列workQueue祭犯、最大線程maximumPoolSize秸妥,如果三者都滿了,使用handler處理被拒絕的任務(wù)  
            //設(shè)此時線程池中的數(shù)量為currentPoolSize,若currentPoolSize>corePoolSize,則創(chuàng)建新的線程執(zhí)行被添加的任務(wù),  
            //當(dāng)corePoolSize+workQueue>currentPoolSize>=corePoolSize,新增任務(wù)被放入緩沖隊列,  
            //當(dāng)maximumPoolSize>currentPoolSize>=corePoolSize+workQueue,建新線程來處理被添加的任務(wù),  
            //當(dāng)currentPoolSize>=maximumPoolSize,通過 handler所指定的策略來處理新添加的任務(wù)  
            //本例中可以同時可以被處理的任務(wù)最多為maximumPoolSize+WORKQUEUE=8個沃粗,其中最多5個在線程中正在處理粥惧,3個在緩沖隊列中等待被處理  
            //當(dāng)currentPoolSize>corePoolSize時,如果某線程空閑時間超過keepAliveTime最盅,線程將被終止突雪。這樣起惕,線程池可以動態(tài)的調(diào)整池中的線程數(shù)  
            threadPool.execute(new ThreadPoolTask(task));  
            try {  
                Thread.sleep(1000);  
            } catch (InterruptedException e) {  
                // TODO Auto-generated catch block  
                e.printStackTrace();  
            }  
        }  
        threadPool.shutdown();//關(guān)閉主線程,但線程池會繼續(xù)運行咏删,直到所有任務(wù)執(zhí)行完才會停止疤祭。若不調(diào)用該方法線程池會一直保持下去,以便隨時添加新的任務(wù)  
    }  
}  
package cn.gaialine.threadpool;  
  
import java.io.Serializable;  
  
/** 
 * 任務(wù)task 
 * @author yangyong 
 * 
 */  
public class ThreadPoolTask implements Runnable,Serializable{  
    private static final long serialVersionUID = -8568367025140842876L;  
  
    private Object threadPoolTaskData;  
    private static int produceTaskSleepTime = 10000;  
      
    public ThreadPoolTask(Object threadPoolTaskData) {  
        super();  
        this.threadPoolTaskData = threadPoolTaskData;  
    }  
  
    public void run() {  
        // TODO Auto-generated method stub  
        System.out.println("start..."+threadPoolTaskData);  
        try {  
            //模擬線程正在執(zhí)行任務(wù)  
            Thread.sleep(produceTaskSleepTime);  
        } catch (InterruptedException e) {  
            // TODO Auto-generated catch block  
            e.printStackTrace();  
        }  
        System.out.println("stop..."+threadPoolTaskData);  
        threadPoolTaskData = null;  
    }  
      
    public Object getTask(){  
        return this.threadPoolTaskData;  
    }  
//---------------
put->task@1  
start...task@1  
put->task@2  
start...task@2  
put->task@3  
put->task@4  
put->task@5  
put->task@6  
start...task@6  
put->task@7  
start...task@7  
put->task@8  
start...task@8  
put->task@9  
Exception in thread "main" java.util.concurrent.RejectedExecutionException  
    at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(Unknown Source)  
    at java.util.concurrent.ThreadPoolExecutor.reject(Unknown Source)  
    at java.util.concurrent.ThreadPoolExecutor.execute(Unknown Source)  
    at cn.gaialine.threadpool.TestThreadPool.main(TestThreadPool.java:42)  
stop...task@1  
start...task@3  
stop...task@2  
start...task@4  
stop...task@6  
start...task@5  
stop...task@7  
stop...task@8  
stop...task@3  
stop...task@4  
stop...task@5  

從中可以看出task1和task2依次最先執(zhí)行饵婆,這時候currentPoolSize=2達(dá)到了corePoolSize勺馆,task3、task4侨核、task5被送入緩沖隊列草穆,達(dá)到了workQueue最大值3,task6搓译、task7悲柱、task8開啟新的線程開始執(zhí)行,此時currentPoolSize=5達(dá)到了maximumPoolSize些己,task9豌鸡、task10根據(jù)AbortPolicy策略拋出異常,不再執(zhí)行task9和task10段标。10秒鐘后task1涯冠、task2....依次執(zhí)行完畢釋放線程,開始執(zhí)行隊列里的task3逼庞、task4蛇更、task5,最后task3赛糟、4派任、5執(zhí)行完畢,所有任務(wù)完成璧南。

JDK根據(jù)ThreadPoolExecutor配置好的線程池

// 固定工作線程數(shù)量的線程池  
ExecutorService executorService1 = Executors.newFixedThreadPool(3);  
  
// 一個可緩存的線程池  
ExecutorService executorService2 = Executors.newCachedThreadPool();  
  
// 單線程化的Executor  
ExecutorService executorService3 = Executors.newSingleThreadExecutor();  
  
// 支持定時的以及周期性的任務(wù)執(zhí)行  
ExecutorService executorService4 = Executors.newScheduledThreadPool(3);  

5. Java 內(nèi)存模型

內(nèi)存模型描述了程序中各個變量(實例域掌逛、靜態(tài)域和數(shù)組元素)之間的關(guān)系,以及在實際計算機(jī)系統(tǒng)中將變量存儲到內(nèi)存和從內(nèi)存中取出變量這樣的底層細(xì)節(jié)司倚。
JVM中存在一個主存區(qū)(Main Memory或Java Heap Memory)豆混,Java中所有變量都是存在主存中的,對于所有線程進(jìn)行共享对湃,而每個線程又存在自己的工作內(nèi)存(Working Memory)崖叫,工作內(nèi)存中保存的是主存中某些變量的拷貝遗淳,線程對所有變量的操作并非發(fā)生在主存區(qū)拍柒,而是發(fā)生在工作內(nèi)存中,而線程之間是不能直接相互訪問屈暗,變量在程序中的傳遞拆讯,是依賴主存來完成的脂男。
JMM的最初目的,就是為了能夠支持多線程程序設(shè)計的种呐,每個線程可以認(rèn)為是和其他線程不同的CPU上運行宰翅,或者對于多處理器的機(jī)器而言,該模型需要實現(xiàn)的就是使得每一個線程就像運行在不同的機(jī)器爽室、不同的CPU或者本身就不同的線程上一樣汁讼。

6. volatile 與 synchronized

在Java中,為了保證多線程讀寫數(shù)據(jù)時保證數(shù)據(jù)的一致性,可以采用兩種方式:

  • 同步
    如用synchronized關(guān)鍵字,或者使用鎖對象.
  • volatile
    使用volatile關(guān)鍵字
    用一句話概括volatile,它能夠使變量在值發(fā)生改變時能盡快地讓其他線程知道.

volatile本質(zhì)是在告訴jvm當(dāng)前變量在寄存器中的值是不確定的,需要從主存中讀取,synchronized則是鎖定當(dāng)前變量,只有當(dāng)前線程可以訪問該變量,其他線程被阻塞住.
volatile僅能使用在變量級別,synchronized則可以使用在變量,方法.
volatile僅能實現(xiàn)變量的修改可見性,但不具備原子特性,而synchronized則可以保證變量的修改可見性和原子性.
volatile不會造成線程的阻塞,而synchronized可能會造成線程的阻塞.
volatile標(biāo)記的變量不會被編譯器優(yōu)化,而synchronized標(biāo)記的變量可以被編譯器優(yōu)化.

7. 面試中遇到的問題

求一個無序數(shù)組的中位數(shù),白板寫code

因為時間有限阔墩,沒有多想嘿架,直接使用冒泡排序冒一半的數(shù)據(jù),另一半保持無序啸箫。如果有更好的方法請告訴我謝謝耸彪!

數(shù)據(jù)庫表的行轉(zhuǎn)列

使用case when就可以實現(xiàn)了,但是要注意需要對每個case when做max忘苛,以及最后的group by蝉娜,這樣可以去除null值。

使用map = new hashmap 比 hashmap = new hashmap 的好處

一時間沒想明白扎唾,因為覺得不會有人寫成hashmap = new hashmap召川,就答了一下實現(xiàn)依賴抽象,方便復(fù)用和修改胸遇,減少棧存儲之類亂七八糟的東西扮宠。。狐榔。如果有更好的答案也請告訴我謝謝??

== 和 equals 的區(qū)別

Object類中的equals方法和“==”是一樣的坛增,沒有區(qū)別,而String類薄腻,Integer類等等一些類收捣,是重寫了equals方法,才使得equals和“==不同”庵楷,所以罢艾,當(dāng)自己創(chuàng)建類時,自動繼承了Object的equals方法尽纽,要想實現(xiàn)不同的等于比較咐蚯,必須重寫equals方法。
"=="比"equal"運行速度快,因為"=="只是比較引用.

hashcode 和 equals 的具體實現(xiàn)方式

這真是個高頻問題弄贿,從大四找實習(xí)面試到研究生找工作面試到兩次跳槽一共幾十場技術(shù)面試幾乎全都問到了春锋。唯一一次沒問到的一次是因為我面的是算法工程師的職位,那次都在面機(jī)器學(xué)習(xí)的算法和實現(xiàn)……

默認(rèn) equals 方法直接調(diào)用了 ==

public boolean equals(Object obj) {
    return (this == obj);
}

String 改寫了 equals

public boolean equals(Object anObject) {
         if (this == anObject) {
             return true;
         }
         if (anObject instanceof String) {
             String anotherString = (String) anObject;
             int n = value.length;
             if (n == anotherString.value.length) {
                 char v1[] = value;
                 char v2[] = anotherString.value;
                 int i = 0;
                 while (n-- != 0) {
                     if (v1[i] != v2[i])
                             return false;
                     i++;
                 }
                 return true;
             }
         }
         return false;
     }

hashCode是根類Obeject中的方法差凹。默認(rèn)情況下期奔,Object中的hashCode() 返回對象的32位jvm內(nèi)存地址侧馅。也就是說如果對象不重寫該方法,則返回相應(yīng)對象的32為JVM內(nèi)存地址呐萌。

String類源碼中重寫的hashCode方法如下:

public int hashCode() {
    int h = hash;    //Default to 0 ### String類中的私有變量馁痴,
    if (h == 0 && value.length > 0) {    //private final char value[]; ### Sting類中保存的字符串內(nèi)容的的數(shù)組
        char val[] = value;

        for (int i = 0; i < value.length; i++) {
            h = 31 * h + val[i];
        }
        hash = h;
    }
    return h;
}

總結(jié):

(1)綁定。當(dāng)equals方法被重寫時肺孤,通常有必要重寫 hashCode 方法罗晕,以維護(hù) hashCode 方法的常規(guī)協(xié)定,該協(xié)定聲明相等對象必須具有相等的哈希碼赠堵。

(2)綁定原因攀例。Hashtable實現(xiàn)一個哈希表,為了成功地在哈希表中存儲和檢索對象顾腊,用作鍵的對象必須實現(xiàn) hashCode 方法和 equals 方法粤铭。同(1),必須保證equals相等的對象杂靶,hashCode 也相等梆惯。因為哈希表通過hashCode檢索對象。

(3)默認(rèn)吗垮。
  ==默認(rèn)比較對象在JVM中的地址垛吗。
  hashCode 默認(rèn)返回對象在JVM中的存儲地址。
  equal比較對象烁登,默認(rèn)也是比較對象在JVM中的地址怯屉,同==

reference:
http://blog.csdn.net/sdyy321/article/details/7407685
http://blog.csdn.net/fanaticism1/article/details/9966163
http://www.cnblogs.com/dingyingsi/p/3760447.html
http://www.cnblogs.com/xudong-bupt/p/3960177.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市饵沧,隨后出現(xiàn)的幾起案子锨络,更是在濱河造成了極大的恐慌,老刑警劉巖狼牺,帶你破解...
    沈念sama閱讀 219,490評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件羡儿,死亡現(xiàn)場離奇詭異,居然都是意外死亡是钥,警方通過查閱死者的電腦和手機(jī)掠归,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來悄泥,“玉大人虏冻,你說我怎么就攤上這事〉簦” “怎么了厨相?”我有些...
    開封第一講書人閱讀 165,830評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我领铐,道長,這世上最難降的妖魔是什么宋舷? 我笑而不...
    開封第一講書人閱讀 58,957評論 1 295
  • 正文 為了忘掉前任绪撵,我火速辦了婚禮,結(jié)果婚禮上祝蝠,老公的妹妹穿的比我還像新娘音诈。我一直安慰自己,他們只是感情好绎狭,可當(dāng)我...
    茶點故事閱讀 67,974評論 6 393
  • 文/花漫 我一把揭開白布细溅。 她就那樣靜靜地躺著,像睡著了一般儡嘶。 火紅的嫁衣襯著肌膚如雪喇聊。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,754評論 1 307
  • 那天蹦狂,我揣著相機(jī)與錄音誓篱,去河邊找鬼。 笑死凯楔,一個胖子當(dāng)著我的面吹牛窜骄,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播摆屯,決...
    沈念sama閱讀 40,464評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼邻遏,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了虐骑?” 一聲冷哼從身側(cè)響起准验,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎廷没,沒想到半個月后沟娱,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,847評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡腕柜,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,995評論 3 338
  • 正文 我和宋清朗相戀三年济似,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片盏缤。...
    茶點故事閱讀 40,137評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡砰蠢,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出唉铜,到底是詐尸還是另有隱情台舱,我是刑警寧澤,帶...
    沈念sama閱讀 35,819評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站竞惋,受9級特大地震影響柜去,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜拆宛,卻給世界環(huán)境...
    茶點故事閱讀 41,482評論 3 331
  • 文/蒙蒙 一嗓奢、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧浑厚,春花似錦股耽、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至敢艰,卻和暖如春诬乞,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背钠导。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評論 1 272
  • 我被黑心中介騙來泰國打工丽惭, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人辈双。 一個月前我還...
    沈念sama閱讀 48,409評論 3 373
  • 正文 我出身青樓责掏,卻偏偏與公主長得像,于是被迫代替她去往敵國和親湃望。 傳聞我的和親對象是個殘疾皇子换衬,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,086評論 2 355

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

  • 從三月份找實習(xí)到現(xiàn)在,面了一些公司证芭,掛了不少瞳浦,但最終還是拿到小米、百度废士、阿里叫潦、京東、新浪官硝、CVTE矗蕊、樂視家的研發(fā)崗...
    時芥藍(lán)閱讀 42,255評論 11 349
  • Java8張圖 11、字符串不變性 12氢架、equals()方法傻咖、hashCode()方法的區(qū)別 13、...
    Miley_MOJIE閱讀 3,707評論 0 11
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法岖研,類相關(guān)的語法卿操,內(nèi)部類的語法,繼承相關(guān)的語法,異常的語法害淤,線程的語...
    子非魚_t_閱讀 31,644評論 18 399
  • Java SE 基礎(chǔ): 封裝扇雕、繼承、多態(tài) 封裝: 概念:就是把對象的屬性和操作(或服務(wù))結(jié)合為一個獨立的整體窥摄,并盡...
    Jayden_Cao閱讀 2,110評論 0 8
  • 1小強(qiáng)升職記 2把時間當(dāng)做朋友 3白夜行 4活著 5百年孤獨 6圍城 7杜拉拉升職記 8暗時間 9拆掉思維的墻 1...
    若谷如是閱讀 250評論 0 0