Stream基礎(chǔ)知識(shí)

Stream API

Stream是Java8中處理集合的關(guān)鍵抽象概念,它可以指定你希望對(duì)集合進(jìn)行的操作宾茂,但是將執(zhí)行操作的時(shí)間交給具體實(shí)現(xiàn)來(lái)決定瓷马。例如,如果你希望計(jì)算某個(gè)方法的平均值跨晴,你可以在每個(gè)元素上指定調(diào)用的方法欧聘,從而獲得所有值的 平均值。你可以使用Stream API來(lái)并行執(zhí)行操作端盆,使用過(guò)多線程來(lái)計(jì)算每一段的總和與數(shù)量怀骤,再將結(jié)果匯總起來(lái)。

一個(gè)Stream表面上看與一個(gè)集合很類似焕妙,允許你改變和獲取數(shù)據(jù)晒喷。但是實(shí)際上它與集合是有很大區(qū)別的:

  1. Stream自己不會(huì)存儲(chǔ)元素。元素可能被存儲(chǔ)在底層的集合中访敌,或者根據(jù)需要產(chǎn)生出來(lái)凉敲。
  2. Stream操作符不會(huì)改變?cè)磳?duì)象。相反寺旺,它們會(huì)返回一個(gè)持有結(jié)果的新Stream爷抓。
  3. Stream操作符可能是延遲執(zhí)行的。這意味者它們會(huì)等到需要結(jié)果的時(shí)候才執(zhí)行阻塑。例如你只想要前5個(gè)長(zhǎng)單詞蓝撇,而不需要統(tǒng)計(jì)所有長(zhǎng)字符,那么filter方法將會(huì)在5次匹配后停止過(guò)濾陈莽。因此渤昌,甚至可以有無(wú)限的Stream。
List<String> words = ...;
//Java8在Collection接口中新添加的stream方法走搁,可以將任何集合轉(zhuǎn)化為一個(gè)Stream
long count = words.stream().filter(w -> w.length() > 12).count();

//將stream方法改成parallel Stream方法独柑,就可以讓StreamAPI并行執(zhí)行過(guò)濾和統(tǒng)計(jì)操作。
long count = words.vStream().filter(w -> w.length() > 12).count();

Stream遵循“做什么私植,而不是怎么去做”的原則忌栅。上面的代碼中,描述了需要做什么:獲的長(zhǎng)單詞并對(duì)它們的個(gè)數(shù)進(jìn)行統(tǒng)計(jì)曲稼。我們沒(méi)有制定按照什么順序索绪,或者在哪個(gè)線程中做湖员,它們都是理所應(yīng)當(dāng)發(fā)生的。相反瑞驱,循環(huán)在一開(kāi)始就需要指定如何進(jìn)行運(yùn)算娘摔,因此就是去了優(yōu)化的機(jī)會(huì)。
當(dāng)你使用Stream時(shí)唤反,你會(huì)通過(guò)三個(gè)階段來(lái)建立一個(gè)操作流水線凳寺。

  1. 創(chuàng)建一個(gè)Stream
  2. 在一個(gè)或多個(gè)步驟中,指定將初始Stream轉(zhuǎn)換為另一個(gè)Stream的中間操作拴袭。
  3. 使用一個(gè)終止操作來(lái)產(chǎn)生一個(gè)結(jié)果。該操作會(huì)強(qiáng)制它之前的延遲操作立即執(zhí)行曙博。在這之后拥刻,該Stream就不會(huì)再被使用了

在上面的代碼中父泳,通過(guò)stream或parallelStream方法來(lái)創(chuàng)建Stream般哼,在通過(guò)filter方法對(duì)其進(jìn)行轉(zhuǎn)換,而count方法就是終止操作惠窄。

創(chuàng)建Stream

  1. Java8在Collection接口中新添加的stream方法蒸眠,可以將任何集合轉(zhuǎn)化為一個(gè)Stream
  2. 如果是一個(gè)數(shù)組,可以用靜態(tài)的Stream.of方法將它轉(zhuǎn)化為一個(gè)Stream;如果需要將數(shù)組的一部分轉(zhuǎn)化為Stream杆融,可以使用Arrays.stream()
