Android面試一Java部分

本系列出于AWeiLoveAndroid的分享划纽,在此感謝,再結(jié)合自身經(jīng)驗(yàn)查漏補(bǔ)缺瞎领,完善答案泌辫。以成系統(tǒng)。


Java基礎(chǔ)

  • java中==和equals和hashCode的區(qū)別

http://blog.csdn.net/dove_knowledge/article/details/71027170

  • == 基本類型比較的是值 引用類型針對(duì)的是變量在堆內(nèi)存的地址
  • equals 針對(duì)引用類型 Object默認(rèn)實(shí)現(xiàn)是 this==object九默,這個(gè)可以在子類中復(fù)寫決定equals是否相等震放。示例 String a = new String("abc")
    String b = new String("abc") a==b 返回false a.equals(b)返回true,原理是String的equals方法為:
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof String) {
            String anotherString = (String) anObject;
            int n = length();
            if (n == anotherString.length()) {
                int i = 0;
                while (n-- != 0) {
                    if (charAt(i) != anotherString.charAt(i))
                            return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }
public int hashCode() {
        int h = hash;
        final int len = length();
        if (h == 0 && len > 0) {
            for (int i = 0; i < len; i++) {
                h = 31 * h + charAt(i);
            }
            hash = h;
        }
        return h;
    }
  • hashCode Object中的hashCode返回的就是其內(nèi)存地址的int值驼修,對(duì)于兩個(gè)對(duì)象如果沒有重寫hashCode方法殿遂,則兩個(gè)對(duì)象的hashCode值不可能相等。hashCode方法一般不會(huì)交由用戶來用邪锌,例如在hashmap中勉躺,由于key是不可以重復(fù)的,它在判斷key是否重復(fù)時(shí)就判斷了hashCode()方法觅丰,而且也用到了equals()方法饵溅。此處“不可以重復(fù)”指的是equals()和hashCode()只要有一個(gè)不等就可以了。所以一般equals和hashCode應(yīng)該同時(shí)被重寫妇萄。
  • hashCode()方法的返回值和equals()方法的關(guān)系如下:x.equals(y)返回true蜕企,即兩個(gè)對(duì)象根據(jù)equals()方法比較是相等的,那么調(diào)用這兩個(gè)對(duì)象中任意一個(gè)對(duì)象的hashCode()方法都必須產(chǎn)生同樣的整數(shù)結(jié)果冠句。
  • int轻掩、char、long各占多少字節(jié)數(shù)
  • int與integer的區(qū)別
  1. Integer是int的包裝類懦底,int是基本類型
  2. Integer變量必須先實(shí)例化唇牧,int變量不需要
  3. Integer變量是一個(gè)對(duì)象的引用,int變量直接存儲(chǔ)的值
  4. Integer默認(rèn)值null ,int默認(rèn)值0
    https://www.cnblogs.com/guodongdidi/p/6953217.html
  • java的Integer源碼解析與自動(dòng)拆箱與裝箱

特別注意源碼中IntegerCache所定義的-128到127的緩存丐重,這點(diǎn)決定了一些判等問題的結(jié)果
http://blog.csdn.net/chenliguan/article/details/53888018

  • Java中如何解決double和float精度不準(zhǔn)的問題

BigDecimal解決精度不準(zhǔn)問題
public static double add(double d1,double d2){
??BigDecimal b1=new BigDecimal(Double.toString(d1));
??BigDecimal b2=new BigDecimal(Double.toString(d2));
??return b1.add(b2).doubleValue();
}

  • 談?wù)剬?duì)java多態(tài)的理解
  1. java的三大特性(繼承腔召,封裝,多態(tài))之一
  2. 定義:允許不同類的對(duì)象對(duì)同一消息作出反應(yīng)扮惦。即同一消息可以根據(jù)發(fā)送對(duì)象的不同而采用多種不同的行為方式(消息也就是函數(shù)調(diào)用)臀蛛。
  3. 父類引用指向子類對(duì)象
  4. 具有 可替換性,可擴(kuò)展性崖蜜,接口性浊仆,靈活性,簡(jiǎn)化性的好處豫领。
  • String抡柿、StringBuffer、StringBuilder區(qū)別
  1. String 是字符串常量氏堤,StringBuffer和StringBuilder是字符串變量
  2. 對(duì)String的操作JVM沙绝,拷貝舊的再創(chuàng)建個(gè)新的,同名的String對(duì)象會(huì)在JVM中回收重建鼠锈。
  3. StringBuffer和StringBuilder都繼承自AbstractStringBuilder,這里面含有一個(gè)char[] value 成員星著,用來存儲(chǔ)字符购笆。append就是不斷的改變value的容量以存儲(chǔ)字符串的。
  4. 從源碼角度看虚循,StringBuffer的很多操作方法前面都有synchronized修飾符同欠,而StringBuilder中并沒有。也就是說StringBuffer的操作是線程安全的横缔。
  5. 結(jié)論:
    從操作速率上 StringBuilder>StringBuffer>String
    從線程安全上 StringBuffer線程安全的铺遂,StringBuilder和String非線程安全
  • 內(nèi)部類??jī)?nèi)部類的分類茎刚??jī)?nèi)部類與閉包

https://www.cnblogs.com/dolphin0520/p/3811445.html

  • 定義:定義在一個(gè)類或者方法內(nèi)的類
  • 類型: 成員內(nèi)部類襟锐,局部?jī)?nèi)部類,匿名內(nèi)部類膛锭,靜態(tài)內(nèi)部類
  • 作用:
  1. 使得Java多繼承的解決方案得到完善
  2. 有利于代碼的獨(dú)立于封裝
  3. 每個(gè)內(nèi)部類都能獨(dú)立地繼承一個(gè)(接口的)實(shí)現(xiàn)粮坞,所以無論外圍類是否已經(jīng)繼承了某個(gè)(接口的)實(shí)現(xiàn),對(duì)于內(nèi)部類都沒有影響初狰。
  • 靜態(tài)內(nèi)部類的設(shè)計(jì)意圖
    要從靜態(tài)內(nèi)部類和非靜態(tài)內(nèi)部類的特點(diǎn)來看莫杈。靜態(tài)內(nèi)部類對(duì)象的創(chuàng)建不依賴其所在外部類的實(shí)例,靜態(tài)內(nèi)部類可以有靜態(tài)成員和方法奢入,但是不能直接訪問外部類的非靜態(tài)成員和方法筝闹。從這些特點(diǎn)上來看更是為了不全內(nèi)部類的設(shè)計(jì)。
  • 閉包和局部?jī)?nèi)部類的區(qū)別
  1. 比表的解釋:閉包就是把函數(shù)以及變量包起來,使得變量的生存周期延長(zhǎng)关顷。
  2. Java中通過接口和內(nèi)部類來實(shí)現(xiàn)閉包
  • 注意:
  • 非靜態(tài)內(nèi)部類會(huì)持有外部類的引用糊秆,從class文件可以看出,這也就是內(nèi)部類能訪問外部類成員的原因
  • 內(nèi)部類對(duì)象的創(chuàng)建:
    外部類.內(nèi)部類 a = 外部類對(duì)象.new 內(nèi)部類();
    靜態(tài)內(nèi)部類對(duì)象的創(chuàng)建
    外部類.內(nèi)部類 a = new 外部類.內(nèi)部類();
  • 局部?jī)?nèi)部類解寝,匿名內(nèi)部類訪問局部變量加final的原理:局部變量的生命周期是方法內(nèi)扩然,局部?jī)?nèi)部類要訪問局部變量時(shí)可能該變量已經(jīng)over了,為此在編譯階段jvm會(huì)將局部變量進(jìn)行拷貝然后放到局部類的class文件中聋伦,為了保證這個(gè)拷貝的變量不會(huì)再發(fā)生變化夫偶,導(dǎo)致局部?jī)?nèi)部類里的值不是最終的,java語(yǔ)法規(guī)定局部?jī)?nèi)部類訪問局部變量時(shí)必須用final修飾觉增。
  • 抽象類和接口區(qū)別

接口:行為規(guī)范
抽象類:事物抽象
區(qū)別點(diǎn):默認(rèn)方法實(shí)現(xiàn)兵拢,實(shí)現(xiàn)關(guān)鍵字,構(gòu)造器逾礁,與普通類的區(qū)別说铃,訪問修飾符,main方法嘹履,多繼承腻扇,速度捏题,添加新方法九個(gè)區(qū)別點(diǎn)明郭。
http://www.importnew.com/12399.html

  • 抽象類的意義
  1. 為子類提供一個(gè)公共的類型典尾;
  2. 封裝子類中重復(fù)內(nèi)容(成員變量和方法)淹魄;
  3. 定義有抽象方法灿里,子類雖然有不同的實(shí)現(xiàn)靖苇,但該方法的定義是一致的
  • 接口的意義

提供了行為規(guī)范嘶朱。保證訪問的統(tǒng)一性溯捆。利于程序的維護(hù)和擴(kuò)展配并。
https://www.cnblogs.com/zhaoyanjun/archive/2016/03/25/5320034.html

  • 泛型的理解

http://www.importnew.com/24029.html

  • 泛型中extends和super的區(qū)別(PECS原則)
  • T extends A : A及A的子類括荡,返回型 例如 T get()類
  • T super A : A及A的父類, 參數(shù)型 例如 add(T a)類
  • 泛型擦除
  • 現(xiàn)象就是編譯后的泛型將變?yōu)?Object或者bound類型(例如 T extends Comparable 泛型擦除后會(huì)變?yōu)?Comparable)
  • 帶來的問題: 1. 不允許創(chuàng)建泛型數(shù)組; 2. Bridge method會(huì)導(dǎo)致與多態(tài)沖突; 3. E elem = new E()不行,這個(gè)問題可以通過反射解決; 4. 無法對(duì)泛型代碼直接使用instanceof關(guān)鍵字
  • 父類的靜態(tài)方法/靜態(tài)屬性能否被子類重寫?

因?yàn)殪o態(tài)方法在運(yùn)行時(shí)就分配好內(nèi)存溉旋,也就是固定好了畸冲,后面父類還是子類使用時(shí)都是使用同一塊內(nèi)存區(qū)域的代碼,子類中有重名的低滩,也會(huì)為其單獨(dú)分配塊內(nèi)存召夹。可見靜態(tài)方法/靜態(tài)屬性的繼承性質(zhì)在恕沫,但是被隱藏了监憎,但談不上重寫。

  • 枚舉的知識(shí)點(diǎn)

http://blog.csdn.net/javazejian/article/details/71333103

  • 這個(gè)知識(shí)點(diǎn)關(guān)鍵是反編譯枚舉的.class文件婶溯。
  • 特點(diǎn):使用enum修飾鲸阔,繼承自Enum類而不是Object;非抽象枚舉類默認(rèn)會(huì)加上final修飾偷霉,不能再被繼承;枚舉類構(gòu)造器默認(rèn)private也只能用private修飾褐筛;枚舉示例在第一行搞定类少,否則再也沒法創(chuàng)建示例了。
  • transient的作用
  • 一旦變量被transient修飾渔扎,變量將不再是對(duì)象持久化的一部分硫狞,該變量?jī)?nèi)容在序列化后無法獲得訪問。
  • transient關(guān)鍵字只能修飾變量晃痴,而不能修飾方法和類残吩。注意,本地變量是不能被transient關(guān)鍵字修飾的倘核。變量如果是用戶自定義類變量泣侮,則該類需要實(shí)現(xiàn)Serializable接口。
  • 被transient關(guān)鍵字修飾的變量不再能被序列化紧唱,一個(gè)靜態(tài)變量不管是否被transient修飾活尊,均不能被序列化。
  • 只配合到Serializable漏益,Parcelable則是自定義序列化的蛹锰,與是否有transient修飾無關(guān)
  • volatile關(guān)鍵字引發(fā)的并發(fā)編程知識(shí)

