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ū)別的:
- Stream自己不會(huì)存儲(chǔ)元素。元素可能被存儲(chǔ)在底層的集合中访敌,或者根據(jù)需要產(chǎn)生出來(lái)凉敲。
- Stream操作符不會(huì)改變?cè)磳?duì)象。相反寺旺,它們會(huì)返回一個(gè)持有結(jié)果的新Stream爷抓。
- 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è)操作流水線凳寺。
- 創(chuàng)建一個(gè)Stream
- 在一個(gè)或多個(gè)步驟中,指定將初始Stream轉(zhuǎn)換為另一個(gè)Stream的中間操作拴袭。
- 使用一個(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
- Java8在Collection接口中新添加的stream方法蒸眠,可以將任何集合轉(zhuǎn)化為一個(gè)Stream
- 如果是一個(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);
- 要?jiǎng)?chuàng)建一個(gè)不含任何元素的Stream楞卡,可以使用靜態(tài)的Stream.empty()
- 創(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ě)入另一流中成黄。
- 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));
- 提取子流和組合流
- 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']
- 有狀態(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ù)中找到“答案”朦拖。
-
聚合方法
在本節(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)提高速度。
-
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ù)
暫略诵次。
-
聚合操作
略。 -
收集結(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ù):- 一個(gè)能創(chuàng)建目標(biāo)類型實(shí)例的方法,例如HashSet的構(gòu)造方法
- 一個(gè)將元素添加到目標(biāo)中的方法波丰,例如一個(gè)add方法
- 一個(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方法哄褒。
其他
-
原始類型流
假設(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ù)組
-
并行流
流使得并行計(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);
- 函數(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)行的二元操作 |