Stream<String> words = Stream.of(String[] array);
Stream<String> words = Stream.of(String ...args);
Stream<String> words = Arrays.stream(array, from, to);
  1. 要?jiǎng)?chuàng)建一個(gè)不含任何元素的Stream楞卡,可以使用靜態(tài)的Stream.empty()
  2. 創(chuàng)建無(wú)限Stream的靜態(tài)方法。
  • generate方法接受一個(gè)無(wú)參的函數(shù)(從技術(shù)上說(shuō)脾歇,是一個(gè)Supplier <T>接口的對(duì)象)蒋腮。當(dāng)需要一個(gè)Stream值時(shí),就可以調(diào)用該方法來(lái)產(chǎn)生一個(gè)值藕各。
Stream<String> echos = Stream.generate( () -> "Echo");//創(chuàng)建一個(gè)含有常量值的Stream
Stream<Double> randoms = Stream.generate( Math::random );
  • iteratre方法接受一個(gè)"種子(seed)"值和一個(gè)函數(shù)(從技術(shù)上講池摧,是一個(gè)UnaryOperator<T>接口的對(duì)象)作為參數(shù),并且會(huì)對(duì)之前的值重復(fù)應(yīng)用該函數(shù)激况。例如:
Stream<BigInterger> integers = Stream.iterate(BigInteger.ZERO, n -> n.add(BigInter.ONE));

在Java8中作彤,添加了許多能夠產(chǎn)生Stream的方法。例如乌逐,Pattern類添加了一個(gè)splitAsStream的方法竭讳,能夠按照正則表達(dá)式對(duì)CharSequence(接口,String浙踢、StringBuilder和StringBuffer都實(shí)現(xiàn)該接口)對(duì)象進(jìn)行分隔代咸。

Stream<String> words = Pattern.compile(",").splitAsStream("abc,def");

Stream的轉(zhuǎn)換

Stream轉(zhuǎn)換是指從一個(gè)流中讀取數(shù)據(jù),并將轉(zhuǎn)換后的數(shù)據(jù)寫(xiě)入另一流中成黄。

  1. filter呐芥、map逻杖、flatMap方法
  • filter()
    filter方法的參數(shù)是一個(gè)Predicate<T>對(duì)象——即一個(gè)從T到Boolean的函數(shù)。
List<String> wordList = ...;
Stream<String> words = wordList.stream();
Stream<String> longWOrds = words.filter(w -> w.length() > 12);
  • map()
    我們經(jīng)常需要對(duì)一個(gè)流中的值進(jìn)行某種形式的轉(zhuǎn)換思瘟。這時(shí)可以考慮使用map方法荸百,并傳遞給它一個(gè)執(zhí)行轉(zhuǎn)換的函數(shù)。例如
//使用了帶有一個(gè)方法引用的map方法
Stream<String> lovercaseWords = words.map(String::toLowerCase);
//通常會(huì)使用一個(gè)lambda表達(dá)式來(lái)代替方法表達(dá)式
Stream<Character> firstChars = words.map(s -> charAt(0)); //該方法產(chǎn)生的流會(huì)包含每個(gè)單詞的第一個(gè)字符
  • flatMap()
    假設(shè)現(xiàn)在有一個(gè)函數(shù)滨攻,如下:
public static Stream<Character> characterStream(String s) {
    List<Character> result = new ArrayList<>();
    for (char c : s.toCharArray()) result.add(c);
    return result.stream();
}

調(diào)用該方法够话,如characterStream("boat")會(huì)返回流['b', 'o', 'a', 't']。假設(shè)將該方法映射到一個(gè)字符串流上:

Stream<Stream<Character>> result = words.mapo(w -> characterStream(w));

將會(huì)得到一個(gè)包含多個(gè)流的流光绕,如:[..., ['b', 'o', 'a', 't'], ...]女嘲。如果要將其展開(kāi)為一個(gè)只包含字符串的流[..., 'b', 'o', 'a', 't', ...],則需要使用flatMap方法诞帐,而不是map方法:

Stream<Character> letters = words.flatMap(w -> characterStream(w));
  1. 提取子流和組合流
  • limit()
    Stream.limit(n)會(huì)返回一個(gè)包含n個(gè)元素的新流(如果原始長(zhǎng)度小于m欣尼,則返回原始的流)。這個(gè)方法特別適用于裁剪指定長(zhǎng)度的流停蕉。例如產(chǎn)生一個(gè)包含100個(gè)隨機(jī)數(shù)字的流:
Stream<Double> randoms = Stream.generate(Math::random).limit(100);
  • skip()
    Stream.skip(n)正好相反愕鼓,它會(huì)丟掉前面的n個(gè)元素。
