欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java8中的Stream流式操作教程之王者歸來

 更新時間:2019年09月06日 10:51:09   作者:歐陽思海  
這篇文章主要給大家介紹了關(guān)于Java8中Stream流式操作的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家學(xué)習(xí)或者使用Java8具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧

前言

相對于Java8之前的Java的相關(guān)操作簡直是天差地別,Java8 的流式操作的出現(xiàn),也很大程度上改變了開發(fā)者對于Java的繁瑣的操作的印象,從此,Java也走向了函數(shù)式編程的道路!

1 流的創(chuàng)建

1.1 流的創(chuàng)建方法

既然需要聊聊流的操作,那么,首先還是先看看怎么創(chuàng)建流。

創(chuàng)建流的方法有三種,分別是:Stream.of()、Stream.iterate()、Stream.generate(),然后,分別看一下這三個方法的聲明。

static <T> Stream<T> of(T... values)

static <T> Stream<T> iterate(T seed, UnaryOperator<T> f)

static <T> Stream<T> generate(Supplier<T> s)

Stream.of():參數(shù)很簡單,就是一系列的泛型參數(shù)。Stream.iterate():第一個參數(shù)是一個初始值,第二個參數(shù)是一個操作。

Stream.generate():參數(shù)就是一個Supplier的供給型的參數(shù)。

1.2 流的創(chuàng)建方法舉例

/*
 * @Author 歐陽思海
 * @Description 創(chuàng)建流
 * @Date 11:05 2019/8/26
 * @Param []
 * @return void
 **/
 @Test
 public void testCreateStream() {
 //利用Stream.of方法創(chuàng)建流
 Stream<String> stream = Stream.of("hello", "world", "Java8");
 stream.forEach(System.out::println);
 System.out.println("##################");
 //利用Stream.iterate方法創(chuàng)建流
 Stream.iterate(10, n -> n + 1)
 .limit(5)
 .collect(Collectors.toList())
 .forEach(System.out::println);
 System.out.println("##################");
 //利用Stream.generate方法創(chuàng)建流
 Stream.generate(Math::random)
 .limit(5)
 .forEach(System.out::println);
 System.out.println("##################");
 //從現(xiàn)有的集合中創(chuàng)建流
 List<String> strings = Arrays.asList("hello", "world", "Java8");
 String string = strings.stream().collect(Collectors.joining(","));
 System.out.println(string);
 }


在上面的例子中,Stream.of()方法的參數(shù)是幾個字符串,Stream.iterate()方法的第一個參數(shù)是初始值 10,第二個參數(shù)是在10 的基礎(chǔ)上每次加 1 的操作,Stream.generate()的參數(shù)是用 Random 方法產(chǎn)生隨機數(shù)。

1.3 流的創(chuàng)建總結(jié)

流的創(chuàng)建有三種方法,分別是Stream.of()、Stream.iterate()、Stream.generate(),這幾個都是 Stream 類的靜態(tài)方法,所以,使用起來非常的方便。

2 流的操作

在上一節(jié)中,我們知道怎么創(chuàng)建流了,接下來,我們就看看對流可以進行哪些操作,使用了 Stream 流之后,是否會比 Java8 之前方便很多呢?

2.1 裝箱流

在處理對象流的時候,可以利用 Collectors 類的靜態(tài)方法轉(zhuǎn)換為集合,例如,將字符串流轉(zhuǎn)換為  List ,這種方式是沒有問題的。

但是,如果遇到 double流想要轉(zhuǎn)換為 List 時,這是就會報錯。

DoubleStream.of(1.0, 2.0, 3.0)
 .collect(Collectors.toList());//錯誤的寫法

這種方式就是錯誤的,編譯是不能通過的。

別慌,對于這種問題,有 3 種比較好的解決方法。

利用 boxed 方法

利用 boxed 方法,可以將 DoubleStream 轉(zhuǎn)換為 Stream ,例如;

DoubleStream.of(1.0, 2.0, 3.0)
  .boxed()
  .collect(Collectors.toList());

這樣就解決了上面的問題。

利用 mapToObj 方法

利用 mapToObj 方法也可以實現(xiàn)上面的功能,另外,也提供了 mapToInt、mapToLong、mapToDouble 等方法將基本類型流轉(zhuǎn)換為相關(guān)包裝類型。

DoubleStream.of(1.0, 2.0, 3.0)
  .boxed()
  .collect(Collectors.toList());

collect 方法

一般情況下,我們利用 collect 方法的時候,都是用于將流的數(shù)據(jù)收集為基本類型的集合,例如;

stream.collect(Collectors.toList())

然而,collect 方法其實還有一種更加一般化的形式,如下;

<R> R collect(Supplier<R> supplier,
   ObjIntConsumer<R> accumulator,
   BiCnsumer<R,R> combiner)