http://www.importnew.com/18126.html

  • 內(nèi)存模型基礎(chǔ)概念:
    cpu + 高速緩存 + 主存;
    簡(jiǎn)單理解:cpu 將內(nèi)存中的內(nèi)容拿到高速緩存中绰疤,處理完后將結(jié)果放回主存宁仔,當(dāng)多線程時(shí)就會(huì)出現(xiàn)緩存不一致問題;
    解決這個(gè)有兩個(gè)方案一個(gè)是總線鎖峦睡,就是在操作變量?jī)?nèi)存空間時(shí)加上總線鎖,其它線程要操作這塊內(nèi)存需要等其它線程釋放鎖后才行;
    另一個(gè)方案是緩存一致協(xié)議权埠,線程1操作時(shí)會(huì)將內(nèi)存置為無效榨了,線程2發(fā)現(xiàn)無效就去主存拿了。
  • 并發(fā)編程的三個(gè)概念:
    原子性(轉(zhuǎn)賬一減一加必須一氣呵成攘蔽,不能終端)龙屉。
    可見性(你拿走去處理了,處理好要告訴我满俗,否則我再拿的時(shí)候還是舊的)转捕。
    有序性(指令重排序可能會(huì)讓你寫的代碼不是自上而下執(zhí)行,但是人家會(huì)保證結(jié)果如排序一樣唆垃,所以當(dāng)上下發(fā)生數(shù)據(jù)依賴時(shí)五芝,人家不會(huì)亂執(zhí)行的);
    由上可知辕万,要想寫好并發(fā)編程枢步,必須要同時(shí)保證原子性沉删,可見性和有序性,缺一不可醉途!
  • JMM(Java內(nèi)存模型)
    Java內(nèi)存模型并沒有限制執(zhí)行引擎使用處理器的寄存器或者高速緩存來提升指令執(zhí)行速度矾瑰,也沒有限制編譯器對(duì)指令進(jìn)行重排序。
    Java內(nèi)存模型規(guī)定所有的變量都是存在主存當(dāng)中(類似于前面說的物理內(nèi)存)隘擎,每個(gè)線程都有自己的工作內(nèi)存(類似于前面的高速緩存)殴穴。線程對(duì)變量的所有操作都必須在工作內(nèi)存中進(jìn)行,而不能直接對(duì)主存進(jìn)行操作货葬。并且每個(gè)線程不能訪問其他線程的工作內(nèi)存采幌。
  • Java對(duì)原子性,可見性宝惰,有序性的保障
    原子性:只有讀取和賦值是原子操作
    可見性: 用volatitle關(guān)鍵字保證可見性植榕;通過synchronized和Lock也能夠保證可見性,synchronized和Lock能保證同一時(shí)刻只有一個(gè)線程獲取鎖然后執(zhí)行同步代碼尼夺,并且在釋放鎖之前會(huì)將對(duì)變量的修改刷新到主存當(dāng)中尊残。因此可以保證可見性。
    有序性: volatile關(guān)鍵字來保證一定的“有序性;synchronized和Lock保證每個(gè)時(shí)刻是有一個(gè)線程執(zhí)行同步代碼淤堵,相當(dāng)于是讓線程順序執(zhí)行同步代碼寝衫,自然就保證了有序性;happens-before原則保證了先天有序性。
  • volatile關(guān)鍵字
    (1) 保證了不同線程對(duì)這個(gè)變量進(jìn)行操作時(shí)的可見性拐邪,即一個(gè)線程修改了某個(gè)變量的值慰毅,這新值對(duì)其他線程來說是立即可見的。(本質(zhì)上用的是緩存一致協(xié)議的思路保證了可見性)
    (2) 禁止進(jìn)行指令重排序扎阶。(假如有 1 2 3 4 5條語(yǔ)句汹胃,3有volatile修飾 則執(zhí)行順序上 3可不能在 1 2 前 也不可能在 4 5后 ,并且到3時(shí) 1 2肯定是完事了东臀,且對(duì) 3 4 5可見着饥。但是這里不能保證 1 2 或者 4 5 是否會(huì)被重排序,故而說volatile能在一定程度上保證有序性)
  • volatile作用的祖墳級(jí)原理
    volatile修飾的語(yǔ)句惰赋,在匯編時(shí)會(huì)在前面加一個(gè)Lock前綴指令宰掉,這個(gè)指令又稱內(nèi)存柵欄,volatile之所以能有如此作用赁濒,關(guān)鍵是靠這個(gè)內(nèi)存柵欄:
  1. 內(nèi)存柵欄能確保重排序時(shí)不越過此柵欄轨奄,前者不能其后,后者不可到其前;
  2. 強(qiáng)制對(duì)緩存的操作立即寫入內(nèi)存
  3. 如果是寫操作拒炎,它會(huì)導(dǎo)致其它c(diǎn)pu中的緩存無效
  • volatile應(yīng)用場(chǎng)景
    volatile主迸材猓可見性,難保原子性枝冀,所以不能完全替代synchronized所保的原子性和有序性舞丛。但在一些情況下用volatile效率要高于synchronized耘子。常見場(chǎng)景如下:

狀態(tài)標(biāo)記量 : 一個(gè)狀態(tài)變量
double check: 例如單例雙重鎖寫法中的靜態(tài)instance可以用volatile修飾

  • synchronized關(guān)鍵字

http://www.importnew.com/23511.html
synchronized可以保證方法或者代碼塊在運(yùn)行時(shí),同一時(shí)刻只有一個(gè)方法可以進(jìn)入到臨界區(qū)球切,同時(shí)它還可以保證共享變量的內(nèi)存可見性

  • 進(jìn)程和線程的定義谷誓,關(guān)系與區(qū)別

https://www.cnblogs.com/lgk8023/p/6430592.html

  • 進(jìn)程:狹義上就是一段程序的執(zhí)行過程,廣義上為具有一定獨(dú)立功能的程序在某個(gè)數(shù)據(jù)集合上的一次活動(dòng)吨凑,進(jìn)程是操作系統(tǒng)分配資源的基本單位
  • 線程:是進(jìn)程的組成部分捍歪,一個(gè)進(jìn)程可以有多個(gè)線程,而一個(gè)線程必須有一個(gè)父進(jìn)程鸵钝。線程可以擁有自己的堆棧糙臼,自己的程序計(jì)數(shù)器和自己的局部變量,單不能擁有系統(tǒng)資源恩商。它與父進(jìn)程和其它線程共享其父進(jìn)程的所有資源变逃。
  • 進(jìn)程線程的關(guān)系:
  1. 一個(gè)進(jìn)程可以有多個(gè)線程,但至少有一個(gè)線程怠堪,一個(gè)線程只能屬于一個(gè)進(jìn)程揽乱。
  2. 資源分配給的是進(jìn)程,進(jìn)程內(nèi)的線程共享該進(jìn)程的系統(tǒng)資源粟矿。
  3. 處理機(jī)分配個(gè)線程凰棉,即真正在處理機(jī)上運(yùn)行的是線程
  4. 線程在執(zhí)行過程中,需要協(xié)同同步陌粹。進(jìn)程的同步需要通過消息機(jī)制撒犀。線程是進(jìn)程中的一個(gè)執(zhí)行單元,也是進(jìn)程的可調(diào)度實(shí)體掏秩。
  • 區(qū)別:
  1. 調(diào)度: 進(jìn)程是擁有資源的基本單位或舞,線程作為調(diào)度和分配的基本單位。
  2. 并發(fā)性: 進(jìn)程可以并發(fā)蒙幻,進(jìn)程內(nèi)的多個(gè)線程也可以并發(fā)
  3. 擁有資源:進(jìn)程是擁有資源的獨(dú)立單位嚷那,線程不擁有資源,但可以訪問進(jìn)程所擁有的資源杆煞。
  4. 系統(tǒng)開銷:在創(chuàng)建和撤銷進(jìn)程時(shí),由于系統(tǒng)要分配和回收系統(tǒng)資源腐泻,導(dǎo)致明顯大于創(chuàng)建和銷毀線程的開銷决乎。
  • final,finally派桩,finalize的區(qū)別

http://blog.csdn.net/stypace/article/details/42102181

  • final : 修飾符构诚,于類時(shí)類不可被繼承,于變量時(shí)變量不可變铆惑,于方法時(shí)方法不可被重寫范嘱。
  • finally: try catch finally送膳,finally標(biāo)示程序總是會(huì)被執(zhí)行。用于清楚或者釋放資源等丑蛤。這里注意一點(diǎn):try 和 finally有return的執(zhí)行情況叠聋。
  • finalize: object中的方法,在垃圾回收器認(rèn)為該對(duì)象無用受裹,在清理前會(huì)調(diào)用此方法碌补,子類重寫該方法意在做一些回收前的清理工作。
  • 序列化的方式Serializable 和Parcelable 的及區(qū)別

http://blog.csdn.net/Double2hao/article/details/70145747

  • string 轉(zhuǎn)換成 integer的方式及原理
// 會(huì)拋出NumberFormatException異常
public static Integer valueOf(String s) throws NumberFormatException {
        return Integer.valueOf(parseInt(s, 10));
}
public static Integer valueOf(int i) {
       //如果 >-128 && < 127 則直接從緩存中獲取
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
}
/**
     * <p>Examples:
     * <blockquote><pre>
     * parseInt("0", 10) returns 0
     * parseInt("473", 10) returns 473
     * parseInt("+42", 10) returns 42
     * parseInt("-0", 10) returns 0
     * parseInt("-FF", 16) returns -255
     * parseInt("1100110", 2) returns 102
     * parseInt("2147483647", 10) returns 2147483647
     * parseInt("-2147483648", 10) returns -2147483648
     * parseInt("2147483648", 10) throws a NumberFormatException
     * parseInt("99", 8) throws a NumberFormatException
     * parseInt("Kona", 10) throws a NumberFormatException
     * parseInt("Kona", 27) returns 411787
     * </pre></blockquote>
     *
     * @param      s 要轉(zhuǎn)換的字符串
     * @param      radix 進(jìn)制  2  8 10  16  
     * @return
     * @exception  NumberFormatException if the {@code String}
     *             does not contain a parsable {@code int}.
     * 作用是把傳入的字符串s解析單做radix機(jī)制的字串,解析成十進(jìn)制int值照藻。也就是在傳值的時(shí)候要對(duì)應(yīng)好例如不能10的radix傳個(gè)里面有F的
     */
    public static int parseInt(String s, int radix)
            throws NumberFormatException
    {
        //這里有這個(gè)警告是因?yàn)関alueOf方法使用了parseInt方法和IntegerCache對(duì)象袜啃,
        //因?yàn)関alueOf在IntegerCache初始化之前使用導(dǎo)致異常情況。后面會(huì)詳細(xì)分析幸缕。
        //拋空異常
        if (s == null) {
            throw new NumberFormatException("s == null");
        }
        //下面三個(gè)if用來判斷參數(shù)是否合法群发。radix大小在2~36之間。
        if (radix < Character.MIN_RADIX) {
            throw new NumberFormatException("radix " + radix +
                    " less than Character.MIN_RADIX");
        }
        if (radix > Character.MAX_RADIX) {
            throw new NumberFormatException("radix " + radix +
                    " greater than Character.MAX_RADIX");
        }

        int result = 0;//解析結(jié)果
        boolean negative = false;//是否是負(fù)數(shù)
        int i = 0, len = s.length();//索引變量和字符串長(zhǎng)度
        int limit = -Integer.MAX_VALUE;//最值限制
        int multmin;//基數(shù)下的最小值
        int digit; //記錄每一位的數(shù)字

        if (len > 0) {
            //處理第一個(gè)字符
            char firstChar = s.charAt(0);
            if (firstChar < '0') { //非數(shù)字
                if (firstChar == '-') {//開頭為“-”
                    negative = true;//負(fù)數(shù)標(biāo)志為true
                    limit = Integer.MIN_VALUE;//最值為Integer最小值
                } else if (firstChar != '+')//不是“+”號(hào)冀值,直接拋異常
                    throw NumberFormatException.forInputString(s);

                if (len == 1) //非數(shù)字且只有一個(gè)符號(hào)也直接拋異常
                    throw NumberFormatException.forInputString(s);
                i++;
            }
            multmin = limit / radix;
            while (i < len) {
                //利用了Character類中的digit非法也物,作用是解析一個(gè)字符。
                digit = Character.digit(s.charAt(i++),radix);
                //進(jìn)行異常判斷列疗。
                //這個(gè)解析字符串為數(shù)字的算法和平時(shí)想到的不太一樣滑蚯,是從字符串左邊開始,初始化結(jié)果是0抵栈,
                //其實(shí)是把結(jié)果算成負(fù)的告材,返回的時(shí)候再轉(zhuǎn)回來。result -= digit;
                if (digit < 0) {
                    throw NumberFormatException.forInputString(s);
                }
                if (result < multmin) {
                    throw NumberFormatException.forInputString(s);
                }
                //根據(jù)進(jìn)制轉(zhuǎn)為10進(jìn)制數(shù)字
                result *= radix;
                if (result < limit + digit) {
                    throw NumberFormatException.forInputString(s);
                }
                result -= digit;
            }
        } else {
            throw NumberFormatException.forInputString(s);
        }
        return negative ? result : -result;
    }  

java深入源碼級(jí)的面試題(有難度)

  • java虛擬機(jī)基礎(chǔ) GC回收算法

