成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Java8-9-Stream介紹與操作方式詳解

時(shí)飛 / 2774人閱讀

摘要:中的與表達(dá)式可以說是相伴相生的,通過我們可以更好的更為流暢更為語義化的操作集合。流是一種惰性操作,所有對源數(shù)據(jù)的計(jì)算只在終止操作被初始化的時(shí)候才會(huì)執(zhí)行。然后傳入表達(dá)式將每個(gè)元素轉(zhuǎn)換大寫,通過方法將結(jié)果收集到中。

上一篇系統(tǒng)學(xué)了方法引用的幾種類型及應(yīng)用場景,本篇開始我們正式學(xué)習(xí)Stream。
Java8中的Stream與lambda表達(dá)式可以說是相伴相生的,通過Stream我們可以更好的更為流暢更為語義化的操作集合。Stream api都位于java.util.stream包中。其中就包含了最核心的Stream接口,一個(gè)Stream實(shí)例可以串行或者并行操作一組元素序列,官方文檔中給出了一個(gè)示例

 * 
{@code
 *     int sum = widgets.stream()//創(chuàng)建一個(gè)流
 *                      .filter(w -> w.getColor() == RED)//取出顏色是紅色的元素
 *                      .mapToInt(w -> w.getWeight())//返回每個(gè)紅色元素的重量
 *                      .sum();//重量求和
 * }

Java8中,所有的流操作會(huì)被組合到一個(gè) stream pipeline中,這點(diǎn)類似linux中的pipeline概念,將多個(gè)簡單操作連接在一起組成一個(gè)功能強(qiáng)大的操作。一個(gè) stream pileline首先會(huì)有一個(gè)數(shù)據(jù)源,這個(gè)數(shù)據(jù)源可能是數(shù)組、集合、生成器函數(shù)或是IO通道,流操作過程中并不會(huì)修改源中的數(shù)據(jù);然后還有零個(gè)或多個(gè)中間操作,每個(gè)中間操作會(huì)將接收到的流轉(zhuǎn)換成另一個(gè)流(比如filter);最后還有一個(gè)終止操作,會(huì)生成一個(gè)最終結(jié)果(比如sum)。流是一種惰性操作,所有對源數(shù)據(jù)的計(jì)算只在終止操作被初始化的時(shí)候才會(huì)執(zhí)行。

總結(jié)一下流操作由3部分組成
1.源
2.零個(gè)或多個(gè)中間操作
3.終止操作 (到這一步才會(huì)執(zhí)行整個(gè)stream pipeline計(jì)算)

創(chuàng)建流的幾種方式

//第一種 通過Stream接口的of靜態(tài)方法創(chuàng)建一個(gè)流
Stream stream = Stream.of("hello", "world", "helloworld");
//第二種 通過Arrays類的stream方法,實(shí)際上第一種of方法底層也是調(diào)用的Arrays.stream(values);
String[] array = new String[]{"hello","world","helloworld"};
Stream stream3 = Arrays.stream(array);
//第三種 通過集合的stream方法,該方法是Collection接口的默認(rèn)方法,所有集合都繼承了該方法
Stream stream2 = Arrays.asList("hello","world","helloworld").stream();

接下來我們看一個(gè)簡單的需求:將流中字符全部轉(zhuǎn)成大寫返回一個(gè)新的集合

List list = Arrays.asList("hello", "world", "helloworld");
List collect = list.stream().map(s -> s.toUpperCase()).collect(Collectors.toList());

這里我們使用了Stream的map方法,map方法接收一個(gè)Function函數(shù)式接口實(shí)例,這里的map和Hadoop中的map概念完全一致,對每個(gè)元素進(jìn)行映射處理。然后傳入lambda表達(dá)式將每個(gè)元素轉(zhuǎn)換大寫,通過collect方法將結(jié)果收集到ArrayList中。

 Stream map(Function mapper);//map函數(shù)定義

那如果我們想把結(jié)果放到Set中或者替他的集合容器,也可以這樣

list.stream().map(s -> s.toUpperCase()).collect(Collectors.toSet());//放到Set中

或者更為通用的

list.stream().map(s -> s.toUpperCase()).collect(Collectors.toCollection(TreeSet::new));//自定義容器類型

我們可以自己制定結(jié)果容器的類型Collectors的toCollection接受一個(gè)Supplier函數(shù)式接口類型參數(shù),可以直接使用構(gòu)造方法引用的方式。

Stream中除了map方法對元素進(jìn)行映射外,還有一個(gè)flatMap方法

 Stream flatMap(Function> mapper);

flatMap從方法命名上可以解釋為扁平的map