Stream<String> words = Stream.of("abc", "cdf","ghi").skip(1); //會(huì)丟棄掉"abc"
  • concat()
    Stream.concat(Stream, Stream)將兩個(gè)流連接到一起慧起。注意菇晃,第一個(gè)流的長(zhǎng)度不應(yīng)該是無(wú)限的蚓挤,否則第二個(gè)流舊永遠(yuǎn)沒(méi)有機(jī)會(huì)被添加到第一個(gè)流后面磺送。
Stream<Character> combined = Stream.concat(Stream.of('H', 'e', 'l', 'l', 'o'), Stream.of('W', 'o', 'r', 'l', 'd'));
//產(chǎn)生一個(gè)新流['H', 'e', 'l', 'l', 'o'灿意,'W', 'o', 'r', 'l', 'd']
  1. 有狀態(tài)的轉(zhuǎn)換
    之前介紹的流轉(zhuǎn)換都是無(wú)狀態(tài)的册着,即當(dāng)從一個(gè)已過(guò)濾或已映射的流中獲取某個(gè)元素時(shí)甲捏,結(jié)果并不依賴之前的元素。除此之外鞭执,Java8也提供了有狀態(tài)的轉(zhuǎn)換司顿。
  • distinct()
    distinct方法會(huì)根據(jù)原始流中的元素返回一個(gè)具有相同順序、抑制了重復(fù)元素的新流兄纺。顯然大溜,該流必須記住之前已讀取的元素。
Stream<String> uniqueWords = Stream.of("merrily", "merrily", "gently").distinct();
// 只獲取一個(gè)"merrily"
  • sorted()
    sorted方法必須遍歷整個(gè)流估脆,并在產(chǎn)生任何元素之前對(duì)它進(jìn)行排序钦奋。顯然,無(wú)法對(duì)一個(gè)無(wú)限流進(jìn)行排序。
Stream<String> longestFirst = words.sorted(Comparator.comparing(String::length).reversed());

Stream終止操作

前面已經(jīng)了解任何創(chuàng)###Stream終止操作建流和轉(zhuǎn)換流付材,接下來(lái)將介紹: 如何從數(shù)據(jù)流數(shù)據(jù)中找到“答案”朦拖。

  1. 聚合方法
    在本節(jié)中介紹的方法統(tǒng)稱聚合方法。它們將流聚合為一個(gè)值厌衔,以便在程序中使用璧帝。聚合方法都是終止操作。當(dāng)一個(gè)流應(yīng)用了終止操作后富寿,它就不能再應(yīng)用其它操作了睬隶。
  • count()
    返回流中元素總數(shù)。
long count = Stream.of("abc", "bcd", "cde").count(); //count的結(jié)果為 3页徐。
  • max(), min()
    max方法返回流中最大值苏潜。min方法返回流中最小值。
    需要注意的是变勇,它們返回的是一個(gè)Optional<T>值恤左,它可能會(huì)封裝返回值,也可能表示沒(méi)有返回(當(dāng)流為空時(shí))贰锁。以前在這種情況通常會(huì)返回null赃梧,程序拿到該返回值后滤蝠,進(jìn)行下一步操作豌熄,可能會(huì)導(dǎo)致拋出空指針異常。在Java8中物咳,Optional類型時(shí)一種更好的表示缺少返回值的方式锣险。
    下面是一個(gè)如何獲得最大值的示例:
Optional<String> largest = Stream.of("abc", "bcd", "cde").max(String::compareToIgnoreCase);
if (largest.isPresent())
    System.out.println("largest: " + largest.get());
  • findFirst(), findAny()
    findFirst方法會(huì)返回非空集合中的第一個(gè)值(通常與filter方法結(jié)合使用);如果想找到所有匹配的元素中的任意一個(gè)览闰,那么可以使用findAny方法芯肤,這個(gè)方法在對(duì)流進(jìn)行并行執(zhí)行時(shí)十分有效,因?yàn)橹灰谌魏纹沃邪l(fā)現(xiàn)第一個(gè)匹配元素压鉴,都會(huì)結(jié)束整個(gè)計(jì)算崖咨。