http://blog.csdn.net/tonytfjing/article/details/44278233

  • JVM 結(jié)構(gòu): 類的加載器古劲,運(yùn)行時(shí)數(shù)據(jù)區(qū)[方法區(qū)斥赋、堆、Jvm棧产艾,本地方法棧疤剑,程序計(jì)數(shù)器],執(zhí)行引擎,本地接口闷堡。
  • 內(nèi)存分配:靜態(tài)內(nèi)存隘膘,動(dòng)態(tài)內(nèi)存。JVM機(jī)棧杠览,本地方法弯菊,程序計(jì)數(shù)器隨線程生滅,方法區(qū)和堆與運(yùn)行有關(guān)踱阿。
  • 垃圾檢測(cè): 引用計(jì)數(shù)法管钳,可達(dá)性分析法
  • 回收算法: 標(biāo)記-清除(清除后又大量碎片)钦铁;復(fù)制(復(fù)制移動(dòng),需要額外的內(nèi)存空間) ;標(biāo)記整理(標(biāo)記-清除-壓縮移動(dòng));分代收集算法(不同生命周期的對(duì)象采用不同的回收算法-年輕代(復(fù)制)才漆,年老代(標(biāo)記-整理)牛曹,持久代(管不了))。
  • 類的加載機(jī)制栽烂,雙親委托機(jī)制
  • 類加載器和雙親委托機(jī)制

http://blog.csdn.net/zhangliangzi/article/details/51338291

  • 類相等判定條件:統(tǒng)一個(gè)Class文件躏仇,同一個(gè)虛擬機(jī),同一個(gè)類加載器
  • Java“相等”判定相關(guān)方法:
  1. obj1.equals(obj2):引用是為同一個(gè)實(shí)例對(duì)象
  2. class.isInstance(obj)腺办;obj是否為某個(gè)類焰手,或者子類,子接口的實(shí)例怀喉。
  3. obj instanceof class书妻;實(shí)例對(duì)象是否為某個(gè)類、接口的實(shí)例
  4. class1.isAssignableFrom(class2)躬拢;一個(gè)類是否為另一個(gè)類本身或其子類躲履、子接口
  • 類加載器分類:
  1. Bootstrap ClassLoader:啟動(dòng)類加載器,加載Java核心類庫(kù)聊闯,注意這個(gè)類是C++實(shí)現(xiàn)工猜,不繼承者ClassLoader。加載目錄為%JAVA_HOME%/lib)目錄下的rt.jar
  2. Extension ClassLoader:擴(kuò)展類加載器菱蔬,加載目錄為%JAVA_HOME%/jre/lib/ext)下的jar包
  3. System ClassLoader\APP ClassLoader:CLASSPATH,用戶自定義的類
  4. 以組合關(guān)系復(fù)用父類加載器,非繼承也
  • 雙親委托模型:本質(zhì)基于類的加載器的關(guān)系篷帅,組合成父子。定義上就是要找類先讓父找拴泌,父沒找到再自己找魏身。
  • 哪些情況下的對(duì)象會(huì)被垃圾回收機(jī)制處理掉?
  • 引用計(jì)數(shù)法蚪腐,可達(dá)性分析法決定引用計(jì)數(shù)為0箭昵,或根不可達(dá)
  • 表現(xiàn): 對(duì)象超出了使用空間,即沒有用回季。對(duì)象=null時(shí)
  • 講一下常見編碼方式家制?

https://www.cnblogs.com/yuan1164345228/p/6937958.html
ASCII---GBKXXX---Unicode---UTF-8---UTF-16

  • utf-8編碼中的中文占幾個(gè)字節(jié);int型幾個(gè)字節(jié)泡一?

*占2個(gè)字節(jié)的:帶有附加符號(hào)的拉丁文慰丛、希臘文、西里爾字母瘾杭、亞美尼亞語(yǔ)、希伯來文哪亿、阿拉伯文粥烁、敘利亞文及它拿字母則需要二個(gè)字節(jié)編碼

  • 占3個(gè)字節(jié)的:基本等同于GBK贤笆,含21000多個(gè)漢字
  • 占4個(gè)字節(jié)的:中日韓超大字符集里面的漢字,有5萬多個(gè)
  • 一個(gè)utf8數(shù)字占1個(gè)字節(jié)
  • 一個(gè)utf8英文字母占1個(gè)字節(jié)
  • 少數(shù)是漢字每個(gè)占用3個(gè)字節(jié)讨阻,多數(shù)占用4個(gè)字節(jié)芥永。
  • 靜態(tài)代理和動(dòng)態(tài)代理的區(qū)別,什么場(chǎng)景使用钝吮?

http://blog.csdn.net/ikownyou/article/details/53081426

  • Java的異常體系

http://blog.csdn.net/htq__/article/details/51024881

Java異常體系.png

  • 談?wù)勀銓?duì)解析與分派的認(rèn)識(shí)埋涧。

http://blog.csdn.net/u011080472/article/details/51334288

  • 基本概念:
    Person p = new Man(); Person是靜態(tài)類型,Man是動(dòng)態(tài)類型
    java虛擬機(jī)中提供了5條方法調(diào)用字節(jié)碼指令:
    invokestatic:調(diào)用靜態(tài)方法奇瘦,解析階段確定
    invokeSpecial:調(diào)用實(shí)力構(gòu)造器<init>方法棘催,私有方法和父類方法,解析階段可確定。
    invokevirtual:調(diào)用虛方法
    invokeinterface:調(diào)用接口方法
    invokedynamic:先在運(yùn)行時(shí)動(dòng)態(tài)解析出調(diào)用點(diǎn)限定符所引用的方法耳标,然后再執(zhí)行該方法
    Java中方法調(diào)用的目標(biāo)方法在Class文件里面都是常量池中的符號(hào)引用醇坝,在類加載的解析階段,會(huì)將其中的一部分符號(hào)引用轉(zhuǎn)化為直接引用次坡。
  • 解析:
    “編譯期可知呼猪,運(yùn)行期不可變”的方法調(diào)用稱為解析,解析的方法取決于兩個(gè)指定 invokeStatic 砸琅、invokeSpecial
  • 分派:解析一定是靜態(tài)的過程宋距,分派可能是靜態(tài),也可能是動(dòng)態(tài)症脂。分派是多態(tài)性的體現(xiàn)谚赎。重載為靜態(tài)分派,重寫為動(dòng)態(tài)分派
  • 靜態(tài)分派:所有依賴靜態(tài)類型來定位方法執(zhí)行版本的分派動(dòng)作稱為靜態(tài)分派摊腋,只會(huì)涉及重載,靜態(tài)分派的最直接的解釋是在重載的時(shí)候是通過參數(shù)的靜態(tài)類型作為判斷依據(jù)沸版。
  • 動(dòng)態(tài)分派:直接的例子是重寫(Override),運(yùn)行期根據(jù)方法接收者的實(shí)際類型來選擇方法兴蒸。當(dāng)調(diào)用invokevirtual指令就會(huì)把運(yùn)行時(shí)常量池中符號(hào)引用解析為不同的直接引用视粮,這就是方法重寫的本質(zhì)。invokevirtual指令的工作過程是橙凳,優(yōu)先尋找當(dāng)前類中是否有該方法蕾殴,如有直接選擇該方法,若沒有找到岛啸,則在父類中尋找钓觉,直到找到為止。
  • 修改對(duì)象A的equals方法的簽名坚踩,那么使用HashMap存放這個(gè)對(duì)象實(shí)例的時(shí)候荡灾,會(huì)調(diào)用哪個(gè)equals方法?

?

  • Java中實(shí)現(xiàn)多態(tài)的機(jī)制是什么惑畴?

https://www.cnblogs.com/TalkWithWorld/p/5641169.html
靠的是父類或接口定義的引用變量可以指向子類或具體實(shí)現(xiàn)類的實(shí)例對(duì)象.
重載和重寫

  • 如何將一個(gè)Java對(duì)象序列化到文件里熊昌?

http://blog.csdn.net/leefengboy/article/details/52724019
ObjectOutputStream的writeObject

  • 說說你對(duì)Java反射的理解

http://www.reibang.com/p/5c67db64e192
java反射機(jī)制是在運(yùn)行狀態(tài)中,對(duì)于任意一個(gè)類勿锅,都能夠知道這個(gè)類的所有屬性和方法荧缘;對(duì)于任意一個(gè)對(duì)象皆警,都能夠調(diào)用它的任意一個(gè)方法和屬性;這種動(dòng)態(tài)獲取的信息以及動(dòng)態(tài)調(diào)用對(duì)象的方法的功能稱為java語(yǔ)言的反射機(jī)制截粗。

  • 說說你對(duì)Java注解的理解

http://www.reibang.com/p/5c67db64e192
注解(Annotation)信姓,也叫元數(shù)據(jù)。一種代碼級(jí)別的說明绸罗。它是JDK1.5及以后版本引入的一個(gè)特性意推,與類、接口从诲、枚舉是在同一個(gè)層次左痢。它可以聲明在包、類系洛、字段俊性、方法、局部變量描扯、方法參數(shù)等的前面定页,用來對(duì)這些元素進(jìn)行說明,注釋绽诚。

  • 說說你對(duì)依賴注入的理解
  • 依賴注入(Dependency Injection)和控制反轉(zhuǎn)(Inversion of Control)是同一個(gè)概念典徊。具體含義是:當(dāng)某個(gè)角色(可能是一個(gè)Java實(shí)例,調(diào)用者)需要另一個(gè)角色(另一個(gè)Java實(shí)例恩够,被調(diào)用者)的協(xié)助時(shí)卒落,在 傳統(tǒng)的程序設(shè)計(jì)過程中,通常由調(diào)用者來創(chuàng)建被調(diào)用者的實(shí)例蜂桶。但在Spring里儡毕,創(chuàng)建被調(diào)用者的工作不再由調(diào)用者來完成,因此稱為控制反轉(zhuǎn);創(chuàng)建被調(diào)用者 實(shí)例的工作通常由Spring容器來完成扑媚,然后注入調(diào)用者腰湾,因此也稱為依賴注入。
  • 我們的應(yīng)用更加松耦合疆股、增強(qiáng)擴(kuò)展性以及可維護(hù)性费坊。通過依賴注入我們可以降低從編譯到運(yùn)行時(shí)的依賴性。
  • 說一下泛型原理旬痹,并舉例說明

https://www.cnblogs.com/hq233/p/7227887.html

  • 通過參數(shù)化的方式將數(shù)據(jù)處理與數(shù)據(jù)類型解耦的技術(shù)
  • java泛型的實(shí)現(xiàn)原理是類型擦除附井。Java的泛型是偽泛型讨越。在編譯期間,所有的泛型信息都會(huì)被擦除掉永毅。

Java中的泛型基本上都是在編譯器這個(gè)層次來實(shí)現(xiàn)的谎痢。在生成的Java字節(jié)碼中是不包含泛型中的類型信息的。使用泛型的時(shí)候加上的類型參數(shù)卷雕,會(huì)在編譯器在編譯的時(shí)候去掉。這個(gè)過程就稱為類型擦除票从。

  • 枚舉的理解與注意事項(xiàng)

http://blog.csdn.net/javazejian/article/details/71333103

  • Java中String的了解

https://www.cnblogs.com/xiaoxi/p/6036701.html
final類
char[]
String對(duì)象一旦被創(chuàng)建就是固定不變的了漫雕,對(duì)String對(duì)象的任何改變都不影響到原對(duì)象,相關(guān)的任何change操作都會(huì)生成新的對(duì)象
字符串常量池

  • String為什么要設(shè)計(jì)成不可變的峰鄙?

http://blog.csdn.net/renfufei/article/details/16808775
字符串常量池的需要
允許String對(duì)象緩存HashCode
安全性,String是很多系統(tǒng)類的參數(shù)

數(shù)據(jù)結(jié)構(gòu)

  • 常用數(shù)據(jù)結(jié)構(gòu)簡(jiǎn)介