map方法是將一個(gè)容器里的元素映射到另一個(gè)容器中。

flatMap方法,可以將多個(gè)容器的元素全部映射到一個(gè)容器中,即為扁平的map。
看一個(gè)求每個(gè)元素平方的例子

Stream> listStream =
                Stream.of(Arrays.asList(1), Arrays.asList(2, 3), Arrays.asList(4, 5, 6));
List collect1 = listStream.flatMap(theList -> theList.stream()).
                map(integer -> integer * integer).collect(Collectors.toList());

首先我們創(chuàng)建了一個(gè)Stream對象,Stream中的每個(gè)元素都是容器List類型,并使用三個(gè)容器list初始化這個(gè)Stream對象,然后使用flatMap方法將每個(gè)容器中的元素映射到一個(gè)容器中,這時(shí)flatMap接收的參數(shù)Funciton的泛型T就是List類型,返回類型就是T對應(yīng)的Stream。最后再對這個(gè)容器使用map方法求出買個(gè)元素的平方。

然后介紹一個(gè)用于獲取統(tǒng)計(jì)信息的方法

//同時(shí)獲取最大 最小 平均值等信息
List list1 = Arrays.asList(1, 3, 5, 7, 9, 11);
IntSummaryStatistics statistics = list1.stream().filter(integer -> integer > 2).mapToInt(i -> i * 2).skip(2).limit(2).summaryStatistics();
System.out.println(statistics.getMax());//18
System.out.println(statistics.getMin());//14
System.out.println(statistics.getAverage());//16

將list1中的數(shù)據(jù)取出大于2的,每個(gè)數(shù)進(jìn)行平方計(jì)算,skip(2)忽略前兩個(gè),limit(2)再取出前兩個(gè),summaryStatistics對取出的這兩個(gè)數(shù)計(jì)算統(tǒng)計(jì)數(shù)據(jù)。mapToInt接收一個(gè)ToIntFunction類型,也就是接收一個(gè)參數(shù)返回值是int類型。

接下來看一下Stream中的一個(gè)靜態(tài)方法,generate方法

/**
 * Returns an infinite sequential unordered stream where each element is
 * generated by the provided {@code Supplier}.  This is suitable for
 * generating constant streams, streams of random elements, etc.
 *
 * @param  the type of stream elements
 * @param s the {@code Supplier} of generated elements
 * @return a new infinite sequential unordered {@code Stream}
 */
public static Stream generate(Supplier s) {
    Objects.requireNonNull(s);
    return StreamSupport.stream(
            new StreamSpliterators.InfiniteSupplyingSpliterator.OfRef<>(Long.MAX_VALUE, s), false);
}

generate接收一個(gè)Supplier,適合生成連續(xù)不斷的流或者一個(gè)全部是隨機(jī)數(shù)的流

Stream.generate(UUID.randomUUID()::toString).findFirst().ifPresent(System.out::println);

使用UUID.randomUUID()::toString 方法引用的方式創(chuàng)建了Supplier,然后取出第一個(gè)元素,這里的findFirst返回的是 Optional,因?yàn)榱髦杏锌赡軟]有元素,為了避免空指針,在使用前 ifPresent 進(jìn)行是否存在的判斷。

最后再學(xué)習(xí)一下另一個(gè)靜態(tài)方法,iterate

/**
 * Returns an infinite sequential ordered {@code Stream} produced by iterative
 * application of a function {@code f} to an initial element {@code seed},
 * producing a {@code Stream} consisting of {@code seed}, {@code f(seed)},
 * {@code f(f(seed))}, etc.
 *
 * 

The first element (position {@code 0}) in the {@code Stream} will be * the provided {@code seed}. For {@code n > 0}, the element at position * {@code n}, will be the result of applying the function {@code f} to the * element at position {@code n - 1}. * * @param the type of stream elements * @param seed the initial element * @param f a function to be applied to to the previous element to produce * a new element * @return a new sequential {@code Stream} */ public static Stream iterate(final T seed, final UnaryOperator f) { Objects.requireNonNull(f); final Iterator iterator = new Iterator() { @SuppressWarnings("unchecked") T t = (T) Streams.NONE; @Override public boolean hasNext() { return true; } @Override public T next() { return t = (t == Streams.NONE) ? seed : f.apply(t); } }; return StreamSupport.stream(Spliterators.spliteratorUnknownSize( iterator, Spliterator.ORDERED | Spliterator.IMMUTABLE), false); }

