【Java 8實(shí)戰(zhàn)筆記】Lambda表達(dá)式

Lambda表達(dá)式

利用行為參數(shù)化這個(gè)概念,就可以編寫(xiě)更為靈活且可重復(fù)使用的代碼衔蹲。但同時(shí)肢娘,使用匿名類(lèi)來(lái)表示不同的行為并不令人滿(mǎn)意。Java 8引入了Lambda表達(dá)式來(lái)解決這個(gè)問(wèn)題舆驶。它使你以一種很簡(jiǎn)潔的表示一個(gè)行為或傳遞代碼橱健。

可以將Lambda表達(dá)式理解為簡(jiǎn)潔地表示可傳遞的匿名函數(shù)的一種方式:它沒(méi)有名稱(chēng),但它有參數(shù)列表沙廉、函數(shù)主體拘荡、返回類(lèi)型,可能還有一個(gè)可以?huà)伋龅漠惓A斜怼?/p>

  • 匿名 - 因?yàn)樗幌衿胀ǖ姆椒ㄒ粯佑幸粋€(gè)明確的名稱(chēng)撬陵。
  • 函數(shù) - 說(shuō)它是函數(shù)是因?yàn)長(zhǎng)ambda函數(shù)不像方法那樣屬于某個(gè)特定的類(lèi)珊皿,但和方法要一樣,Lambda有參數(shù)列表巨税、函數(shù)主體蟋定、返回類(lèi)型,還可能有可以?huà)伋龅漠惓A斜怼?/li>
  • 傳遞 - Lambda表達(dá)式可以作為參數(shù)傳遞給方法或存儲(chǔ)在變量中草添。
  • 簡(jiǎn)潔 - 無(wú)需像匿名類(lèi)那樣寫(xiě)很多模板代碼

使用Lambda的最終結(jié)果就是你的代碼變得更清晰驶兜、靈活。打比方远寸,利用Lambda表達(dá)式促王,可以更為簡(jiǎn)潔地自定義一個(gè)Comparator對(duì)象。

Lambda表達(dá)式由參數(shù)而晒、箭頭和主體組成

對(duì)比以下兩段代碼:

Comparator <Apple> byWeight = new Comparator<Apple>(){
    public int compare(Apple a1,Apple a2){
        return a1.getWeight().compareTo(a2.getWeight());
    }
};
(Apple a1,Apple a2) -> a1.getWeight().compareTo(a2.getWeight())

代碼看起來(lái)更清晰了≡某耄基本上只傳遞了真正需要的代碼(compare方法的主體)倡怎。

Lambda表達(dá)式由三個(gè)部分,如圖 Lambda表達(dá)式由參數(shù)、箭頭和主體組成 所示

  • 參數(shù)列表 - 這里它采用了Comparator中compare方法的參數(shù)监署,兩個(gè)Apple颤专。
  • 箭頭 - 箭頭 -> 把參數(shù)列表與Lambda主體分隔開(kāi)。
  • Lambda主體 - 比較兩個(gè)Apple的重量钠乏。表達(dá)式就是Lambda的返回值栖秕。

Lambda 的基本語(yǔ)法是:
(parameters) -> expression(parameters) -> { statements; }

函數(shù)式接口

之前的Predicate<T>就是一個(gè)函數(shù)式接口,因?yàn)镻redicate僅僅定義了一個(gè)抽象方法:

public interface Predicate<T>{
    boolean test(T t);
}

簡(jiǎn)而言之晓避,函數(shù)式接口就是只定義一個(gè)抽象方法的接口簇捍。Lambda表達(dá)式允許你直接以?xún)?nèi)聯(lián)的形式為函數(shù)式接口的抽象方法提供實(shí)現(xiàn),并把整個(gè)表達(dá)式作為函數(shù)式接口的實(shí)例俏拱。

函數(shù)式接口的抽象方法的簽名

把Lambda付諸實(shí)踐:環(huán)繞執(zhí)行模式

要從一個(gè)文件中讀取一行所需的模板代碼:

public static String processFile() throws IOException{
    try (BufferedReader br =
            new BufferedReader(new FileReader("data.txt"))){
        return br.readLine();
    }
}