http://www.reibang.com/p/230e6fde9c75

  • 一浸间、線性表(n個(gè)數(shù)據(jù)元素的有限序列)
    1.數(shù)組實(shí)現(xiàn)(一組連續(xù)的存儲(chǔ)單元,下標(biāo)來訪問或者修改元素,比較高效,插入和刪除的花費(fèi)開銷較大)
    2.鏈表(物理存儲(chǔ)單元上非連續(xù)吟榴、非順序的存儲(chǔ)結(jié)構(gòu),添加或者刪除時(shí)魁蒜,只需要改變相關(guān)節(jié)點(diǎn)的Next的指向,效率很高,訪問效率低)
  • 二吩翻、棧與隊(duì)列
    1.棧(插入刪除只能在棧頂兜看,LIFO(Last In First Out)表,即后進(jìn)先出狭瞎。)
    2.隊(duì)列(只允許在表的前端(front)進(jìn)行刪除操作细移,而在表的后端(rear)進(jìn)行插入操作,FIFO)
  • 三、樹與二叉樹
    1.樹(由n(n>=1)個(gè)有限節(jié)點(diǎn)組成一個(gè)具有層次關(guān)系的集合)
    2.二叉樹基本概念(每個(gè)節(jié)點(diǎn)最多有兩棵子樹的樹結(jié)構(gòu),滿二叉樹熊锭,完全二叉樹弧轧,非完全二叉樹;根節(jié)點(diǎn)碗殷、左子樹和右子樹精绎;先序遍歷(ABC)、中序遍歷(BAC)和后續(xù)遍歷(BCA))
    3.二叉查找樹(左<根 右>根)
    4.平衡二叉樹(它的左子樹和右子樹都是平衡二叉樹锌妻,且左子樹和右子樹的深度之差的絕對(duì)值不超過1)
    5.紅黑樹
  • 四代乃、圖(復(fù)雜)
  • 并發(fā)集合了解哪些?
  • AtomicInteger, AtomicBoolean, AtomicLong, AtomicReference
    sun.misc.Unsafe
    boolean compareAndSet(expectedValue, updateValue);
    public boolean compareAndSet(
    ? ? V expectedReference,//預(yù)期引用
    ? ? V newReference,//更新后的引用
    ? ? int expectedStamp, //預(yù)期標(biāo)志
    ? ? int newStamp) //更新后的標(biāo)志
  • ArrayBlockingQueue
    一個(gè)由數(shù)組支持的有界阻塞隊(duì)列从祝。此隊(duì)列按 FIFO(先進(jìn)先出)原則對(duì)元素進(jìn)行排序襟己。有界緩存區(qū),試圖向已滿隊(duì)列中放入元素會(huì)導(dǎo)致操作受阻塞;試圖從空隊(duì)列中提取元素將導(dǎo)致類似阻塞牍陌。只使用了一個(gè)lock來控制互斥訪問
public void put(E e) throws InterruptedException {
        Objects.requireNonNull(e);
        final ReentrantLock lock = this.lock;
        lock.lockInterruptibly();
        try {
            while (count == items.length)
                notFull.await();
            enqueue(e);
        } finally {
            lock.unlock();
        }
    }
  • LinkedBlockingQueue
    一個(gè)基于已鏈接節(jié)點(diǎn)的擎浴、范圍任意的blocking queue。
    LinkedBlockingQueue使用了2個(gè)lock毒涧,一個(gè)takelock和一個(gè)putlock贮预,讀和寫用不同的lock來控制,這樣并發(fā)效率更高。
  • ConcurrentLinkedQueue
    使用CAS來實(shí)現(xiàn)仿吞,是非阻塞式的“l(fā)ock-free”實(shí)現(xiàn)
  • ConcurrentHashMap
    jdk1.6采用了Segment分段技術(shù)滑频,容器里有多把鎖,每把鎖用于鎖容器其中一部分?jǐn)?shù)據(jù)唤冈,那么當(dāng)多線程訪問容器里不同數(shù)據(jù)段的數(shù)據(jù)時(shí)峡迷,線程間就不會(huì)存在鎖競(jìng)爭(zhēng),從而可以有效的提高并發(fā)訪問效率你虹。
    由Segment數(shù)組結(jié)構(gòu)和HashEntry數(shù)組結(jié)構(gòu)組成
    jdk1.8采用CAS+數(shù)組绘搞,鏈表,紅黑樹
  • CopyOnWriteArrayList
    寫時(shí)復(fù)制的容器.一種讀寫分離的思想傅物,讀和寫不同的容器夯辖。寫時(shí)加鎖,讀時(shí)讀的是之前的董饰,不需要加鎖
public boolean add(T e) {
    final ReentrantLock lock = this.lock;
    lock.lock();
    try {
        Object[] elements = getArray();
        int len = elements.length;
        // 復(fù)制出新數(shù)組
        Object[] newElements = Arrays.copyOf(elements, len + 1);
        // 把新元素添加到新數(shù)組里
        newElements[len] = e;
        // 把原數(shù)組引用指向新數(shù)組
        setArray(newElements);
        return true;
    } finally {
        lock.unlock();
    }
}
  • AbstractQueuedSynchronizer
    為實(shí)現(xiàn)依賴于先進(jìn)先出 (FIFO) 等待隊(duì)列的阻塞鎖和相關(guān)同步器(信號(hào)量蒿褂、事件,等等)提供一個(gè)框架卒暂。
  • 列舉java的集合以及集合之間的繼承關(guān)系

http://alexyyek.github.io/2015/04/06/Collection/

  • Collection
    public interface Collection<E> extends Iterable<E> {}
  • List
    public interface List<E> extends Collection<E> {}
    List是有序的隊(duì)列啄栓,List中的每一個(gè)元素都有一個(gè)索引;允許重復(fù)
    實(shí)現(xiàn)List接口的集合主要有:ArrayList、LinkedList介却、Vector谴供、Stack。
  • ArrayList
    public class ArrayList<E> extends AbstractList<E>
    implements List<E>, RandomAccess, Cloneable, java.io.Serializable
    private static final int DEFAULT_CAPACITY = 10;//初始容量齿坷,隨著容器中的元素不斷增加桂肌,容器的大小也會(huì)隨著增加
    transient Object[] elementData;//數(shù)組
    RandomAccess 用來表明其支持快速(通常是固定時(shí)間)隨機(jī)訪問,適合for循環(huán)而不適合迭代器方法
    ArrayList的操作是固定時(shí)間
  • LinkedList
    public class LinkedList<E> extends AbstractSequentialList<E>
    implements List<E>, Deque<E>, Cloneable, java.io.Serializable
    transient Node<E> first;//LinkedList是一個(gè)雙向鏈表
    transient Node<E> last;
  • Vector
    和ArrayList類似永淌,只是線程安全的崎场,提供的是synchronized方法
  • Stack
    public class Stack<E> extends Vector<E> {}
    Stack繼承自Vector,實(shí)現(xiàn)一個(gè)后進(jìn)先出的堆棧
  • Set
    public interface Set<E> extends Collection<E> {}
    是一種不包括重復(fù)元素的Collection,
    該接口定義了 boolean equals(Object o);方法
    實(shí)現(xiàn)類:HashSet遂蛀、TreeSet谭跨、LinkedHashSet、EnumSet李滴。
  • HashSet
    public class HashSet<E> extends AbstractSet<E>
    implements Set<E>, Cloneable, java.io.Serializable
    查詢速度最快的集合,內(nèi)部是以HashCode來實(shí)現(xiàn)的
    內(nèi)部 private transient HashMap<E,Object> map;
    可以放null螃宙,因?yàn)閔ash方法null時(shí)會(huì)為0。
    add方法:
    public boolean add(E e) {
    ? ? return map.put(e, PRESENT)==null;
    }
    public V put(K key, V value) {
    ? ? return putVal(hash(key), key, value, false, true);
    }
  • TreeSet
    public class TreeSet<E> extends AbstractSet<E>
    implements NavigableSet<E>, Cloneable, java.io.Serializable
    private transient NavigableMap<E,Object> m;
    public TreeSet() {//默認(rèn)是TreeMap實(shí)現(xiàn)
    ? ? this(new TreeMap<E,Object>());
    }
    二叉樹實(shí)現(xiàn)的所坯,生成一個(gè)總是處于排序狀態(tài)的set
    不允許放入null
    提供的 Comparator 進(jìn)行排序
  • LinkedHashSet
    public class LinkedHashSet<E> extends HashSet<E>
    implements Set<E>, Cloneable, java.io.Serializable
    同時(shí)使用鏈表維護(hù)元素的次序
    //基于的是LinkedHashMap
    HashSet(int initialCapacity, float loadFactor, boolean dummy) {
    ? ? map = new LinkedHashMap<>(initialCapacity, loadFactor);
    }
  • EnumSet
    final Enum<?>[] universe;
    所有值都必須是指定枚舉類型的值
    枚舉類的定義順序來決定集合元素的順序
    通過它提供的static方法來創(chuàng)建EnumSet對(duì)象
  • Map
    說一個(gè)key對(duì)應(yīng)一個(gè)value谆扎,所以它不能存在相同的key值
    HashMap、HashTable芹助、TreeMap堂湖、WeakHashMap等實(shí)現(xiàn)類
  • HashMap
    public class HashMap<K,V> extends AbstractMap<K,V>
    implements Map<K,V>, Cloneable, Serializable
    查找對(duì)象時(shí)通過哈希函數(shù)計(jì)算其位置
    transient Node<K,V>[] table; hash表數(shù)組
    如果有沖突闲先,則使用散列鏈表
  • HashTable
    public class Hashtable<K,V> extends Dictionary<K,V>
    implements Map<K,V>, Cloneable, java.io.Serializable
    Dictionary類是任何可將鍵映射到相應(yīng)值的類(如 Hashtable)的抽象父類
    “拉鏈法”比HashMap性能低
    synchronized方法 線程安全
  • TreeMap
    public class TreeMap<K,V> extends AbstractMap<K,V>
    implements NavigableMap<K,V>, Cloneable, java.io.Serializable
    有序散列表,實(shí)現(xiàn)SortedMap接口无蜂,底層通過紅黑樹實(shí)現(xiàn)伺糠。
  • WeakHashMap
    public class WeakHashMap<K,V> extends AbstractMap<K,V>
    implements Map<K,V>
    null值和null鍵都被支持
    弱鍵可被終止
  • Iterator
    Iterator遍歷Collection時(shí),是fail-fast機(jī)制的斥季。拋出ConcurrentModificationException異常
  • Arrays和Collections

http://blog.csdn.net/excellentyuxiao/article/details/52344594

  • Collections:一個(gè)工具類训桶。它包含各種有關(guān)集合操作的靜態(tài)多態(tài)方法
    • 空集合:返回只讀空集合
      Collections.emptyList();emptyMap();emptySet()
    • 單元素集合(只讀)
      Collections.singletonList();singletonMap();singleton();
    • 只讀集合,硬改拋UnsupportedOperationException
      unmodifiableXXX(XXX s)
    • Checked集合,具有檢查插入集合元素類型的特性
      checkedXXX(XXX<E> s, Class<E> type)
    • 同步集合,內(nèi)部通過synchronized (mutex)實(shí)現(xiàn)
      synchnorizedXXX(XXX s)
    • 替換:把所有內(nèi)容替換為obj
      fill(List<? super T> list, T obj)
    • 查找
      1. frequency(Collection<?> c, Object o)返回指定 collection 中等于指定對(duì)象的元素?cái)?shù),為null的時(shí)候用==判斷酣倾,否則用equals(Object中equals也是用的==判斷)
      2. indexOfSubList(List<?> source, List<?> target)/lastIndexOfSubList:返回指定源列表中第一次(最后一次)出現(xiàn)指定目標(biāo)列表的起始位置渊迁,如果沒有出現(xiàn)這樣的列表,則返回 -1灶挟。
      3. max/min(Collection<? extends T> coll, Comparator<? super T> comp):返回給定 collection 的最大/小元素
      4. replaceAll(List<T> list, T oldVal, T newVal):使用另一個(gè)值替換列表中出現(xiàn)的所有某一指定值。
    • 排序
      1. reverse(List<?> list):對(duì)List中的元素倒序排列
      2. shuffle:基于Random的隨機(jī)排序
      3. sort:java8中List接口使用default關(guān)鍵字實(shí)現(xiàn)了sort方法
      4. swap(List<?> list, int i, int j):交換List中某兩個(gè)指定下標(biāo)位元素在集合中的位置
      5. rotate(List<?> list, int distance):循環(huán)滾動(dòng)毒租,[t, a, b, k, s] --->rotate(list,1)==>[s稚铣,t,a墅垮,b惕医,k]
  • Arrays
    1. fill:給數(shù)組賦值
    2. sort:排序
    3. copyOf——復(fù)制數(shù)組:其實(shí)理解為集合擴(kuò)容即可
    4. equals
    5. binarySearch:核心binarySearch0(byte[] a, int fromIndex, int toIndex,byte key),二分查找算法
  • List,Set,Map的區(qū)別

https://www.cnblogs.com/grayworm/p/6235657.html

  • List的特征是其元素以線性方式存儲(chǔ)算色,集合中可以存放重復(fù)對(duì)象
  • 集合中的對(duì)象不按特定的方式排序抬伺,并且沒有重復(fù)對(duì)象
  • Map 是一種把鍵對(duì)象和值對(duì)象映射的集合,它的每一個(gè)元素都包含一對(duì)鍵對(duì)象和值對(duì)象灾梦。 Map沒有繼承于Collection接口 從Map集合中檢索元素時(shí)峡钓,只要給出鍵對(duì)象,就會(huì)返回對(duì)應(yīng)的值對(duì)象若河。
  • HashMap理解