Optional<String> startsWithQ = Stream.of("abc",  Qabc1", "bcd", "Qabc2").parallel().filter(s -> s.startWith("Q")).findAny();
  • allMatch(), anyMatch()
    allMatch方法和anyMatch方法,它們分別在所有元素和沒(méi)有元素匹配predicate時(shí)返回true油吭。雖然這些方法總是會(huì)檢查整個(gè)流击蹲,但是仍可以通過(guò)并行執(zhí)行來(lái)提高速度。
  1. Optional類型
    Optional<T>對(duì)象或者是對(duì)一個(gè)對(duì)象的封裝婉宰,或者表示不是任何對(duì)象歌豺。它一般比指向T類型的引用更安全,因?yàn)樗粫?huì)反回null心包。
    如果存在被封裝的對(duì)象类咧,那么get方法會(huì)返回該對(duì)象,否則會(huì)返回一個(gè)NoSuchElementException。因此痕惋,
Optional<T> optionalValue = ...;
optionalValue.get().someMethod();

并不比下面的方式更安全:

T value = ...;
value.someMethod();

isPresent方法會(huì)反映出一個(gè)Optional<T>對(duì)象是否有值区宇。同樣的:

if (optionalValue.isPresent()) optionalValue.get().someMethod();

并不比下面的方式更簡(jiǎn)單:

if (value != null) value.someMethod();

下面開(kāi)始了解如何真正使用Optional值。

使用Optional

高效使用Optional的關(guān)鍵在于血巍,使用一個(gè)或者接受正確值萧锉、或者返回另一個(gè)替代值的方法。

  • ifPresent()
    ifPresent方法可以接受一個(gè)函數(shù)述寡。如果存在可選值柿隙,那么它會(huì)將該值傳遞給函數(shù),否則不會(huì)進(jìn)行任何操作鲫凶。例如禀崖,如果希望在當(dāng)有值存在時(shí)將它添加到一個(gè)集合中,可以調(diào)用:
optionalValue.ifPresent(v -> results.add(v));
//或者
optionalValue.ifPresent(results::add);
  • map()
    當(dāng)調(diào)用ifPresent方法時(shí)螟炫,不會(huì)反回任何值波附。如果你希望對(duì)結(jié)果進(jìn)行處理,可以使用map方法昼钻。
Optional<Boolean> added = optionalValue.map(results::add);

因?yàn)閞esults.add()返回值是boolean類型掸屡,現(xiàn)在added有可能是以下三種值:被封裝到Optional中的true或者false,或者是一個(gè)空的可選值然评。

  • orElse()
    已經(jīng)了解了當(dāng)一個(gè)可選值存在時(shí)應(yīng)該如何對(duì)它優(yōu)雅地進(jìn)行處理仅财。另一種使用可選值的方式是,當(dāng)沒(méi)有值存在時(shí)碗淌,產(chǎn)生一個(gè)替代值盏求。通常,當(dāng)沒(méi)有可匹配項(xiàng)時(shí)亿眠,會(huì)希望使用一個(gè)默認(rèn)值碎罚,例如一個(gè)空字符串:
String result = optionalString.orElse("");
// 如果封裝的字符串為空的話,則使用給定的空字符串""
  • orElseGet()
    當(dāng)沒(méi)有值存在時(shí)纳像,還可以調(diào)用代碼來(lái)計(jì)算
String result = optionalString.orElseGet(() -> System.getProperty("user.dir"));
  • orElseThrow()
    當(dāng)沒(méi)有值存在時(shí)荆烈,會(huì)拋出一個(gè)指定的異常。
String result = optionalString.orElseThrow(NoSuchElementException::new);
//需要提供一個(gè)產(chǎn)生異常對(duì)象的方法

創(chuàng)建可選值

之前已經(jīng)討論了如何處理一個(gè)已存在的Optional對(duì)象竟趾。接下來(lái)說(shuō)明如何創(chuàng)建一個(gè)Optional對(duì)象憔购。

  • Optional.of(obj),Optional.empty()
    of方法創(chuàng)建一個(gè)封裝了obj的Optional對(duì)象,empty方法創(chuàng)建一個(gè)”空"的Optional對(duì)象潭兽。
  • Optional.ofNullable()
    ofNullable方法被設(shè)計(jì)為null值和可選值之間的一座橋梁倦始。如果obj不為null,那么Optional.ofNullable(obj)會(huì)返回Optional.of(obj)山卦,否則會(huì)返回Optional.empty()鞋邑。
  • 使用flatMap來(lái)組合可選值函數(shù)
    暫略诵次。
  1. 聚合操作
    略。
  2. 收集結(jié)果
    當(dāng)你處理完流之后枚碗,通常只是想看一下結(jié)果逾一,而不是將它們聚合為一個(gè)值。
    iterator()
    該方法會(huì)生成一個(gè)傳統(tǒng)風(fēng)格的迭代器肮雨,用于訪問(wèn)元素遵堵。
    toArray()
    由于無(wú)法在運(yùn)行時(shí)創(chuàng)建一個(gè)泛型數(shù)組,所以表達(dá)式stream.toArray()會(huì)返回一個(gè)Object[]數(shù)組怨规。如果希望得到一個(gè)正確類型的數(shù)組陌宿,可以將類型傳遞給數(shù)組的構(gòu)造函數(shù):