現(xiàn)在這段代碼的局限性在于只能讀文件的第一行暑塑,如果想要返回頭兩行,甚至是返回使用最頻繁的詞锅必。這時(shí)需要把processFile的行為參數(shù)化事格。
需要一個(gè)接收BufferedReader并返回String的Lambda。下面是從BufferedReader中打印兩行的寫(xiě)法:

String result = processFile(BufferedReader br) -> br.readLine() + br.readLine());

現(xiàn)在需要?jiǎng)?chuàng)建一個(gè)能匹配BufferedReader -> String搞隐,還可以?huà)伋鯥OException異常的接口:

@FunctionalInterface
public interface BufferedReaderProcessor{
    String process(BufferedReader b) throws IOException;
}

@FunctionalInterface 是什么驹愚?
這個(gè)標(biāo)注用于表示該接口會(huì)設(shè)計(jì)成一個(gè)函數(shù)式接口。如果用 @FunctionalInterface 定義了一個(gè)接口劣纲,而它卻不是函數(shù)式接口的話(huà)逢捺,編譯器將返回一個(gè)提示原因的錯(cuò)誤。
使用它不是必須的味廊,但是使用它是比較好的做法蒸甜。

現(xiàn)在就可以把這個(gè)接口作為新的processFile方法的參數(shù),在方法主體內(nèi)余佛,對(duì)得到BufferedReaderProcessor對(duì)象調(diào)用process方法執(zhí)行處理:

public static String processFile(BufferedReaderProcessor p) throws IOException {
    try (BufferedReader br =
                 new BufferedReader(new FileReader("data.txt"))){
        return p.process(br);
    }
}

現(xiàn)在可以通過(guò)傳遞不同的Lambda重用processFile方法柠新,并以不用的方式處理文件了。
處理一行:

String oneLine =
    processFile((BufferedReader br) -> br.readLine());

處理兩行:

String twoLines = 
     processFile((BufferedReader br) -> br.readLine() + br.readLine());

完整代碼如下:

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class test{
    @FunctionalInterface
    public interface BufferedReaderProcessor{
        String process(BufferedReader b) throws IOException;
    }
    public static String processFile(BufferedReaderProcessor p) throws IOException {
        try (BufferedReader br =
                     new BufferedReader(new FileReader("c:/tmp/data.txt"))){
            return p.process(br);
        }
    }
    public static void main(String[] args) throws IOException {
        String oneLine = processFile((BufferedReader br) -> br.readLine());
        String twoLines = processFile((BufferedReader br) -> br.readLine() + br.readLine());
        System.out.println(oneLine);
        System.out.println(twoLines);
    }
}

現(xiàn)在已經(jīng)能成功的利用函數(shù)式接口來(lái)傳遞Lambda辉巡。

使用函數(shù)式接口

函數(shù)接口定義且只定義了一個(gè)抽象方法恨憎。函數(shù)式接口的抽象方法的簽名稱(chēng)為函數(shù)描述符。因此郊楣,為了應(yīng)用不同的Lambda表達(dá)式憔恳,需要一套能夠描述常見(jiàn)函數(shù)描述符的函數(shù)式接口。
Java 8在java.util.function包中加入了許多新的函數(shù)式接口净蚤,你可以重用它來(lái)傳遞多個(gè)不同的Lambda钥组。

Predicate

java.util.function.Predicate<T>接口定義了一個(gè)名叫test的抽象方法,它接受泛型T對(duì)象今瀑,并返回一個(gè)boolean程梦。在需要表示一個(gè)涉及類(lèi)型T的布爾表達(dá)式時(shí)点把,就可以使用這個(gè)接口。

public interface Predicate<T> {
    boolean test(T t);
}

例如:

@FunctionalInterface
public interface Predicate<T> {
    boolean test(T t);
}

public static <T> List<T> filter(List<T> list, Predicate<T> p){
    List<T> results = new ArrayList<>();
    for (T s: list){
        if(p.test(s)){
            results.add(s);
        }    
    }
    return results;
}
Predicate<String> nonEmptyStringPredicate = (String s) -> !s.isEmpty();
List<String> nonEmpty = filter(listOfStrings, nonEmptyStringPredicate);
Consumer