http://www.importnew.com/7099.html

  • 實(shí)現(xiàn)原理


    1520949407329.jpg

    基于哈希表的Map接口的非同步實(shí)現(xiàn)

    • 數(shù)據(jù)結(jié)構(gòu)
      鏈表散列的數(shù)據(jù)結(jié)構(gòu)即鏈表(或紅黑樹(jdk>1.8時(shí)))+數(shù)組
      transient Entry[] table;
      static class Node<K,V> implements Map.Entry<K,V> {
        final int hash;//用于定位數(shù)組索引的位置
        final K key;
        V value;
        Node<K,V> next;//鏈表的下一個(gè)Node
       ……
      }
      
    • 基本參數(shù)
      int threshold;// 所能容納的key-value對(duì)極限能岩,超過要resize(擴(kuò)容)
      final float loadFactor; // 負(fù)載因子 默認(rèn)0.75
      int modCount;  //結(jié)構(gòu)變化的次數(shù)
      int size;  // 實(shí)際存在的鍵值對(duì)數(shù)量,和length不一樣
      threshold = length * loadFactor
      //table的長(zhǎng)度length大小必須為2的n次方,為了好高位運(yùn)算
      
    • 確定哈希桶數(shù)組索引位置(速度快萧福,效率高的算法)
      static final int hash(Object key) {
              int h;
              //取hashCode值  +  高位運(yùn)算
              return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
       }
      //取模
      tab[i = (n - 1) & hash])---i = (n-1)&hash
      
    • 存儲(chǔ)
      對(duì)key的hashCode()做hash拉鹃,然后再計(jì)算index;
      如果沒碰撞直接放到bucket里;
      如果碰撞了鲫忍,以鏈表的形式存在buckets后膏燕;
      如果碰撞導(dǎo)致鏈表過長(zhǎng)(大于等于TREEIFY_THRESHOLD),就把鏈表轉(zhuǎn)換成紅黑樹悟民;
      如果節(jié)點(diǎn)已經(jīng)存在就替換old value(保證key的唯一性)
      如果bucket滿了(超過load factor*current capacity)坝辫,就要resize
      final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
                         boolean evict) {
              Node<K,V>[] tab; Node<K,V> p; int n, i;
             //判斷table是否為空,
              if ((tab = table) == null || (n = tab.length) == 0)
                  //創(chuàng)建一個(gè)新的table數(shù)組逾雄,并且獲取該數(shù)組的長(zhǎng)度
                  n = (tab = resize()).length;
              if ((p = tab[i = (n - 1) & hash]) == null)//取模得tab索引
                  tab[i] = newNode(hash, key, value, null);//放入
              else {//table不為空
                  Node<K,V> e; K k;
                  //如果key完全相等
                  if (p.hash == hash &&
                      ((k = p.key) == key || (key != null && key.equals(k))))
                      e = p;//替換Value,保證了完全相等的key不存在重復(fù)值
                  else if (p instanceof TreeNode)//如果是紅黑樹阀溶,鏈表長(zhǎng)>8
                      e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, >        key, value);//直接放入
                  else {//是鏈表
                      for (int binCount = 0; ; ++binCount) {
                          if ((e = p.next) == null) {
                              p.next = newNode(hash, key, value, null);
                              if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st長(zhǎng)度>8轉(zhuǎn)為紅黑樹
                                  treeifyBin(tab, hash);
                              break;
                          }
                          if (e.hash == hash &&
                              ((k = e.key) == key || (key != null && key.equals(k))))//完全相等腻脏,不管
                              break;
                          p = e;
                      }
                  }
                  //寫入
                  if (e != null) { // existing mapping for key
                      V oldValue = e.value;
                      if (!onlyIfAbsent || oldValue == null)
                          e.value = value;
                      afterNodeAccess(e);
                      return oldValue;
                  }
              }
            ++modCount;
            if (++size > threshold)//插入成功后,判斷實(shí)際存在的鍵值對(duì)數(shù)量size是否超多了最大容量threshold
                resize();//擴(kuò)容
            afterNodeInsertion(evict);
            return null;
        }
      
    • 獲取
      1. bucket里的第一個(gè)節(jié)點(diǎn)银锻,直接命中永品;
      2. 如果有沖突,則通過key.equals(k)去查找對(duì)應(yīng)的entry
        若為樹击纬,則在樹中通過key.equals(k)查找鼎姐,O(logn);
        若為鏈表更振,則在鏈表中通過key.equals(k)查找炕桨,O(n)。
      final Node<K,V> getNode(int hash, Object key) {
              Node<K,V>[] tab; Node<K,V> first, e; int n; K k;
              if ((tab = table) != null && (n = tab.length) > 0 &&
                  (first = tab[(n - 1) & hash]) != null) {//目標(biāo)索引直接找到也就是該桶的第一個(gè)節(jié)點(diǎn)
                  if (first.hash == hash && 
                      ((k = first.key) == key || (key != null && key.equals(k))))//完全相等
                      return first;
                  if ((e = first.next) != null) {//找下一個(gè)節(jié)點(diǎn)
                      if (first instanceof TreeNode)//如果是紅黑樹
                          return ((TreeNode<K,V>)first).getTreeNode(hash, key);//在樹中找
                      do {//在鏈表中找
                          if (e.hash == hash &&
                              ((k = e.key) == key || (key != null && key.equals(k))))
                              return e;
                      } while ((e = e.next) != null);
                  }
              }
              return null;
      }
      
    • 擴(kuò)容
      JKD1.7 擴(kuò)容后會(huì)倒置肯腕,JDK1.8不會(huì)献宫,JDK1.8源碼如下
      final Node<K,V>[] resize() {
              Node<K,V>[] oldTab = table;//老Table引用
              int oldCap = (oldTab == null) ? 0 : oldTab.length;//原length
              int oldThr = threshold;//原容量
              int newCap, newThr = 0;//定義新長(zhǎng)度和容量
              if (oldCap > 0) {//原來長(zhǎng)度大于0
                  if (oldCap >= MAXIMUM_CAPACITY) {//如果原容量>2的30次方
                      threshold = Integer.MAX_VALUE;
                      return oldTab;//不擴(kuò)了
                  }
                  else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY &&
                           oldCap >= DEFAULT_INITIAL_CAPACITY)//擴(kuò)兩倍長(zhǎng)度
                      newThr = oldThr << 1; //擴(kuò)兩倍容量
              }
              else if (oldThr > 0) //如果原長(zhǎng)度==0且原容量大于0
                  newCap = oldThr;//新長(zhǎng)度等于原容量
              else {// 如果原來長(zhǎng)度和容量全是0
                  newCap = DEFAULT_INITIAL_CAPACITY;//默認(rèn)值長(zhǎng)度16
                  newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);//默認(rèn)容量=0.75*16=12
              }
              if (newThr == 0) {//新容量還是0
                  float ft = (float)newCap * loadFactor;//計(jì)算長(zhǎng)度
                  newThr = (newCap < MAXIMUM_CAPACITY && ft < (float)MAXIMUM_CAPACITY ?
                            (int)ft : Integer.MAX_VALUE);//不超過2^30容量為新計(jì)算的長(zhǎng)度
              }
              threshold = newThr;//更新當(dāng)前的容量
              @SuppressWarnings({"rawtypes","unchecked"})
                  Node<K,V>[] newTab = (Node<K,V>[])new Node[newCap];//創(chuàng)建新長(zhǎng)度的table數(shù)組
              table = newTab;//更新當(dāng)前的數(shù)組為新數(shù)組
              if (oldTab != null) {
                  for (int j = 0; j < oldCap; ++j) {//遍歷老數(shù)組
                      Node<K,V> e;
                      if ((e = oldTab[j]) != null) {//老的Node先拿出來
                          oldTab[j] = null;//將老數(shù)組此處的引用清除
                          if (e.next == null)//鏈表只有一個(gè)值,即沒有碰撞
                              //沒有重新計(jì)算HashCode,且位置不變
                              newTab[e.hash & (newCap - 1)] = e;
                          else if (e instanceof TreeNode)//如果是紅黑樹則split
                              ((TreeNode<K,V>)e).split(this, newTab, j, oldCap);
                          else { // 普通鏈表的時(shí)候
                              Node<K,V> loHead = null, loTail = null;
                              Node<K,V> hiHead = null, hiTail = null;
                              Node<K,V> next;
                              do {//遍歷此桶下的鏈表
                                  next = e.next;
                                  if ((e.hash & oldCap) == 0) {//原索引
                                      if (loTail == null)
                                          loHead = e;
                                      else
                                          loTail.next = e;
                                      loTail = e;
                                  }
                                  else {//新索引
                                      if (hiTail == null)
                                          hiHead = e;
                                      else
                                          hiTail.next = e;
                                      hiTail = e;
                                  }
                              } while ((e = next) != null);
                              if (loTail != null) {//放到原索引位置
                                  loTail.next = null;
                                  newTab[j] = loHead;
                              }
                              if (hiTail != null) {//放到原索引+oldCap的位置
                                  hiTail.next = null;
                                  newTab[j + oldCap] = hiHead;
                              }
                          }
                      }
                  }
              }
              return newTab;
          }
      
  • CAS

http://blog.csdn.net/ls5718/article/details/52563959

  • 鎖之不足:
    1. 頻繁獲取釋放鎖实撒,開銷大姊途,有延時(shí),性能低
    2. 得不到鎖的現(xiàn)成會(huì)掛起知态,浪費(fèi)
    3. 低優(yōu)先級(jí)擁有鎖捷兰,高優(yōu)先級(jí)也白費(fèi),優(yōu)先級(jí)錯(cuò)亂
  • CAS理解
    1. compare and swap 比較替換负敏;核心方法compareAndSwapXXX
    2. 三大元素V的地址贡茅,預(yù)期原值A(chǔ),新值B
    3. V地址的值=預(yù)期原值其做,在V地址更新為B值
    4. 是一種樂觀鎖機(jī)制顶考,synchnorized是悲觀鎖
    5. 基于Cpu的CAS指令,借助JNI完成一種非阻塞算法
    6. CAS 的指令允許算法執(zhí)行讀-修改-寫操作妖泄,而無需害怕其他線程同時(shí) 修改變量村怪,因?yàn)槿绻渌€程修改變量,那么 CAS 會(huì)檢測(cè)它(并失敻÷)甚负,算法 可以對(duì)該操作重新計(jì)算。
  • CAS問題
    1. ABA問題--1A2B3A
    2. 循環(huán)開銷大--pause指令
    3. 只能保證一個(gè)共享變量--多變量合并成一個(gè)
  • CAS應(yīng)用
    1. atomic包 AtomicReference組合原子變量
    2. concurrent包: volatile + CAS
  • ConcurrentHashMap的實(shí)現(xiàn)原理

http://blog.csdn.net/fjse51/article/details/55260493

  • 來源因素
    1. HashMap 非同步审残,put擴(kuò)容由于競(jìng)爭(zhēng)可能會(huì)導(dǎo)致死鏈
    2. HashTable雖同步梭域,但是用的是synchronized屬于悲觀鎖,性能較差
    3. jdk1.6采用鎖分段技術(shù)搅轿,但是jdk1.8已經(jīng)放棄病涨,采用CAS加數(shù)組,鏈表璧坟,紅黑樹既穆,性能更好
  • jdk1.6實(shí)現(xiàn)核心
    分段鎖的機(jī)制,Segment數(shù)組和HashEntry數(shù)組組成,Segment繼承ReentrantLock用來充當(dāng)鎖的角色,個(gè) Segment 對(duì)象守護(hù)每個(gè)散列映射表的若干個(gè)桶.
  • jdk1.8實(shí)現(xiàn)核心
    1. 采用volatile變量保證可見性赎懦,通過CAS維護(hù)這些變量重要屬性如下
      transient volatile Node<K,V>[] table;//桶數(shù)組
      private transient volatile Node<K,V>[] nextTable;
      private transient volatile long baseCount;//Updated via CAS
      private transient volatile int sizeCtl;
      static class Node<K,V> implements Map.Entry<K,V> {
              final int hash;
              final K key;
              volatile V val;
              volatile Node<K,V> next;
      ...
      }
      static final <K,V> boolean casTabAt(Node<K,V>[] tab, int i,
                                              Node<K,V> c, Node<K,V> v) {
              return U.compareAndSwapObject(tab, ((long)i << ASHIFT) + ABASE, c, v);
          }
      
    2. 存儲(chǔ)時(shí)以桶為鎖,進(jìn)一步提高并發(fā)行
      // 針對(duì)首個(gè)節(jié)點(diǎn)進(jìn)行加鎖操作幻工,而不是segment励两,進(jìn)一步減少線程沖突
                  synchronized (f) {
                  }
      
    3. 讀取時(shí)通過CAS讀取
    e = tabAt(tab, (n - 1) & h)) != null
    static final <K,V> Node<K,V> tabAt(Node<K,V>[] tab, int i) {
        return (Node<K,V>)U.getObjectVolatile(tab, ((long)i << ASHIFT) + ABASE);
    }
    
  • SparseArray