String[] result = String.of("abc", "bcd", "cde").toArray(String[]::new);

collect()

  • collect(Supplier, BiConsumer, BiConsumer)
    該方法接收三個(gè)參數(shù):

    1. 一個(gè)能創(chuàng)建目標(biāo)類型實(shí)例的方法,例如HashSet的構(gòu)造方法
    2. 一個(gè)將元素添加到目標(biāo)中的方法波丰,例如一個(gè)add方法
    3. 一個(gè)將兩個(gè)對(duì)象整合到一起的方法壳坪,例如addAll方法

    下面是如何使用HashSet的collect方法的示例:

HashSet<String> result = String.of("abc", "bcd", "abc").collect(HashSet::new, HashSet::add, HashSet::addAll);
  • collect(Collector)
    上面介紹了需要接收三個(gè)參數(shù)的collect方法,在實(shí)際中掰烟,并不需要這么做爽蝴,因?yàn)镃ollector接口已經(jīng)為我們提供了這三個(gè)方法,并且Collectors類還為常用的手機(jī)類型提供了各個(gè)工廠方法纫骑。
    要將一個(gè)流收集到一個(gè)list或者set中蝎亚,只需要調(diào)用:
List<String> result = String.of("abc", "bcd").collect(Collectors.toList());
Set<String> result = String.of("abc", "bcd", "abc").collect(Collectors.toSet());

如果希望控制得到的set類型,可以使用如下方式:

TreeSet<String> result = String.of("abc", "bcd", "abc").collect(Collectors.toCollection(TreeSet::new));

假設(shè)有一個(gè)Steam<Person>對(duì)象先馆,并且希望將其中的元素收集到一個(gè)map中发框,這樣隨后可以通過(guò)它們的id來(lái)查找。Collectors.toMap方法有兩個(gè)函數(shù)參數(shù)磨隘,分別用來(lái)生成map的鍵和值缤底。例如:

Map<Integer, String> idToName = persons.collect(Collectors.toMap(Person::getId, Person::getName));
Map<Integer, Person> idToPerson = persons.collect(Collectors.toMap(Person::getId, Function.identity()));

forEach()顾患, forEachOrdered()
當(dāng)只要將它們打印出來(lái)番捂,或逐個(gè)遍歷它們,那么可以使用forEach方法江解,如下:

Stream.of("abc", "bcd", "cdf").forEach(System.out::println);

向該方法傳遞的函數(shù)會(huì)被應(yīng)用到流中的每個(gè)元素上设预。需要注意的是,在一個(gè)并行流上犁河,要確保該函數(shù)可以被并發(fā)執(zhí)行鳖枕。
在一個(gè)并行流上,可能會(huì)以任意的順序來(lái)訪問(wèn)元素桨螺。如果希望按照流的順序來(lái)執(zhí)行它們宾符,那么可以使用forEachOrdered方法。
forEach方法和forEachOrdered方法都是終止操作灭翔。因此在調(diào)用它們之后魏烫,就不能再使用這個(gè)流了。如果希望還能繼續(xù)使用這個(gè)流,請(qǐng)使用peek方法哄褒。

其他

  1. 原始類型流
    假設(shè)有一個(gè)整型數(shù)組稀蟋,并將該數(shù)組收集到一個(gè)Stream<Integer>的流中,不過(guò)獎(jiǎng)每個(gè)證書(shū)包裝成Integer對(duì)象顯然是一個(gè)低效的做法呐赡,對(duì)于其他原始類型double退客、float、long链嘀、short萌狂、char、byte及boolean也是一樣怀泊。為此粥脚,Stream API提供了IntStream和LongStream和DoubleStream三種類型,專門(mén)用來(lái)直接存儲(chǔ)原始類型值包个,不必使用包裝刷允,而Stream API設(shè)計(jì)者認(rèn)為不需要為其它5種原始類型都添加對(duì)應(yīng)的專門(mén)類型。

    要?jiǎng)?chuàng)建一個(gè)IntStream碧囊,可以調(diào)用IntStream.of和Arrays.stream方法:

IntStream stream = IntStream.of(1, 3, 5, 7);
IntStream stream = Arrays.stream(values, from, to); // values是一個(gè)int[]數(shù)組
  1. 并行流
    流使得并行計(jì)算變得容易树灶。默認(rèn)情況下,流操作會(huì)創(chuàng)建一個(gè)串行流糯而,方法Collection.parallelStream()除外天通。parallel方法可以將任意的串行流轉(zhuǎn)換為一個(gè)并行流。

    一個(gè)并行流熄驼,只要在終止方法執(zhí)行前像寒,流處于并行模式,那么所有延遲執(zhí)行的流操作就都會(huì)被并行執(zhí)行瓜贾。

    當(dāng)并行運(yùn)行流操作時(shí)诺祸,需要確保傳遞給并行流操作的函數(shù)都是線程安全的,應(yīng)當(dāng)返回與串行運(yùn)行時(shí)相同的結(jié)果祭芦。很重要的一點(diǎn)是筷笨,這些操作都是無(wú)狀態(tài)的,因此可以以任意順序被執(zhí)行龟劲。

    默認(rèn)情況下胃夏,從有序集合、范圍值昌跌、生成器及迭代器仰禀,或者調(diào)用Stream.storted所產(chǎn)生的流,都是有序的蚕愤。有序并不會(huì)妨礙并行答恶,例如囊榜,當(dāng)計(jì)算stream.map(fun)時(shí),流可以被分為n段亥宿,每一段都會(huì)被并發(fā)處理卸勺。然后再按順序?qū)⒔Y(jié)果組合起來(lái)。

    當(dāng)不考慮有序時(shí)烫扼,一些操作可以更有效地并行運(yùn)行曙求。調(diào)用Stream.unordered方法可以不關(guān)心順序。比如映企,可以放棄有序來(lái)加快limit方法的速度悟狱。如果只需要一個(gè)流中的任意n個(gè)元素,并不關(guān)心具體內(nèi)容時(shí)堰氓,可以調(diào)用:

Stream<String> stream = stringStream.parallel().unordered().limit(n);
  1. 函數(shù)式接口
    在前文中挤渐,你已經(jīng)了解了許多參數(shù)為函數(shù)的操作。例如双絮,Stream.filter方法就將一個(gè)函數(shù)作為參數(shù)浴麻,filter方法的描述如下:
Stream<T> filter( Predicate<? super T> predicate )

filter方法的使用例子,如下:

Stream<String> longWords = words.filter( s -> s.length() >= 12 );
//words是一個(gè)含有多個(gè)字符串的流

查看文檔可以知道囤攀,Predicate是一個(gè)接口软免,只含有一個(gè)返回boolean值的非默認(rèn)方法:

public interface Predicate {
        boolean test(T argument);
}

在實(shí)際開(kāi)發(fā)中,開(kāi)發(fā)人員可能會(huì)經(jīng)常傳一個(gè)lambda表達(dá)式或者方法引用焚挠,所以方法名并不重要膏萧。重要的部分是返回boolean值。當(dāng)查閱文檔時(shí)蝌衔,只需要記住Predicate是一個(gè)返回boolean值的函數(shù)就行了榛泛。

下表總結(jié)了能夠作為Stream和Collectors方法參數(shù)的函數(shù)式接口。