java.util.function.Consumer<T>定義了一個(gè)名叫accept的抽象方法屿附,它接受泛型T對(duì)象郎逃,沒(méi)有返回。
例如:

@FunctionalInterface
public interface Comsumer<T> {
    void accept(T t);
}

public static <T> void forEach(List<T> list, Predicate<T> c){
    for (T i: list){
        c.accept(i);
    }
}
forEach(
      Arrays.asList(1,2,3,4,5),
      (Interger i) -> System.ou.println(i)
    );
Function

java.util.function.Function<T, R>定義了一個(gè)名叫apply的抽象方法挺份,它接受一個(gè)泛型T對(duì)象褒翰,并返回一個(gè)泛型R的對(duì)象。
下面將創(chuàng)建一個(gè)map方法匀泊,以將一個(gè)String列表映射到包含每個(gè)String長(zhǎng)度的Interger列表:

@FunctionalInterface
public interface Function<T, R> {
    R accept(T t);
}

public static <T, R> List<R> map(List<T> list, Function<T, R> f){
    List<R> result = new ArrayList<>();
    for (T s: list){
        result.add(f.apply(s));
    }
    return result;
}
List<Integer> l =map(Arrays.asList("lambdas","in","action"), (String s) -> s.length());
原始類(lèi)型特化

Java的類(lèi)型有兩種: 引用類(lèi)型原始類(lèi)型 优训。但是泛型只能綁定到引用類(lèi)型。這是由于泛型內(nèi)部的實(shí)現(xiàn)方式造成的探赫。因此Java里有一個(gè)將原始類(lèi)型轉(zhuǎn)換為對(duì)應(yīng)的引用類(lèi)型的機(jī)制型宙。這個(gè)機(jī)制叫裝箱(boxing)。相反的操作便叫拆箱(unboxing)伦吠。裝箱和拆箱操作是可以由自動(dòng)裝箱機(jī)制來(lái)自動(dòng)完成的妆兑。但是這在性能方面要付出代價(jià),裝箱后的值需要更多的內(nèi)存并且需要額外的內(nèi)存毛仪。

Java 8為原始類(lèi)型帶來(lái)了一個(gè)專(zhuān)門(mén)的版本搁嗓,用于在輸入和輸出都是原始類(lèi)型時(shí)避免自動(dòng)裝箱的操作:

public interface IntPredicate{
    boolean test(int t);
}

無(wú)裝箱:

IntPredicate evenNumbers = (int i) -> i%2 ==0;
evenNumbers.test(1000);

裝箱:

Predicate<Integer> oddNumbers = (Integer i) -> i%2 == 1;
oddNumbers.test(1000);

類(lèi)型檢查、類(lèi)型推斷以及限制

Lambda本身并不包含它在實(shí)現(xiàn)哪個(gè)函數(shù)式接口的信息箱靴。為了全面了解Lambda表達(dá)式應(yīng)該知道Lambda的實(shí)際類(lèi)型是什么腺逛。

類(lèi)型檢查

Lambda的類(lèi)型是從使用Lambda的上下文推斷出來(lái)的。上下文(例如接受它傳遞的方法的參數(shù)衡怀,或接受它的值的局部變量)中Lambda表達(dá)式需要的類(lèi)型稱(chēng)為目標(biāo)類(lèi)型棍矛。

同樣的Lambda,不同的函數(shù)式接口

有了目標(biāo)類(lèi)型的概念抛杨,同一個(gè)Lambda表達(dá)式就可以與不同的函數(shù)式接口聯(lián)系起來(lái)够委。

類(lèi)型推斷

可以進(jìn)一步簡(jiǎn)化你的代碼。編譯器會(huì)從上下文(目標(biāo)類(lèi)型)推斷出痛什么函數(shù)式接口來(lái)配合Lambda表達(dá)式怖现,這意味著它也可以推斷出適合Lambda的簽名茁帽,這樣就可以再Lambda語(yǔ)法中省去標(biāo)注參數(shù)類(lèi)型。