上面這種方法的第一個參數(shù)是一個供給器,相當(dāng)于初始化一個容器,第二個參數(shù)是累加器,相當(dāng)于給初始化的容器賦值,第三個參數(shù)是組合器,相當(dāng)于將這些元素全部組合到一個容器。

下面,我們通過一個簡單的例子來看看到底是怎么使用的!

List<Double> list = DoubleStream.of(1.0, 2.0, 3.0)
  .collect(ArrayList<Double>::new, ArrayList::add, ArrayList::addAll);

上面的例子我們可以看到,第一個參數(shù):使用一個靜態(tài)方法初始化一個 List 容器,第二個參數(shù):使用靜態(tài)方法 add ,添加元素,第三個參數(shù):使用靜態(tài)方法 addAll ,用于聯(lián)合所有的元素。

從最后的返回值為 List,我們也可以看出,全部組合成一個初始化的 List 集合中了。

2.2 字符串與流之間的轉(zhuǎn)換

這一小節(jié)主要講解一下字符串與流之間的轉(zhuǎn)換,將 String 轉(zhuǎn)為流有兩種方法,分別是 java.lang.CharSequence 接口定義的默認方法 chars 和 codePoints ,而將流轉(zhuǎn)為字符串就是我們前面已經(jīng)講解到的方法 collect 。

/*
 * @Author 歐陽思海
 * @Description 字符串與流之間的轉(zhuǎn)換
 * @Date 9:41 2019/9/2
 * @Param []
 * @return void
 **/
 @Test
 public void testString2Stream() {
 String s = "hello world Java8".codePoints()//轉(zhuǎn)換成流
  .collect(StringBuffer::new,
   StringBuffer::appendCodePoint,
   StringBuffer::append)//將流轉(zhuǎn)換為字符串
  .toString();

 String s1 = "hello world Java8".chars()//轉(zhuǎn)換成流
  .collect(StringBuffer::new,
   StringBuffer::appendCodePoint,
   StringBuffer::append)//將流轉(zhuǎn)換為字符串
  .toString();
 }

在上面的例子中,先用chars 和 codePoints 方法轉(zhuǎn)換為流,然后都是利用 collect 方法再轉(zhuǎn)回字符串。

2.3 流的映射 map 與 flatMap

流的映射是什么意思呢,我們先將一個在 Java8 之前的例子,我們常常需要將一個集合的對象的某一個字段取出來,然后再存到另外一個集合中,這種場景我們在 Java8 之前我們會這樣實現(xiàn)。

/*
 * @Author 歐陽思海
 * @Description Java8之前的用法
 * @Date 19:31 2019/9/2
 * @Param []
 * @return void
 **/
 @Test
 public void testList() {
 List<Person> list = new ArrayList<>();
 List<Friend> friends = new ArrayList<>();
 friends.add(new Friend("Java5"));
 friends.add(new Friend("Java6"));
 friends.add(new Friend("Java7"));
 Person person = new Person();
 person.setFriends(friends);
 list.add(person);

 List<String> strings = new ArrayList<>();

 for(Person p : list){
  strings.add(p.getName());
 }
 }

是不是這樣很麻煩,這也就是以前大家一直所說的 Python 用一招,Java 需要用花招!

但是,Java8 卻改變了這種現(xiàn)實,我們來看一看怎么使用 map 和 flatMap。

首先,我們先看一下這倆個方法的聲明;

<R> Stream<R> map(Function<? super T,? extends R> mapper)

<R> Stream<R> flatMap(Function<? super T,? extends Stream<? extends R>> mapper)

接下來,我們用這兩個方法改寫上面的方式,先看看 map 方法;

/*
 * @Author 歐陽思海
 * @Description map、flatMap方法
 * @Date 9:50 2019/9/2
 * @Param []
 * @return void
 **/
 @Test
 public void testMapAndFlatMap() {
 List<Person> list = new ArrayList<>();
 List<Friend> friends = new ArrayList<>();
 friends.add(new Friend("Java5"));
 friends.add(new Friend("Java6"));
 friends.add(new Friend("Java7"));
 Person person = new Person();
 person.setFriends(friends);
 list.add(person);

 //映射出名字
 List<String> strings = list.stream().map(Person::getName).collect(Collectors.toList());
 }

通過使用 map 方法,參數(shù)給定 Person::getName 映射出 name,然后再用 collect 收集到 List 中,就完成了上面的負責(zé)的操作,是不是很舒服。

但是,如果我們用 map 方法想要映射出 friends 屬性,會遇到一個問題;

//映射出朋友
  List<List<Friend>> collect = list.stream().map(Person::getFriends).collect(Collectors.toList());

我們發(fā)現(xiàn),上面的返回值是 List>,這種形式集合里面還包著集合,處理有點麻煩,但是,不是還有另外 flatMap 沒有使用嗎,這個方法正好能夠解決這個問題。