http://blog.csdn.net/abcdef314159/article/details/51679494

private static final Object DELETED = new Object();
private int[] mKeys;//Key以數(shù)組存儲(chǔ),key為int
private Object[] mValues;//Value以數(shù)組存儲(chǔ)
public void put(int key, E value) {
        //二分法查找key的位置囊颅,這就決定mKeys數(shù)組是有序遞增的
        int i = ContainerHelpers.binarySearch(mKeys, mSize, key);

        if (i >= 0) {//如果該位置有值当悔,直接替換
            mValues[i] = value;
        } else {
            i = ~i;//如果沒有二分法會(huì)返回key的大臨界值的位置的取反,這里再取反就是小臨界值的位置踢代,如-4取反是3

            if (i < mSize && mValues[i] == DELETED) {//如果這個(gè)值被刪了盲憎,則將key放到該位置
                mKeys[i] = key;
                mValues[i] = value;
                return;
            }

            if (mGarbage && mSize >= mKeys.length) {
                gc();//重排,把刪除了的去掉胳挎,然后其后面的前移

                // 位置變化重新二分法查找
                i = ~ContainerHelpers.binarySearch(mKeys, mSize, key);
            }
            //放入
            mKeys = GrowingArrayUtils.insert(mKeys, mSize, i, key);
            mValues = GrowingArrayUtils.insert(mValues, mSize, i, value);
           //大小加1
            mSize++;
        }
    }
private void gc() {
        // Log.e("SparseArray", "gc start with " + mSize);

        int n = mSize;
        int o = 0;
        int[] keys = mKeys;
       Object[] values = mValues;

        for (int i = 0; i < n; i++) {
            Object val = values[i];

            if (val != DELETED) {//該位置已經(jīng)被刪除的話就釋放
                if (i != o) {
                    keys[o] = keys[i];
                    values[o] = val;
                    values[i] = null;
                }

                o++;
            }
        }

        mGarbage = false;
        mSize = o;//回收后的大小

        // Log.e("SparseArray", "gc end with " + mSize);
    }
public E get(int key, E valueIfKeyNotFound) {
        int i = ContainerHelpers.binarySearch(mKeys, mSize, key);//二分法找位置

        if (i < 0 || mValues[i] == DELETED) {
            return valueIfKeyNotFound;
        } else {
            return (E) mValues[i];
        }
    }
public void delete(int key) {
        int i = ContainerHelpers.binarySearch(mKeys, mSize, key);

        if (i >= 0) {
            if (mValues[i] != DELETED) {
                mValues[i] = DELETED;
                mGarbage = true;
            }
        }
    }
  • ArrayMap

http://blog.csdn.net/abcdef314159/article/details/51683093
一個(gè)數(shù)組存儲(chǔ)的是Hash值另一個(gè)數(shù)組存儲(chǔ)的是key和value饼疙,其中key和value是成對(duì)出現(xiàn)的,key存儲(chǔ)在數(shù)組的偶數(shù)位上慕爬,value存儲(chǔ)在數(shù)組的奇數(shù)位上

mHashes[index] = hash;
mArray[index<<1] = key;
mArray[(index<<1)+1] = value;

只有hash值相同并且key也相同才會(huì)返回所在的位置

  • HashTable實(shí)現(xiàn)原理

http://blog.csdn.net/jinhuoxingkong/article/details/52022999
線程安全的宏多,key和value是不允許為空的

  • Hashtable和HashMap區(qū)別

(1)基類不同:HashTable基于Dictionary類,而HashMap是基于AbstractMap澡罚。Dictionary是什么?它是任何可將鍵映射到相應(yīng)值的類的抽象父類肾请,而AbstractMap是基于Map接口的骨干實(shí)現(xiàn)留搔,它以最大限度地減少實(shí)現(xiàn)此接口所需的工作。
(2)null不同:HashMap可以允許存在一個(gè)為null的key和任意個(gè)為null的value铛铁,但是HashTable中的key和value都不允許為null隔显。
(3)線程安全:HashMap時(shí)單線程安全的,Hashtable是多線程安全的饵逐。
(4)遍歷不同:HashMap僅支持Iterator的遍歷方式括眠,Hashtable支持Iterator和Enumeration兩種遍歷方式。

  • TreeMap具體實(shí)現(xiàn)

http://blog.csdn.net/qq_32166627/article/details/72773293
基于紅黑樹(Red-Black tree)的 NavigableMap實(shí)現(xiàn)
可排序(自然排序倍权,Comparator-(實(shí)現(xiàn)Comparable接口的實(shí)體或自定義實(shí)現(xiàn)Comparator接口的類))

public class TreeMap<K,V>
    extends AbstractMap<K,V>
    implements NavigableMap<K,V>, Cloneable, java.io.Serializable
  • HashMap與HashSet的區(qū)別
hashmap與hashset區(qū)別.jpg
  • HashSet與HashMap怎么判斷集合元素重復(fù)掷豺?
f (p.hash == hash &&
                ((k = p.key) == key || (key != null && key.equals(k))))
                e = p;
  • 集合Set實(shí)現(xiàn)Hash怎么防止碰撞

如果hash碼值不相同,說明是一個(gè)新元素薄声,存当船;
如果hash碼值相同,且equles判斷相等默辨,說明元素已經(jīng)存在德频,替換
如果hash碼值相同,且equles判斷不相等缩幸,說明元素不存在壹置,存竞思;

  • ArrayList和LinkedList的區(qū)別,以及應(yīng)用場(chǎng)景
  • 數(shù)組--雙鏈表
  • 數(shù)組結(jié)構(gòu)在通過索引進(jìn)行查詢數(shù)據(jù)時(shí)效率比較高
  • 保證數(shù)據(jù)插入和刪除钞护,不會(huì)影響其他數(shù)據(jù)的移動(dòng)盖喷,保證線性開銷
  • 二叉樹的深度優(yōu)先遍歷和廣度優(yōu)先遍歷的具體實(shí)現(xiàn)
package gjg.com.fundemo.javatest;

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Queue;

/**
 * @author : gaojigong
 * @date : 2018/3/15
 * @description:
 */


public class TreeNodeDemo {
    public static class TreeNode{
        String value;
        TreeNode left;
        TreeNode right;

        public TreeNode(String value) {
            this.value = value;
        }
    }

    public static class TreeNodeMethod{
        /**
         * 遞歸方式創(chuàng)建二叉樹
         * @param array 中序數(shù)組
         * @param index
         * @return
         */
        public static TreeNode makeTreeNodeRootByArray(String[] array,int index){
            if(array == null || array.length == 0){
                return null;
            }
            if(index < array.length){
                //獲取索引出的數(shù)組值
                String value = array[index];
                if(null != value){
                    TreeNode t = new TreeNode(value);
                    //清除數(shù)組次位置的引用
                    array[index] = null;
                    //創(chuàng)建左子樹
                    t.left = makeTreeNodeRootByArray(array,index * 2);
                    t.right = makeTreeNodeRootByArray(array,index * 2 + 1);
                    return t;
                }
            }
            return null;
        }

        /**
         * 深度優(yōu)先遍歷
         * 非遞歸
         * 借助棧  先進(jìn)后出
         * @param root
         */
        public static List<String> depthOrderTraversal(TreeNode root){
            if(root == null){
                return null;
            }
            List<String> result = new ArrayList<>();
            ArrayDeque<TreeNode> stack = new ArrayDeque<>();
            stack.push(root);//入棧
            while (!stack.isEmpty()){
                //出棧
                TreeNode t = stack.pop();
                result.add(t.value);
                if(t.right != null){
                    stack.push(t.right);
                }
                if(t.left != null){
                    stack.push(t.left);
                }
            }
            return result;
        }

        /**
         * 廣度優(yōu)先遍歷
         * 利用隊(duì)列  先進(jìn)先出
         * @param root
         * @return
         */
        public static List<String> levelOrderTraversal(TreeNode root){
            if (root == null){
                return null;
            }
            List<String> result = new ArrayList<>();
            ArrayDeque<TreeNode> queue = new ArrayDeque<>();
            queue.add(root);
            while (!queue.isEmpty()){
                TreeNode t = queue.remove();
                result.add(t.value);
                if(t.left != null){
                    queue.add(t.left);
                }
                if(t.right != null){
                    queue.add(t.right);
                }
            }
            return result;
        }

        /**
         * 遞歸獲取最大深度
         * @param root
         * @return
         */
        public static int getMaxDepth(TreeNode root){
            if(root == null){
                return 0;
            }
            int left = getMaxDepth(root.left);
            int right = getMaxDepth(root.right);
            return 1 + Math.max(left,right);
        }

        /**
         * 獲取最大寬度
         * 基于隊(duì)列
         * @param root
         * @return
         */
        public static int getMaxWidth(TreeNode root){
            if(root == null){
                return 0;
            }
            Queue<TreeNode> queue = new ArrayDeque<>();
            queue.add(root);
            int maxWidth = 1;//最大寬度
            while (true){
                int len = queue.size();
                if(len == 0){
                    //隊(duì)列處理完
                    break;
                }
                while (len > 0){
                    //當(dāng)層節(jié)點(diǎn)還有子節(jié)點(diǎn)
                    TreeNode t = queue.poll();
                    len--;//處理了一個(gè)節(jié)點(diǎn)
                    //當(dāng)前的子節(jié)點(diǎn)加入隊(duì)列
                    if(t.left != null){
                        queue.add(t.left);
                    }
                    if(t.right != null){
                        queue.add(t.right);
                    }
                }
                maxWidth = Math.max(maxWidth,queue.size());
            }
            return maxWidth;
        }
    }
}
  • 堆的結(jié)構(gòu)

堆是一種經(jīng)過排序的樹形數(shù)據(jù)結(jié)構(gòu),每個(gè)節(jié)點(diǎn)都有一個(gè)值
根結(jié)點(diǎn)的值最谢家凇(或最大),且根結(jié)點(diǎn)的兩個(gè)子樹也是一個(gè)堆

  • 堆和棧在內(nèi)存中的區(qū)別是什么(解答提示:可以從數(shù)據(jù)結(jié)構(gòu)方面以及實(shí)際實(shí)現(xiàn)方面兩個(gè)方面去回答)传蹈?

http://blog.csdn.net/Fiorna0314/article/details/49757195
申請(qǐng)方式和回收方式不同(棧自動(dòng)分收,堆自己申放)
棧想去飯店吃飯步藕,只點(diǎn)菜自會(huì)上菜惦界,堆想自己下廚自己做

  • 什么是深拷貝和淺拷貝

http://blog.csdn.net/lcg910978041/article/details/51992614
復(fù)制對(duì)象(深),復(fù)制引用(淺)
clone Clonable

  • 手寫鏈表逆序代碼
public class NodeReverse {
    public static class Node{
        String value;
        Node next;
    }
    public static Node reverse(Node head){
        //如果鏈表中只有一個(gè)直接返回原來的
        if(head == null || head.next == null || head.next.next == null){
            return head;
        }
        Node p = head.next;//拿出引用
        Node q = head.next.next;//拿出引用
        Node t = null;//輔助移動(dòng)
        while (q != null){
            t = q.next;//先存一下q.next
            q.next = p;
            p = q;
            q = t;
        }
        head.next.next = null;//設(shè)置鏈偉
        head.next = p;
        return head;
    }
}
  • 講一下對(duì)樹咙冗,B+樹的理解

http://blog.csdn.net/liuquan0071/article/details/50521032
?

  • 講一下對(duì)圖的理解

https://www.cnblogs.com/moonlord/p/5938061.html

  • 判斷單鏈表成環(huán)與否沾歪?

定義兩個(gè)指針p, q,其中p每次向前移動(dòng)一步雾消,q每次向前移動(dòng)兩步灾搏,所以就成p為慢指針,q為快指針立润。
那么如果單鏈表存在環(huán)狂窑,則p和q進(jìn)入環(huán)后一定會(huì)在某一點(diǎn)相遇,因?yàn)檫M(jìn)入環(huán)后就會(huì)一直循環(huán)下去桑腮,否則q將首先遇到null泉哈,就說明不存在環(huán)。

  • 合并多個(gè)單有序鏈表(假設(shè)都是遞增的)

http://blog.csdn.net/liang_henry/article/details/52943150