沒(méi)有自動(dòng)類(lèi)型推斷:

Comparator<Apple> c = (Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight());

有自動(dòng)類(lèi)型推斷:

Comparator<Apple> c =(a1, a2) -> a1.getWeight().compareTo(a2.getWeight());
使用局部變量

之前介紹的所有Lambda表達(dá)式都只用到了其主體里面的參數(shù)屈嗤。但Lambda表達(dá)式也允許使用自由變量(不是參數(shù)潘拨,而是在外層作用域中定義的變量),就像匿名類(lèi)一樣饶号。它們被稱(chēng)作捕獲Lambda铁追。

例如:

int portNumber = 1337;
Runnable r = () -> System.out.println(portNumber);

Lambda捕獲了portNumber變量。但關(guān)于對(duì)這些變量可以做什么有一些限制茫船。Lambda可以沒(méi)有限制的捕獲實(shí)例變量和靜態(tài)變量(也就是在其主體中引用)脂信。但是局部變量必須顯示聲明為final(或事實(shí)上是final)癣蟋。
下面的代碼無(wú)法編譯,因?yàn)閜ortNumber變量被賦值了兩次:

int portNumber = 1337;
Runnable r = () -> System.out.println(portNumber);
portNumber = 31337;

實(shí)例變量和局部變量背后的實(shí)現(xiàn)有一個(gè)關(guān)鍵的不同狰闪。實(shí)例變量都存儲(chǔ)在堆中,而局部變量則保存在棧上濒生。Java在訪(fǎng)問(wèn)自由局部變量時(shí)埋泵,實(shí)際上是在訪(fǎng)問(wèn)它的副本,而不是訪(fǎng)問(wèn)原始變量罪治。如果Lambda可以直接訪(fǎng)問(wèn)局部變量丽声,而且Lambda是在一個(gè)線(xiàn)程中使用的,則使用Lambda的線(xiàn)程觉义,可能會(huì)在分配該變量的線(xiàn)程將這個(gè)變量收回之后去訪(fǎng)問(wèn)該變量雁社,這回引發(fā)造成線(xiàn)程不安全的新的可能性。

方法引用

方法引用可以重復(fù)使用現(xiàn)有的方法定義晒骇,并像Lambda一樣傳遞它們霉撵。

下面是用方法引用寫(xiě)的一個(gè)排序的例子:

先前:

invenstory.sort((Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight()));

之后(使用方法引用和 java.util.Comparator.comparing ):

inventory.sort(comparing(Apple::getWeight));

方法引用可以被看做僅僅調(diào)用特定方法的Lambda的一種快捷寫(xiě)法。它的基本思想是洪囤,如果一個(gè)Lambda代表的只是“直接調(diào)用這個(gè)方法”徒坡,那最好還是用名稱(chēng)來(lái)調(diào)用它,而不是去描述如何調(diào)用它瘤缩。

方法引用就是讓你根據(jù)已有的方法實(shí)現(xiàn)來(lái)創(chuàng)建Lambda表達(dá)式喇完。

當(dāng)你需要使用方法引用時(shí),目標(biāo)引用放在分隔符 :: 前剥啤,方法的名稱(chēng)放在后面锦溪。例如 Apple::getWeight 就是引用了Apple類(lèi)中定義的方法getWeight。

方法引用也可以看做針對(duì)僅僅設(shè)計(jì)單一方法的Lambda的語(yǔ)法糖府怯。

構(gòu)建方法引用

方法引用主要有三類(lèi)刻诊。

  1. 指向靜態(tài)方法的方法引用(Integer::parseInt)
  2. 指向任意類(lèi)型實(shí)例方法的方法引用(String::length)
  3. 指向現(xiàn)有對(duì)象的實(shí)例方法的方法引用(Transaction::getValue)

第二種方法引用的思想就是你在引用一個(gè)對(duì)象的方法,而這個(gè)對(duì)象本身是Lambda的一個(gè)參數(shù)富腊。
例如 (String s) -> s.toUpperCase() 可以寫(xiě)作 String::toUpperCase坏逢。