List<Friend> collect1 = list.stream().flatMap(friend -> friend.getFriends().stream()).collect(Collectors.toList());

發(fā)現(xiàn),這個方法的返回值是 List,正如我們看到的,flatMap 的方法能夠“展平”包裹的流,這就是 map 和 flatMap 的區(qū)別。

2.4 流的連接

流的連接有兩種方式,如果是兩個流的連接,使用 Stream.concat 方法,如果是三個及三個以上的流的連接,就使用 Stream.flatMap 方法。

/**
  * @return void
  * @Author 歐陽思海
  * @Description 流的連接
  * @Date 10:13 2019/9/2
  * @Param []
  **/
 @Test
 public void testConcatStream() {
  //兩個流的連接
  Stream<String> first = Stream.of("sihai", "sihai2", "sihai3");
  Stream<String> second = Stream.of("sihai4", "sihai5", "sihai6");
  Stream<String> third = Stream.of("siha7", "sihai8", "sihai9");
  Stream<String> concat = Stream.concat(first, second);

  //多個流的連接
  Stream<String> stringStream = Stream.of(first, second, third).flatMap(Function.identity());

 }

3 流的規(guī)約操作

流的規(guī)約操作幾種類型,這里都講一下。

內(nèi)置的規(guī)約操作

基本類型流都有內(nèi)置的規(guī)約操作。包括average、count、max、min、sum、summaryStatistics,前面的幾個方法相信不用說了,summaryStatistics 方法是前面的幾個方法的結(jié)合,下面我們看看他們?nèi)绾问褂谩?br />

/**
  * @return void
  * @Author 歐陽思海
  * @Description 內(nèi)置規(guī)約操作
  * @Date 22:04 2019/9/1
  * @Param []
  **/
 @Test
 public void testReduce1() {
  String[] strings = {"hello", "sihai", "hello", "Java8"};
  long count = Arrays.stream(strings)
    .map(String::length)
    .count();
  System.out.println(count);

  System.out.println("##################");

  int sum = Arrays.stream(strings)
    .mapToInt(String::length)
    .sum();
  System.out.println(sum);

  System.out.println("##################");

  OptionalDouble average = Arrays.stream(strings)
    .mapToInt(String::length)
    .average();
  System.out.println(average);

  System.out.println("##################");

  OptionalInt max = Arrays.stream(strings)
    .mapToInt(String::length)
    .max();
  System.out.println(max);

  System.out.println("##################");

  OptionalInt min = Arrays.stream(strings)
    .mapToInt(String::length)
    .min();
  System.out.println(min);

  DoubleSummaryStatistics statistics = DoubleStream.generate(Math::random)
    .limit(1000)
    .summaryStatistics();
  System.out.println(statistics);
 }


就是這么簡單!

基本的規(guī)約操作

基本的規(guī)約操作是利用前面講過的 reduce 方法實現(xiàn)的,IntStream 接口定義了三種 reduce 方法的重載形式,如下;

OptionalInt reduce(IntBinaryOperator op)

int reduce(int identity, IntBianryOperator op)

<U> U reduce(U identity,
  BiFunction<U,? super T,U> accumulator,
  BianryOperator<U> combiner)

上面的 identity 參數(shù)就是初始化值的意思,IntBianryOperator 類型的參數(shù)就是操作,例如 lambda 表達式;

BianryOperator combiner是一個組合器,在前面有講過。

下面我們通過一個例子來講解一下。

/**
  * @return void
  * @Author 歐陽思海
  * @Description reduce規(guī)約操作
  * @Date 22:20 2019/9/1
  * @Param []
  **/
 @Test
 public void testReduce2() {
  int sum = IntStream.range(1, 20)
    .reduce((x, y) -> x + y)
    .orElse(0);
  System.out.println(sum);

  System.out.println("##################");

  int sum2 = IntStream.range(1, 20)
    .reduce(0, (x, y) -> x + 2 * y);
  System.out.println(sum2);

  System.out.println("##################");

  int sum3 = IntStream.range(1, 20)
    .reduce(0, Integer::sum);
  System.out.println(sum3);

 }


例子中的第一個是1到20累加的操作,第二個以0為初始值,然后2倍累加,第三個是以0為初始值,累加。

流的計數(shù)

流的數(shù)量統(tǒng)計有兩種方法,分別是 Stream.count() 方法和 Collectors.counting() 方法。

/**
  * @return void
  * @Author 歐陽思海
  * @Description 統(tǒng)計測試
  * @Date 23:29 2019/9/1
  * @Param []
  **/
 @Test
 public void testStatistics() {
  //統(tǒng)計數(shù)量
  String[] strings = {"hello", "sihai", "hello", "Java8"};
  long count = Arrays.stream(strings)
    .count();
  System.out.println(count);

  System.out.println("##################");

  Long count2 = Arrays.stream(strings)
    .collect(Collectors.counting());
  System.out.println(count2);
  
 }