public ListNode getResult(ListNode result, ListNode l1, ListNode l2) {  
        if (l1 == null && l2 == null) {  
            return null;  
        }  
        if (l1 == null) {  
            result = l2;  
            //result.next = getResult(result.next, l1, l2.next);  
            return result;  
        }  
        if (l2 == null) {  
            result = l1;  
            //result.next = getResult(result.next, l1.next, l2);  
            return result;  
        }  
        if (l1.val > l2.val) {  
            result = l2;  
            l2 = l2.next;  
        } else {  
            result = l1;  
            l1 = l1.next;  
        }  
        result.next = getResult(result.next, l1, l2);  
        return result;  

線程破讨、多線程和線程池

  • 開啟線程的三種方式丛晦?

http://blog.csdn.net/longshengguoji/article/details/41126119

  • MyThread extends Thread
    new MyThread().start()
  • MyRunable implements Runable
    Thread thread = new Thread(new MyRunable()).start();
  • Target implements Callable<T>
  • FutureTask task = new FutureTask(new Target());
  • Thread thread = new Thread(task).start();
  • 為什么要有線程,而不是僅僅用進(jìn)程提陶?

線程增加的進(jìn)程的并發(fā)度烫沙,線程能更有效的利用多處理器和多內(nèi)核

  • run()和start()方法區(qū)別

http://www.jb51.net/article/98433.htm

  • start與run方法的主要區(qū)別在于當(dāng)程序調(diào)用start方法一個(gè)新線程將會(huì)被創(chuàng)建,并且在run方法中的代碼將會(huì)在新線程上運(yùn)行隙笆,然而在你直接調(diào)用run方法的時(shí)候锌蓄,程序并不會(huì)創(chuàng)建新線程,run方法內(nèi)部的代碼將在當(dāng)前線程上運(yùn)行撑柔。
  • 另外一個(gè)區(qū)別在于煤率,一但一個(gè)線程被啟動(dòng),你不能重復(fù)調(diào)用該thread對(duì)象的start方法乏冀,調(diào)用已經(jīng)啟動(dòng)線程的start方法將會(huì)報(bào)IllegalStateException異常蝶糯, 而你卻可以重復(fù)調(diào)用run方法
  • 如何控制某個(gè)方法允許并發(fā)訪問線程的個(gè)數(shù)?

https://www.cnblogs.com/androidsuperman/p/6349586.html

Semaphore semaphore = new Semaphore(5);//線程run中只有5個(gè)線程可并發(fā)訪問
semaphore.acquire();//申請(qǐng)一個(gè)信號(hào)
semaphore.release();//釋放一個(gè)信號(hào)
  • 線程的狀態(tài)

http://blog.csdn.net/pange1991/article/details/53860651

image

  • 在Java中wait和sleep方法的不同辆沦;

http://blog.csdn.net/liuguangqiang/article/details/49180319
wait 釋放對(duì)象鎖 sleep與對(duì)象鎖無關(guān)
當(dāng)前線程必須擁有此對(duì)象的monitor昼捍,才能調(diào)用對(duì)象的wait

  • 談?wù)剋ait/notify關(guān)鍵字的理解

都是本地final方法,調(diào)用之前持有對(duì)象鎖
wait 识虚,線程進(jìn)入掛起狀態(tài),釋放對(duì)象鎖
notify, 通知喚醒wait隊(duì)列中的線程(某個(gè))

  • 什么導(dǎo)致線程阻塞妒茬?

Thread.sleep t.join 等待輸入

  • 線程如何關(guān)閉担锤?

http://blog.csdn.net/tanga842428/article/details/52717610

  • 講一下java中的同步的方法

run方法結(jié)束 stop(相當(dāng)危險(xiǎn)) interrput()

  • 數(shù)據(jù)一致性如何保證/如何保證線程安全/如何實(shí)現(xiàn)線程同步?

http://blog.csdn.net/wenwen091100304/article/details/48318699

  • 同步方法 synchronized
  • 同步代碼塊 synchronize(obj)
  • volatile
  • 重入鎖 ReentrantLock
  • 使用局部變量 ThreadLocal<Integer> local
  • CAS非阻塞同步
  • 兩個(gè)進(jìn)程同時(shí)要求寫或者讀乍钻,能不能實(shí)現(xiàn)肛循?如何防止進(jìn)程的同步?(讀者寫者問題)

https://www.cnblogs.com/dancingwing/p/4165711.html
信號(hào)量+計(jì)數(shù)器

  • 線程間操作List

Collections.synchronizedList

  • Java中對(duì)象的生命周期

http://blog.csdn.net/sodino/article/details/38387049
創(chuàng)建--應(yīng)用-不可見-不可達(dá)-收集-終結(jié)-重分配

  • Synchronized用法

https://www.cnblogs.com/wl0000-03/p/5973039.html
內(nèi)置鎖银择,不影響沒有鎖多糠,或者沒有該鎖的方法執(zhí)行
類鎖只是一個(gè)抽象出來的概念,只是為了區(qū)別靜態(tài)方法的特點(diǎn)
同步代碼塊優(yōu)于同步方法(大房子小房間)

  • synchronize的原理

http://www.importnew.com/23511.html

  • 實(shí)現(xiàn)基礎(chǔ)(java對(duì)象頭和monitor是實(shí)現(xiàn)synchronized的基礎(chǔ):瓶肌)
    1. 普通同步方法夹孔,鎖是當(dāng)前實(shí)例對(duì)象
    2. 靜態(tài)同步方法,鎖是當(dāng)前類的class對(duì)象
    3. 同步方法塊析孽,鎖是括號(hào)里面的對(duì)象
  • 同步代碼塊-看class文件信息
    monitorenter monitorexit
  • 同步方法
    access_flags字段中的synchronized標(biāo)志位置1
  • java對(duì)象頭
    1. MarkWord 標(biāo)記字段 存儲(chǔ)對(duì)象自身運(yùn)行的數(shù)據(jù)搭伤,如哈希碼(HashCode)彤敛、GC分代年齡靶瘸、鎖狀態(tài)標(biāo)志衣吠、線程持有的鎖亚享、偏向線程 ID、偏向時(shí)間戳等等
    2. Klass Poniter 類型指針 哪個(gè)類型實(shí)例
  • Monitor
    一個(gè)同步工具,線程私有的數(shù)據(jù)結(jié)構(gòu),一些字段標(biāo)示了相關(guān)意義(Owner, EntryQ, RcThis, Nest, HashCode, Candidate)
  • 鎖優(yōu)化
    1. 自旋鎖:頻繁的阻塞和喚醒對(duì)CPU來說不值故而因數(shù)自旋淹接,讓該線程等待一段時(shí)間离唐,不會(huì)被立即掛起,執(zhí)行一段無意義的循環(huán)即可(自旋)忍疾。
    2. 適應(yīng)自旋鎖:固定次數(shù)自旋裁赠,有可能造成占著茅坑不拉屎,所以有了自適應(yīng)赴精,自適應(yīng)就是自選成功下次還會(huì)自旋(次數(shù)+1)佩捞,不成功就不自旋了。
    3. 鎖消除,有些時(shí)候不需要鎖蕾哟,但是一些系統(tǒng)類StringBuffer,Vector,HashTable自帶synchronize方法一忱,當(dāng)確實(shí)不需要的時(shí)候,JVM會(huì)對(duì)這些進(jìn)行鎖消除
    4. 鎖粗化: 鎖住的代碼塊越小越好谭确,但是連續(xù)鎖幾個(gè)小的就不好了帘营,連續(xù)鎖較多時(shí),合并成一個(gè)鎖逐哈,就是鎖粗化
    5. 輕量級(jí)鎖:主要目的是在多沒有多線程競(jìng)爭(zhēng)的前提下芬迄,減少傳統(tǒng)的重量級(jí)鎖使用操作系統(tǒng)互斥量產(chǎn)生的性能消耗。原理是多次通過CAS去改Mark Word字段昂秃。
    6. 偏向鎖:為了在無多線程競(jìng)爭(zhēng)的情況下盡量減少不必要的輕量級(jí)鎖執(zhí)行路徑禀梳。原理是檢查是否為偏向鎖杜窄、鎖標(biāo)識(shí)為以及ThreadID。
    7. 重量級(jí)鎖:重量級(jí)鎖通過對(duì)象內(nèi)部的監(jiān)視器(monitor)實(shí)現(xiàn)算途,其中monitor的本質(zhì)是依賴于底層操作系統(tǒng)的Mutex Lock實(shí)現(xiàn)塞耕,操作系統(tǒng)實(shí)現(xiàn)線程之間的切換需要從用戶態(tài)到內(nèi)核態(tài)的切換,切換成本非常高嘴瓤。
  • static synchronized 方法的多線程訪問和作用

靜態(tài)同步方法扫外,鎖為Class對(duì)象

  • 同一個(gè)類里面兩個(gè)synchronized方法,兩個(gè)線程同時(shí)訪問的問題

普通synchronized時(shí)廓脆,不能同時(shí)訪問筛谚,因?yàn)閮蓚€(gè)方法的鎖是示例對(duì)象,是一個(gè)狞贱。

  • volatile的原理

http://www.importnew.com/18126.html
lock前綴指令,即內(nèi)存柵欄:重排序不跨欄刻获,強(qiáng)制緩存立即更新主存,如果是寫會(huì)讓其它c(diǎn)pu中的對(duì)應(yīng)緩存無效

  • 談?wù)剉olatile關(guān)鍵字的用法

http://www.importnew.com/18126.html
狀態(tài)標(biāo)記量 瞎嬉,double check時(shí)

  • 談?wù)剉olatile關(guān)鍵字的作用

http://www.importnew.com/18126.html
可見蝎毡,一定程度的有序

  • synchronized 和volatile 關(guān)鍵字的區(qū)別

https://www.cnblogs.com/tf-Y/p/5266710.html

  • synchronized與Lock的區(qū)別

http://blog.csdn.net/u012403290/article/details/64910926?locationNum=11&fps=1

  • lock ReentrantLock

http://blog.csdn.net/yanyan19880509/article/details/52345422
http://blog.csdn.net/endlu/article/details/51249156

  • 死鎖的四個(gè)必要條件?

http://blog.csdn.net/jyy305/article/details/70077042
互斥條件
不可剝奪條件
請(qǐng)求和保持條件
循環(huán)等待條件

  • 怎么避免死鎖氧枣?

http://blog.csdn.net/ls5718/article/details/51896159
加鎖順訊
鎖加時(shí)限
鎖檢查

  • 對(duì)象鎖和類鎖是否會(huì)互相影響沐兵?

http://blog.csdn.net/codeharvest/article/details/70649375
http://blog.csdn.net/codeharvest/article/details/70649375

  • 什么是線程池,如何使用?

http://www.importnew.com/19011.html
關(guān)注如何縮短或調(diào)整T1,T3時(shí)間的技術(shù),調(diào)整線程池中工作線線程的數(shù)目以達(dá)到最優(yōu)
Executors ---- ThreadPoolExecutor
newSingleThreadExecutor
newFixedThreadExecutor(n)
newCacheThreadExecutor(推薦使用)
newScheduleThreadExecutor