函數(shù)式接口 參數(shù)類型 返回類型 描述
Supplier<T> 無(wú) T 提供一個(gè)T類型的值
Consumer<T> T void 處理一個(gè)T類型的值
BiConsumer<T, U> T, U void 處理T類型和U類型的值
Predicate<T> T boolean 一個(gè) 計(jì)算Boolean值的函數(shù)
ToIntFunction<T>
ToLongFunction<T>
ToDoubleFunction<T>
T int
long
double
分別計(jì)算int噩斟、long曹锨、double值的函數(shù)
IntFunction<R>
LongFunction<R>
DoubleFunction<R>
int
long
double
R 參數(shù)分別為int、long亩冬、double類型的函數(shù)
Function<T, R> T R 一個(gè)參數(shù)類型為T(mén)的函數(shù)
BiFunction<T, U, R> T, U R 一個(gè)參數(shù)類型為T(mén)和U的函數(shù)
UnaryOperator<T> T T 對(duì)類型T進(jìn)行的一元操作
BinaryOperator<T> T, T T 對(duì)類型T進(jìn)行的二元操作
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末艘希,一起剝皮案震驚了整個(gè)濱河市硼身,隨后出現(xiàn)的幾起案子硅急,更是在濱河造成了極大的恐慌,老刑警劉巖佳遂,帶你破解...
    沈念sama閱讀 218,036評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件营袜,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡丑罪,警方通過(guò)查閱死者的電腦和手機(jī)荚板,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,046評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)凤壁,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人跪另,你說(shuō)我怎么就攤上這事拧抖。” “怎么了免绿?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,411評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵唧席,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我嘲驾,道長(zhǎng)淌哟,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,622評(píng)論 1 293
  • 正文 為了忘掉前任辽故,我火速辦了婚禮徒仓,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘誊垢。我一直安慰自己掉弛,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,661評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布喂走。 她就那樣靜靜地躺著狰晚,像睡著了一般。 火紅的嫁衣襯著肌膚如雪缴啡。 梳的紋絲不亂的頭發(fā)上壁晒,一...
    開(kāi)封第一講書(shū)人閱讀 51,521評(píng)論 1 304
  • 那天,我揣著相機(jī)與錄音业栅,去河邊找鬼秒咐。 笑死,一個(gè)胖子當(dāng)著我的面吹牛碘裕,可吹牛的內(nèi)容都是我干的携取。 我是一名探鬼主播,決...
    沈念sama閱讀 40,288評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼帮孔,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼雷滋!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起文兢,我...
    開(kāi)封第一講書(shū)人閱讀 39,200評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤晤斩,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后姆坚,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體澳泵,經(jīng)...
    沈念sama閱讀 45,644評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,837評(píng)論 3 336
  • 正文 我和宋清朗相戀三年兼呵,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了兔辅。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片腊敲。...
    茶點(diǎn)故事閱讀 39,953評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖维苔,靈堂內(nèi)的尸體忽然破棺而出碰辅,到底是詐尸還是另有隱情,我是刑警寧澤介时,帶...
    沈念sama閱讀 35,673評(píng)論 5 346
  • 正文 年R本政府宣布乎赴,位于F島的核電站,受9級(jí)特大地震影響潮尝,放射性物質(zhì)發(fā)生泄漏榕吼。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,281評(píng)論 3 329
  • 文/蒙蒙 一勉失、第九天 我趴在偏房一處隱蔽的房頂上張望羹蚣。 院中可真熱鬧,春花似錦乱凿、人聲如沸顽素。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,889評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)胁出。三九已至,卻和暖如春段审,著一層夾襖步出監(jiān)牢的瞬間全蝶,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,011評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工寺枉, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留抑淫,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,119評(píng)論 3 370
  • 正文 我出身青樓姥闪,卻偏偏與公主長(zhǎng)得像始苇,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子筐喳,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,901評(píng)論 2 355

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

  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理催式,服務(wù)發(fā)現(xiàn),斷路器避归,智...
    卡卡羅2017閱讀 134,657評(píng)論 18 139
  • Java8 in action 沒(méi)有共享的可變數(shù)據(jù)荣月,將方法和函數(shù)即代碼傳遞給其他方法的能力就是我們平常所說(shuō)的函數(shù)式...
    鐵牛很鐵閱讀 1,229評(píng)論 1 2
  • 關(guān)于 本文是對(duì) Brian Goetz的State of the Lambda: Libraries Editio...
    aaron688閱讀 1,342評(píng)論 0 5
  • 第一章 為什么要關(guān)心Java 8 使用Stream庫(kù)來(lái)選擇最佳低級(jí)執(zhí)行機(jī)制可以避免使用Synchronized(同...
    謝隨安閱讀 1,491評(píng)論 0 4
  • 本文采用實(shí)例驅(qū)動(dòng)的方式喉童,對(duì)JAVA8的stream API進(jìn)行一個(gè)深入的介紹。雖然JAVA8中的stream AP...
    浮梁翁閱讀 25,754評(píng)論 3 50