iterate方法有兩個(gè)參數(shù),第一個(gè)是seed也可以稱作種子,第二個(gè)是一個(gè)UnaryOperator,UnaryOperator實(shí)際上是Function的一個(gè)子接口,和Funciton區(qū)別就是參數(shù)和返回類型都是同一種類型

@FunctionalInterface
public interface UnaryOperator extends Function {

}

iterate方法第一次生成的元素是UnaryOperator對seed執(zhí)行apply后的返回值,之后所有生成的元素都是UnaryOperator對上一個(gè)apply的返回值再執(zhí)行apply,不斷循環(huán)。
f(f(f(f(f(f(n))))))......

//從1開始,每個(gè)元素比前一個(gè)元素大2,最多生成10個(gè)元素
Stream.iterate(1,item -> item + 2).limit(10).forEach(System.out::println);

我們在使用stream api時(shí)也要注意一些陷阱,比如下面這個(gè)例子

//Stream陷阱 distinct()會(huì)一直等待產(chǎn)生的結(jié)果去重,將distinct()和limit(6)調(diào)換位置,先限制結(jié)果集再去重就可以了
IntStream.iterate(0,i -> (i + 1) % 2).distinct().limit(6).forEach(System.out::println);

如果distinct()一直等待那程序會(huì)一直執(zhí)行不斷生成數(shù)據(jù),所以需要先限制結(jié)果集再去進(jìn)行去重操作就可以了。

下一篇

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/70730.html

相關(guān)文章

  • 【連載】前端個(gè)人文章整理-從基礎(chǔ)到入門

    摘要:個(gè)人前端文章整理從最開始萌生寫文章的想法,到著手開始寫,再到現(xiàn)在已經(jīng)一年的時(shí)間了,由于工作比較忙,更新緩慢,后面還是會(huì)繼更新,現(xiàn)將已經(jīng)寫好的文章整理一個(gè)目錄,方便更多的小伙伴去學(xué)習(xí)。 showImg(https://segmentfault.com/img/remote/1460000017490740?w=1920&h=1080); 個(gè)人前端文章整理 從最開始萌生寫文章的想法,到著手...

    madthumb 評論0 收藏0
  • 前端每周清單第 55 期: MobX 4 特性概覽,iOS Hacks 分享, 分布式事務(wù)詳解

    摘要:異步剪貼板操作過去的數(shù)年中,各瀏覽器基本上都在使用來進(jìn)行剪貼板交互。而提供了新的,則為我們提供了另一種異步式的剪貼板操作方式,本文即是對該機(jī)制與接口規(guī)范的詳細(xì)介紹。 showImg(https://segmentfault.com/img/remote/1460000013854167); 前端每周清單第 55 期: MobX 4 特性概覽,iOS Hacks 分享, 分布式事務(wù)詳解 ...

    zombieda 評論0 收藏0
  • 后臺(tái)開發(fā)常問面試題集錦(問題搬運(yùn)工,附鏈接)

    摘要:基礎(chǔ)問題的的性能及原理之區(qū)別詳解備忘筆記深入理解流水線抽象關(guān)鍵字修飾符知識(shí)點(diǎn)總結(jié)必看篇中的關(guān)鍵字解析回調(diào)機(jī)制解讀抽象類與三大特征時(shí)間和時(shí)間戳的相互轉(zhuǎn)換為什么要使用內(nèi)部類對象鎖和類鎖的區(qū)別,,優(yōu)缺點(diǎn)及比較提高篇八詳解內(nèi)部類單例模式和 Java基礎(chǔ)問題 String的+的性能及原理 java之yield(),sleep(),wait()區(qū)別詳解-備忘筆記 深入理解Java Stream流水...

    spacewander 評論0 收藏0
  • 后臺(tái)開發(fā)常問面試題集錦(問題搬運(yùn)工,附鏈接)

    摘要:基礎(chǔ)問題的的性能及原理之區(qū)別詳解備忘筆記深入理解流水線抽象關(guān)鍵字修飾符知識(shí)點(diǎn)總結(jié)必看篇中的關(guān)鍵字解析回調(diào)機(jī)制解讀抽象類與三大特征時(shí)間和時(shí)間戳的相互轉(zhuǎn)換為什么要使用內(nèi)部類對象鎖和類鎖的區(qū)別,,優(yōu)缺點(diǎn)及比較提高篇八詳解內(nèi)部類單例模式和 Java基礎(chǔ)問題 String的+的性能及原理 java之yield(),sleep(),wait()區(qū)別詳解-備忘筆記 深入理解Java Stream流水...

    xfee 評論0 收藏0

發(fā)表評論

0條評論

最新活動(dòng)
閱讀需要支付1元查看
<