4 流的查找與匹配

流的查找

流的查找 Stream 接口提供了兩個方法 findFirst 和 findAny。

findFirst 方法返回流中的第一個元素的 Optional,而 findAny 方法返回流中的某個元素的 Optional。

我們來看一個例子。

  String[] strings = {"hello", "sihai", "hello", "Java8"};
  Optional<String> first = Arrays.stream(strings)
    .findFirst();
  System.out.println(first.get());

  System.out.println("##################");

  Optional<String> any = Arrays.stream(strings).findAny();
  System.out.println(any.get());

  System.out.println("##################");

流的匹配

流的匹配 Stream 接口提供了三個方法,分別是 anyMatch(任何一個元素匹配,返回 true)、allMatch(所有元素匹配,返回 true)、noneMatch(沒有一個元素匹配,返回 true)。

  boolean b = Stream.of(1, 2, 3, 4, 5, 10)
    .anyMatch(x -> x > 5);
  System.out.println(b);

  System.out.println("##################");

  boolean b2 = Stream.of(1, 2, 3, 4, 5, 10)
    .allMatch(x -> x > 5);
  System.out.println(b2);

  System.out.println("##################");

  boolean b3 = Stream.of(1, 2, 3, 4, 5, 10)
    .noneMatch(x -> x > 5);
  System.out.println(b3);

5 流的總結(jié)

這篇文章主要講解了流的一些操作,包括下面幾個方面。

- 流的創(chuàng)建方法。

- 流的系列操作,包括裝箱流、字符串與流之間的轉(zhuǎn)換、流和映射 map 和 flatMap、流的連接。

- 流的規(guī)約操作

- 流的查找與匹配

總結(jié)

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,謝謝大家對腳本之家的支持。

相關(guān)文章

  • Java開發(fā)常用類庫之Hutool詳解

    Java開發(fā)常用類庫之Hutool詳解

    這篇文章主要介紹了Java開發(fā)常用類庫之Hutool,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-02-02
  • IDEA一致卡在build時間過長問題解決

    IDEA一致卡在build時間過長問題解決

    有很多小伙伴在起項目的時候巨慢,特別影響開發(fā)效率,本文主要介紹了IDEA一致卡在build時間過長問題解決,具有一定的參考價值,感興趣的可以了解一下
    2024-06-06
  • 基于SpringBoot加載Mybatis的TypeAlias問題

    基于SpringBoot加載Mybatis的TypeAlias問題

    這篇文章主要介紹了解決SpringBoot加載Mybatis的TypeAlias問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • Java pdf和jpg互轉(zhuǎn)案例

    Java pdf和jpg互轉(zhuǎn)案例

    這篇文章主要介紹了Java pdf和jpg互轉(zhuǎn)案例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-09-09
  • java中this關(guān)鍵字的詳細使用介紹

    java中this關(guān)鍵字的詳細使用介紹

    大家好,本篇文章主要講的是java中this關(guān)鍵字的詳細使用介紹,感興趣的同學(xué)趕快來看一看吧,對你有幫助的話記得收藏一下,方便下次瀏覽
    2022-01-01
  • Java應(yīng)用啟動停止重啟Shell腳本模板server.sh

    Java應(yīng)用啟動停止重啟Shell腳本模板server.sh

    這篇文章主要為大家介紹了Java應(yīng)用啟動、停止、重啟Shell腳本模板server.sh,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-08-08
  • Java為什么基本數(shù)據(jù)類型不需要進行創(chuàng)建對象?

    Java為什么基本數(shù)據(jù)類型不需要進行創(chuàng)建對象?

    今天小編就為大家分享一篇關(guān)于Java為什么基本數(shù)據(jù)類型不需要進行創(chuàng)建對象?,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-04-04
  • Hibernate三種狀態(tài)和Session常用的方法

    Hibernate三種狀態(tài)和Session常用的方法

    本文主要介紹了Hibernate三種狀態(tài)和Session常用的方法,具有很好的參考價值,下面跟著小編一起來看下吧
    2017-03-03
  • SpringBoot中的MongoTemplate的各種條件查詢示例詳解

    SpringBoot中的MongoTemplate的各種條件查詢示例詳解

    這篇文章主要介紹了SpringBoot中的MongoTemplate的各種條件查詢示例詳解,本文通過示例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借價值,需要的朋友參考下吧
    2024-01-01
  • Java 中FastJson的基本使用

    Java 中FastJson的基本使用

    fastjson 是一個性能很好的 Java 語言實現(xiàn)的 JSON 解析器和生成器,來自阿里巴巴的工程師開發(fā)。下面通過本文給大家介紹Java 中FastJson的基本使用,需要的朋友參考下吧
    2017-11-11

最新評論