第三種方法引用指的是,你在Lambda中調(diào)用一個(gè)已經(jīng)存在的外部對(duì)象的方法赘被。例如是整,Lambda表達(dá)式 () -> expenssiveTransaction.getValue() 可以寫(xiě)作 expensiveTransaction::getValue

方法引用不需要括號(hào)民假,是因?yàn)闆](méi)有實(shí)際調(diào)用這個(gè)方法浮入。

構(gòu)造函數(shù)引用

可以利用現(xiàn)有構(gòu)造函數(shù)的名稱(chēng)和關(guān)鍵字來(lái)創(chuàng)建它的一個(gè)引用 ClassName:new

例如:

List<Integer> weight = Arrays.asList(7,3,4,10);
List<Apple> apples = map(weights, Apple::new);
public static List<Apple> map(List<Integer> List, Function<Integer, Apple> f){
    List<Apple> result = new ArrayList<>();
    for(Integer e: list){
        result.add(f.apply(e))
    }
    return result;
}

Lambda和方法引用實(shí)戰(zhàn)(用不同的排序策略給一個(gè)Apple列表排序)

第1步:傳遞代碼

Java API已經(jīng)提供了一個(gè)List可用的sort方法,要如何把排序策略傳遞給sort呢羊异?sort方法的簽名樣子如下:

void sort(Comparator<? super E> c)

它需要一個(gè)Comparator對(duì)象來(lái)比較兩個(gè)Apple事秀。

第一個(gè)解決方案看上去是這樣的:

public class AppleComparator implements Comparator<Apple>{
    public int compare(Apple a1, Apple a2){
        return a1.getWeight().compareTo(a2.getWeight());
    }
}

inventory.sort(new AppleComparator());
第2步:使用匿名類(lèi)改進(jìn)
inventory.sort(new AppleComparator<Apple>(){
    public int compare(Apple a1, Apple a2){
        return a1.getWeight().compareTo(a2.getWeight());
    }
});

使用匿名類(lèi)的意義僅僅在于不用為了只實(shí)例化一次而實(shí)現(xiàn)一個(gè)Comparator彤断。

第3步:使用Lambda表達(dá)式
inventory.sort((Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight()));

inventory.sort((a1, a2) -> a1.getWeight().compareTo(a2.getWeight()));

Comparator有一個(gè)叫做comparing的靜態(tài)輔助方法,它可以接受一個(gè)Function來(lái)提取Comparable鍵值易迹,并生成一個(gè)Comparator對(duì)象:

import static java.util.Comparator.comparing;

inventory.sort(comparing((a) -> a.getWeight()));
第4步:使用方法引用
inventory(comparing(Apple::getWeight));

復(fù)合Lambda表達(dá)式的有用方法

比較器復(fù)合

對(duì)于:

Comparator<Apple> c = Comparator.comparing(Apple::getWeight);

1.逆序

想要按重量遞減排序怎么辦宰衙?不需要建立一個(gè)新的Comparator的實(shí)例。接口有個(gè)默認(rèn)方法 reverse 可以使給定的比較器逆序睹欲。因此仍然可以用之前的那個(gè)比較器:

inventory.sort(comparing(Apple::getWeight).reversed());

2.比較器鏈

如果兩個(gè)蘋(píng)果一樣重怎么辦窘疮,哪個(gè)蘋(píng)果應(yīng)該排在前面闸衫?這時(shí)候可能需要再提供一個(gè)Comparator來(lái)進(jìn)一步比較弟翘。
thenComparing 就是做這個(gè)用的衅胀。它接受一個(gè)函數(shù)作為參數(shù)(與comparing方法一樣)滚躯,如果兩個(gè)對(duì)象用第一個(gè)Comparator比較之后是一樣的掸掏,就提供第二個(gè)Comparator:

inventory.sort(comparing(Apple::getWeight).reversed().thenComparing(Apple::getCountry));
謂詞復(fù)合

謂詞接口包括三個(gè)方法:negate、and 和 or愿待。

  1. negate
    可以使用negate方法來(lái)返回一個(gè)Predicate的非,比如蘋(píng)果不是紅色:
Predicate<Apple> notRedApple = redApple.negate()
  1. and
    可以用and方法將兩個(gè)Lambda組合起來(lái):
Predicate<Apple> redAndHeavyApple = redApple.and(a -> a.getWeight() > 150);
  1. or
Predicate<Apple> redAndHeavyAppleOrGreen = redApple.and(a -> a.getWeight() > 150).or(a -> "green".equals(a.getcolor()));
函數(shù)復(fù)合

還可以把Function接口所代表的Lambda表達(dá)式復(fù)合起來(lái)。Function接口有兩個(gè)默認(rèn)方法:andThen和 compose砸紊。它們都會(huì)返回Function的一個(gè)實(shí)例沼溜。

  1. andThen 方法會(huì)返回一個(gè)函數(shù),它先對(duì)輸入應(yīng)用一個(gè)給定函數(shù),再對(duì)輸出應(yīng)用另一個(gè)函數(shù)。

比如函數(shù)f給數(shù)字加1啰扛,另一個(gè)函數(shù)給數(shù)字乘2:

Function<Integer,Integer> f = x -> x + 1;
Function<Integer,Integer> g = x -> x * 2;
Function<Integer,Integer> h = f.andThen(g);
int result = h.apply(1);

在數(shù)學(xué)上意味著g(f(x))

  1. compose 方法先把給定的函數(shù)用作compose的參數(shù)里面給的那個(gè)函數(shù),然后再把函數(shù)本身用于結(jié)果续徽。
Function<Integer,Integer> f = x -> x + 1;
Function<Integer,Integer> g = x -> x * 2;
Function<Integer,Integer> h = f.compose(g);
int result = h.apply(1);

在數(shù)學(xué)上意味著f(g(x))

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市膀斋,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌惰匙,老刑警劉巖哑梳,帶你破解...
    沈念sama閱讀 219,490評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件龄毡,死亡現(xiàn)場(chǎng)離奇詭異祭隔,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)搞坝,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)慌核,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)垫桂,“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了吴攒?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,830評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我轻猖,道長(zhǎng)琉雳,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,957評(píng)論 1 295
  • 正文 為了忘掉前任盟戏,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘律歼。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,974評(píng)論 6 393
  • 文/花漫 我一把揭開(kāi)白布域庇。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上煌妈,一...
    開(kāi)封第一講書(shū)人閱讀 51,754評(píng)論 1 307
  • 那天,我揣著相機(jī)與錄音之宿,去河邊找鬼族操。 笑死,一個(gè)胖子當(dāng)著我的面吹牛澈缺,可吹牛的內(nèi)容都是我干的坪创。 我是一名探鬼主播,決...
    沈念sama閱讀 40,464評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼姐赡,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼莱预!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起项滑,我...
    開(kāi)封第一講書(shū)人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤依沮,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體危喉,經(jīng)...
    沈念sama閱讀 45,847評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡宋渔,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,995評(píng)論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了辜限。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片皇拣。...
    茶點(diǎn)故事閱讀 40,137評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖薄嫡,靈堂內(nèi)的尸體忽然破棺而出氧急,到底是詐尸還是另有隱情,我是刑警寧澤毫深,帶...
    沈念sama閱讀 35,819評(píng)論 5 346
  • 正文 年R本政府宣布吩坝,位于F島的核電站,受9級(jí)特大地震影響哑蔫,放射性物質(zhì)發(fā)生泄漏钉寝。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,482評(píng)論 3 331
  • 文/蒙蒙 一闸迷、第九天 我趴在偏房一處隱蔽的房頂上張望嵌纲。 院中可真熱鬧,春花似錦腥沽、人聲如沸疹瘦。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,023評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至邓嘹,卻和暖如春酣栈,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背汹押。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,149評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工矿筝, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人棚贾。 一個(gè)月前我還...
    沈念sama閱讀 48,409評(píng)論 3 373
  • 正文 我出身青樓窖维,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親妙痹。 傳聞我的和親對(duì)象是個(gè)殘疾皇子铸史,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,086評(píng)論 2 355

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