/**
     * corePoolSize 核心池的大小(正式職工數(shù))便监,這個(gè)參數(shù)跟后面講述的線程池的>實(shí)現(xiàn)原理有非常大的關(guān)系扎谎。
        在創(chuàng)建了線程池后,默認(rèn)情況下烧董,線程池中并沒有任何線程毁靶,而是等待有任務(wù)到來才創(chuàng)建線程去執(zhí)行任務(wù),
       除非調(diào)用了prestartAllCoreThreads()或者prestartCoreThread()方法逊移,從這2個(gè)方法的名字就可以看出预吆,是預(yù)創(chuàng)建線程的意思,即在沒有任務(wù)到來之前就創(chuàng)建corePoolSize個(gè)線程或者一個(gè)線程胳泉。
       默認(rèn)情況下拐叉,在創(chuàng)建了線程池后,線程池中的線程數(shù)為0扇商,當(dāng)有任務(wù)來之后凤瘦,就會(huì)創(chuàng)建一個(gè)線程去執(zhí)行任務(wù),當(dāng)線程池中的線程數(shù)目達(dá)到corePoolSize后案铺,就會(huì)把到達(dá)的任務(wù)放到緩存隊(duì)列當(dāng)中蔬芥;
     * maximumPoolSize 線程池最大線程數(shù)(正式職工數(shù)+臨時(shí)工數(shù)),這個(gè)參數(shù)也是一個(gè)非常重要的參數(shù),它表示在線程池中最多能創(chuàng)建多少個(gè)線程坝茎;
     * keepAliveTime 表示線程沒有任務(wù)執(zhí)行時(shí)最多保持多久時(shí)間會(huì)終止涤姊。
       默認(rèn)情況下,只有當(dāng)線程池中的線程數(shù)大于corePoolSize時(shí)嗤放,keepAliveTime才會(huì)起作用思喊,即當(dāng)線程池中的線程數(shù)大于corePoolSize時(shí),如果一個(gè)線程空閑的時(shí)間達(dá)到keepAliveTime次酌,則會(huì)終止恨课,直到線程池中的線程數(shù)不超過corePoolSize。
       但是如果調(diào)用了allowCoreThreadTimeOut(boolean)方法岳服,在線程池中的線程數(shù)不大于corePoolSize時(shí)剂公,keepAliveTime參數(shù)也會(huì)起作用,直到線程池中的線程數(shù)為0吊宋;
     * unit keepAliveTime的時(shí)間單位
     * workQueue 一個(gè)阻塞隊(duì)列纲辽,用來存儲(chǔ)等待執(zhí)行的任務(wù),這個(gè)參數(shù)的選擇也很重要璃搜,會(huì)對(duì)線程池的運(yùn)行過程產(chǎn)生重大影響拖吼,一般來說,這里的阻塞隊(duì)列有以下幾種選擇:
       ArrayBlockingQueue;LinkedBlockingQueue;SynchronousQueue;
     * threadFactory 線程工廠这吻,主要用來創(chuàng)建線程吊档;
     * handler 表示當(dāng)拒絕處理任務(wù)時(shí)的策略
       ThreadPoolExecutor.AbortPolicy:丟棄任務(wù)并拋出RejectedExecutionException異常。 
       ThreadPoolExecutor.DiscardPolicy:也是丟棄任務(wù)唾糯,但是不拋出異常怠硼。 
       ThreadPoolExecutor.DiscardOldestPolicy:丟棄隊(duì)列最前面的任務(wù),然后重新嘗試執(zhí)行任務(wù)(重復(fù)此過程)
       ThreadPoolExecutor.CallerRunsPolicy:由調(diào)用線程處理該任務(wù)
     */
    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {
          .....................
    }
  • execute()方法實(shí)際上是Executor中聲明的方法移怯,在ThreadPoolExecutor進(jìn)行了具體的實(shí)現(xiàn)香璃,這個(gè)方法是ThreadPoolExecutor的核心方法,通過這個(gè)方法可以向線程池提交一個(gè)任務(wù)舟误,交由線程池去執(zhí)行葡秒。
  • submit()方法是在ExecutorService中聲明的方法,在AbstractExecutorService就已經(jīng)有了具體的實(shí)現(xiàn)脐帝,在ThreadPoolExecutor中并沒有對(duì)其進(jìn)行重寫同云,這個(gè)方法也是用來向線程池提交任務(wù)的糖权,但是它和execute()方法不同堵腹,它能夠返回任務(wù)執(zhí)行的結(jié)果,去看submit()方法的實(shí)現(xiàn)星澳,會(huì)發(fā)現(xiàn)它實(shí)際上還是調(diào)用的execute()方法疚顷,只不過它利用了Future來獲取任務(wù)執(zhí)行結(jié)果
  • shutdown()和shutdownNow()是用來關(guān)閉線程池的。
  1. 線程池狀態(tài)
    volatile int runState;//表示當(dāng)前線程池的狀態(tài),線程之間可見
    static final int RUNNING = 0;//初始時(shí)
    static final int SHUTDOWN = 1;//shutdown()后腿堤,不接新任務(wù)阀坏,等待所有任務(wù)執(zhí)行完畢
    static final int STOP = 2;//shutdownNow()后,不接新任務(wù)笆檀,當(dāng)前任務(wù)嘗試結(jié)束
    static final int TERMINATED = 3;//工作線程已經(jīng)銷毀,任務(wù)隊(duì)列無任務(wù)
  2. 任務(wù)執(zhí)行
public void execute(Runnable command) {
            if (command == null)
                throw new NullPointerException();
            int c = ctl.get();
            if (workerCountOf(c) < corePoolSize) {
                if (addWorker(command, true))
                    return;
                c = ctl.get();
            }
            if (isRunning(c) && workQueue.offer(command)) {
                int recheck = ctl.get();
                if (! isRunning(recheck) && remove(command))
                    reject(command);
                else if (workerCountOf(recheck) == 0)
                   addWorker(null, false);
            } else if (!addWorker(command, false))
                reject(command);
 }
  1. 線程池中的線程初始化
    prestartCoreThread():初始化一個(gè)核心線程忌堂;
    prestartAllCoreThreads():初始化所有核心線程
  2. 任務(wù)緩存隊(duì)列及排隊(duì)策略
    1)ArrayBlockingQueue:基于數(shù)組的先進(jìn)先出隊(duì)列,此隊(duì)列創(chuàng)建時(shí)必須指定大行锶鳌士修;
    2)LinkedBlockingQueue:基于鏈表的先進(jìn)先出隊(duì)列,如果創(chuàng)建時(shí)沒有指定此隊(duì)列大小樱衷,則默認(rèn)為Integer.MAX_VALUE棋嘲;
    3)synchronousQueue:這個(gè)隊(duì)列比較特殊,它不會(huì)保存提交的任務(wù)矩桂,而是將直接新建一個(gè)線程來執(zhí)行新來的任務(wù)沸移。
  3. 任務(wù)拒絕策略
  4. 線程池的關(guān)閉
    shutdown():不會(huì)立即終止線程池,而是要等所有任務(wù)緩存隊(duì)列中的任務(wù)都執(zhí)行完后才終止侄榴,但再也不會(huì)接受新的任務(wù)
    shutdownNow():立即終止線程池雹锣,并嘗試打斷正在執(zhí)行的任務(wù),并且清空任務(wù)緩存隊(duì)列牲蜀,返回尚未執(zhí)行的任務(wù)
  5. 線程池容量的動(dòng)態(tài)調(diào)整
  • Java的并發(fā)笆制、多線程、線程模型

https://www.cnblogs.com/EasonJim/p/7011747.html?utm_source=itdadao&utm_medium=referral
?

  • 談?wù)剬?duì)多線程的理解

https://www.cnblogs.com/SeaSky0606/p/4722413.html

  • 多線程有什么要注意的問題涣达?

http://blog.csdn.net/saizo123/article/details/64543853

  • 談?wù)勀銓?duì)并發(fā)編程的理解并舉例說明

http://blog.csdn.net/maozhr720/article/details/76017671

  • 談?wù)勀銓?duì)多線程同步機(jī)制的理解在辆?

?

  • 如何保證多線程讀寫文件的安全?

http://blog.csdn.net/rlanffy/article/details/26622521

  • 多線程斷點(diǎn)續(xù)傳原理與實(shí)現(xiàn)

https://www.cnblogs.com/amosli/p/3821474.html
RandomAccessFile

  • 談?wù)凬IO的理解

http://blog.csdn.net/suifeng3051/article/details/48160753
NIO主要用到的是塊
所有的數(shù)據(jù)都是用Buffer處理的度苔,它是NIO讀寫數(shù)據(jù)的中轉(zhuǎn)池匆篓。Buffer實(shí)質(zhì)上是一個(gè)數(shù)組
Channel是一個(gè)對(duì)象,可以通過它讀取和寫入數(shù)據(jù)

    1. 第一步:獲取通道
      FileInputStream fin = new FileInputStream( "readandshow.txt" );
      FileChannel fc = fin.getChannel();
    2. 第二步:創(chuàng)建緩沖區(qū)
      ByteBuffer buffer = ByteBuffer.allocate( 1024 );
    3. 第三步:將數(shù)據(jù)從通道讀到緩沖區(qū)
      fc.read( buffer );
    1. 第一步:獲取一個(gè)通道
      FileOutputStream fout = new FileOutputStream( "writesomebytes.txt" );
      FileChannel fc = fout.getChannel();
    2. 第二步:創(chuàng)建緩沖區(qū)寇窑,將數(shù)據(jù)放入緩沖區(qū)
      ByteBuffer buffer = ByteBuffer.allocate( 1024 );
      for (int i=0; i<message.length; ++i) {
      buffer.put( message[i] );
      }
      buffer.flip();
    3. 第三步:把緩沖區(qū)數(shù)據(jù)寫入通道中
      fc.write( buffer );

并發(fā)編程有關(guān)知識(shí)點(diǎn)

  • java線程安全總結(jié)

http://www.iteye.com/topic/806990

  • 深入理解java內(nèi)存模型

http://ifeve.com/java-memory-model-0/

  • 一張圖讓你看懂JAVA線程間的狀態(tài)轉(zhuǎn)換

https://my.oschina.net/mingdongcheng/blog/139263

  • 鎖機(jī)制:synchronized鸦概、Lock、Condition

http://blog.csdn.net/vking_wang/article/details/9952063

  • Java 中的鎖

http://wiki.jikexueyuan.com/project/java-concurrent/locks-in-java.html

  • Java并發(fā)編程:Thread類的使用

http://www.cnblogs.com/dolphin0520/p/3920357.html

  • Java多線程編程總結(jié)

http://blog.51cto.com/lavasoft/27069

  • Java并發(fā)編程實(shí)戰(zhàn)-----synchronized

http://www.cnblogs.com/chenssy/p/4701027.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末甩骏,一起剝皮案震驚了整個(gè)濱河市窗市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌饮笛,老刑警劉巖咨察,帶你破解...
    沈念sama閱讀 206,013評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異福青,居然都是意外死亡摄狱,警方通過查閱死者的電腦和手機(jī)脓诡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,205評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來媒役,“玉大人祝谚,你說我怎么就攤上這事『ㄖ裕” “怎么了交惯?”我有些...
    開封第一講書人閱讀 152,370評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)穿仪。 經(jīng)常有香客問我商玫,道長(zhǎng),這世上最難降的妖魔是什么牡借? 我笑而不...
    開封第一講書人閱讀 55,168評(píng)論 1 278
  • 正文 為了忘掉前任拳昌,我火速辦了婚禮,結(jié)果婚禮上钠龙,老公的妹妹穿的比我還像新娘炬藤。我一直安慰自己,他們只是感情好碴里,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,153評(píng)論 5 371
  • 文/花漫 我一把揭開白布沈矿。 她就那樣靜靜地躺著,像睡著了一般咬腋。 火紅的嫁衣襯著肌膚如雪羹膳。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 48,954評(píng)論 1 283
  • 那天根竿,我揣著相機(jī)與錄音陵像,去河邊找鬼。 笑死寇壳,一個(gè)胖子當(dāng)著我的面吹牛醒颖,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播壳炎,決...
    沈念sama閱讀 38,271評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼泞歉,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了匿辩?” 一聲冷哼從身側(cè)響起腰耙,我...
    開封第一講書人閱讀 36,916評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎铲球,沒想到半個(gè)月后挺庞,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,382評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡睬辐,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,877評(píng)論 2 323
  • 正文 我和宋清朗相戀三年挠阁,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片溯饵。...
    茶點(diǎn)故事閱讀 37,989評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡侵俗,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出丰刊,到底是詐尸還是另有隱情隘谣,我是刑警寧澤,帶...
    沈念sama閱讀 33,624評(píng)論 4 322
  • 正文 年R本政府宣布啄巧,位于F島的核電站寻歧,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏秩仆。R本人自食惡果不足惜码泛,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,209評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望澄耍。 院中可真熱鬧噪珊,春花似錦、人聲如沸齐莲。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,199評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)选酗。三九已至阵难,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間芒填,已是汗流浹背呜叫。 一陣腳步聲響...
    開封第一講書人閱讀 31,418評(píng)論 1 260
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留殿衰,地道東北人怀偷。 一個(gè)月前我還...
    沈念sama閱讀 45,401評(píng)論 2 352
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像播玖,于是被迫代替她去往敵國(guó)和親椎工。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,700評(píng)論 2 345

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

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法蜀踏,類相關(guān)的語(yǔ)法维蒙,內(nèi)部類的語(yǔ)法,繼承相關(guān)的語(yǔ)法果覆,異常的語(yǔ)法颅痊,線程的語(yǔ)...
    子非魚_t_閱讀 31,581評(píng)論 18 399
  • 一斑响、基本數(shù)據(jù)類型 注釋 單行注釋:// 區(qū)域注釋:/* */ 文檔注釋:/** */ 數(shù)值 對(duì)于byte類型而言...
    龍貓小爺閱讀 4,254評(píng)論 0 16
  • 1.HashMap是一個(gè)數(shù)組+鏈表/紅黑樹的結(jié)構(gòu)菱属,數(shù)組的下標(biāo)在HashMap中稱為Bucket值,每個(gè)數(shù)組項(xiàng)對(duì)應(yīng)的...
    誰在烽煙彼岸閱讀 1,010評(píng)論 2 2
  • (一)Java部分 1舰罚、列舉出JAVA中6個(gè)比較常用的包【天威誠(chéng)信面試題】 【參考答案】 java.lang;ja...
    獨(dú)云閱讀 7,069評(píng)論 0 62
  • 第一步纽门,你需要采取正確的學(xué)習(xí)方法來學(xué)習(xí)不同的學(xué)習(xí)內(nèi)容。方法正確营罢,就是成功了一半赏陵。有兩種學(xué)習(xí)方法。一種是自然...
    韓承伯閱讀 240評(píng)論 0 0