1. 程式人生 > >Java8新特性-Stream API 常用完整版

Java8新特性-Stream API 常用完整版

流(Stream)

1. 流的概念

流是資料渠道,用於操作資料來源,所生成一種新的元素序列。集合講的是資料,流講的是計算,是操作

Stream是Java8中處理集合的關鍵抽象概念,它可以指定希望對集合的操作,可以執行復雜的查詢過濾和對映資料等操作。

使用Stream API 對集合的資料進行操作,類似於SQL執行的資料庫查詢,也可以用來並行執行操作,其提供了一種高效且易於使用的處理資料方式

注意點:

  • Stream自身不會儲存元素
  • Stream不會改變資料來源物件,相反會返回產生一個持有結果的新Stream
  • Steam操作是延遲執行的,這意味著他們會等到需要結果的時候才執行

2. 流的操作步驟

三步走

2.1. 建立Stream

獲取一個數據源(集合,陣列),從而獲取一個流
產生方式:

2.1.1 通過Collection 系列集合提供的序列流:stream()並行流: paralleStream()

List<String> list = new ArrayList<>();
Stream<String> stream1 = list.stream();

2.1.2 通過Arrays中的靜態方法stream(T[] array) 獲取陣列流

Arrays.stream(T[] array)的原始碼:

public static <T> Stream<T> stream(T[] array) {
     return stream(array, 0, array.length);
 }

用例:

Stu[] stus = new Stu[10];
Stream<Stu> stream2 = Arrays.stream(stus);
/*
  public static <T> Stream<T> stream(T[] array) {
     return stream(array, 0, array.length);
 }
 */

2.1.3 通過Stream類中的靜態方法 of()

Stream.of() 原始碼:

//1.單參泛型of
 public static<T> Stream<T> of(T t) {
    return StreamSupport.stream(new Streams.StreamBuilderImpl<>(t), false);
}
//2.可變引數
@SafeVarargs
@SuppressWarnings("varargs") // Creating a stream from an array is safe
public static<T> Stream<T> of(T... values) {
    return Arrays.stream(values);
}

用例:

Stream<String> stream3 = Stream.of("hxh", "aj", "hhh");

2.1.4 使用Stream類的靜態方法 iterate 建立無限流

iterate方法:

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

引數 seed 種子起始值UnaryOperator 函式式介面 繼承Function<T,T> 此時引數型別符合返回值型別一致

用例:

//4.使用Stream類的靜態方法 iterate 建立無限流
//Stream<T> iterate(final T seed, final UnaryOperator<T> f) 
//引數 seed 種子起始值,
// UnaryOperator 函式式介面 繼承Function<T,T> 此時引數型別符合返回值型別一致

Stream<Integer> stream4 = Stream.iterate(0, (x) -> x + 2);
//中間操作和終止操作
stream4.limit(5).forEach(System.out::println);
//0
//2
//4
//6
//8

2.1.5 使用Stream類的靜態方法 generate建立無限流

generate方法引數為Supplier<T> 供給型介面

//5.使用Stream類的靜態方法 generate 建立無限流
//引數為Supplier<T> 供給型介面
Stream<Double> generateStream = Stream.generate(() -> Math.random());
generateStream.limit(5).forEach(System.out::println);
//0.4762976596937549
//0.08577913333772513
//0.32149010682857515
//0.31059489250233197
//0.45181354173159927

2.2. 用Stream中間操作

一箇中間操作鏈,用Stream API 對資料來源資料進行操作處理

注意點

  • 若只有中間操作,則不會執行
  • 只有終止操作執行後,所有的中間操作一次執行,此時就稱為延遲載入或者惰性求值

驗證是否是延遲載入:

@Test
public  void test2(){
    //取age>30的Stu元素
    //若只有中間操作,則不會執行
    Stream<Stu> stuStream = stuList.stream().filter((i) -> {
        System.out.println("驗證是否是延遲載入");
        return  i.getAge() > 40;
    });
    //此時只有中間操作,無終止操作,無結果,控制檯無輸出

}

此時只有中間操作,無終止操作無結果,控制檯無輸出

此時加上終止操作後:

@Test
public  void test2(){
    //取age>30的Stu元素
    //若只有中間操作,則不會執行
    Stream<Stu> stuStream = stuList.stream().filter((i) -> {
        System.out.println("驗證是否是延遲載入");
        return  i.getAge() > 40;
    });
    //終止操作 執行後,所有的中間操作一次執行,此時就稱為延遲載入或者惰性求值
    stuStream.forEach(System.out::println);
}

此時結果為:

驗證是否是延遲載入
驗證是否是延遲載入
驗證是否是延遲載入
驗證是否是延遲載入
Stu{id=4, name='cc', age=42}
驗證是否是延遲載入
Stu{id=5, name='dd', age=52}

結論:若只有中間操作,則不會執行中間操作。終止操作 執行後,所有的中間操作一次執行。最後流中只有經過操作過濾後的元素。

2.2.1 篩選與切片

迭代:
- 內部迭代:迭代過程操作由Stream API 內部自主完成,無需自行再次編寫。
- 外部迭代:由程式編寫人員自己通過一些迭代方法進行的迭代操作。

2.2.1.1 filter-過濾

Stream<T> filter(Predicate<? super T> predicate)
斷言型介面引數 即條件判斷過濾

用例:
先建立一個Stu類List集合

List<Stu> stuList = Arrays.asList(
        new Stu(1,"hh",22),
        new Stu(2,"aa",22),
        new Stu(3,"bb",32),
        new Stu(4,"cc",42),
        new Stu(5,"dd",52)
);

filter過濾實現:

//取age>30的Stu元素
//若只有中間操作,則不會執行
Stream<Stu> stuStream = stuList.stream()
    .filter((i) -> i.getAge() > 40);
//終止操作 執行後,所有的中間操作一次執行,此時就稱為延遲載入或者惰性求值
stuStream.forEach(System.out::println);

結果:

Stu{id=4, name='cc', age=42}
Stu{id=5, name='dd', age=52}
2.2.1.2 limit-限定元素數量

limit(n)

通過截斷流,使流中元素個數不超過指定數量

stuList.stream()
        .filter((s) ->{
            System.out.println("測試迭代幾次");
            return s.getAge()>40;
        }).limit(1).forEach(System.out::println);

結果:

測試迭代幾次
測試迭代幾次
測試迭代幾次
測試迭代幾次
Stu{id=4, name='cc', age=42}

結果發現:先通過filter()過濾,迭代到想要的過濾結果後,再根據limit(n),直接截斷流,後續操作不繼續,限制其流中元素個數為n,此操作稱為短路操作,短路操作也用於提高效率

所以前3次元素不在結果中,但都進行迭代判斷,列印了3次後後面的元素再次進行迭代,發現元素滿足過濾條件,但limit限制只要一個,即最後一次迭代後直接截斷流,結果為第一個滿足過濾條件的元素。

2.2.1.3 skip-跳過元素

skip(n)

返回一個跳過前n個元素的流,若流中元素不足n個,則返回一個空流
與limit(n)互補

//skip(n)  跳過前n個元素
stuList.stream()
    .skip(2).forEach(System.out::println);
/* 結果:
    Stu{id=3, name='bb', age=32}
    Stu{id=4, name='cc', age=42}
    Stu{id=5, name='dd', age=52}
 */
stuList.stream().skip(6).forEach(System.out::println);
//流中元素個數總數為5,小於6,則返回空流,沒有結果值
2.2.1.4 distinct-去重
  • 通過流所生成元素的hashCode()equals()來去除重複元素

先在stuList中新增幾個重複元素用於測試:

List<Stu> stuList = Arrays.asList(
        new Stu(1,"hh",22),
        new Stu(2,"aa",22),
        new Stu(3,"bb",32),
        new Stu(4,"cc",42),
        new Stu(4,"cc",42),
        new Stu(4,"cc",42),
        new Stu(4,"cc",42),
        new Stu(5,"dd",52)
);

此時的Stu類中沒有生成重寫hashCode()equals()方法,測試:

 //distinct 去重
 stuList.stream().distinct().forEach(System.out::println);

但是結果發現,並沒有去重:

Stu{id=1, name='hh', age=22}
Stu{id=2, name='aa', age=22}
Stu{id=3, name='bb', age=32}
Stu{id=4, name='cc', age=42}
Stu{id=4, name='cc', age=42}
Stu{id=4, name='cc', age=42}
Stu{id=4, name='cc', age=42}
Stu{id=5, name='dd', age=52}

此時,在Stu類中生成重寫hashCode()equals()方法:

@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    Stu stu = (Stu) o;
    return Objects.equals(id, stu.id) &&
            Objects.equals(name, stu.name) &&
            Objects.equals(age, stu.age);
}

@Override
public int hashCode() {

    return Objects.hash(id, name, age);
}

再次測試用例後,發現結果已經去重:

Stu{id=1, name='hh', age=22}
Stu{id=2, name='aa', age=22}
Stu{id=3, name='bb', age=32}
Stu{id=4, name='cc', age=42}
Stu{id=5, name='dd', age=52}

結論:

distinct()去重原理為通過流所生成元素的hashCode()equals()來去除重複元素

2.2.2 對映

2.2.2.1 map對映

<R> Stream<R> map(Function<? super T, ? extends R> mapper)
- 接收Lambda,將元素轉換成其他形式提取資訊
- 接收一個Function<? super T, ? extends R> mapper函式作為引數,該函式會被應用到每個元素上,並將其對映到一個新的元素

//map對映
List<String> stringList = Arrays.asList("aa", "bb", "cc", "dd");
stringList.stream()
    .map((x)->x.length()).forEach(System.out::println);
stringList.stream()
    .map((x)->x.toUpperCase()).forEach(System.out::println);

結果:

2
2
2
2
AA
BB
CC
DD

從結果看出,流中的每個元素都應用了map()裡的引數中的Function函式,並返回經過Function處理的元素。

  • map對映的重要應用為:即類似SQL中的對映獲取物件中的某些屬性(即資料庫中的某些欄位)

例如:獲取Stu中的name屬性

stuList.stream().map(Stu::getName).forEach(System.out::println);

測試結果:

hh
aa
bb
cc
cc
cc
cc
dd
2.2.2.2 flatMap對映
  • 接收一個函式作為引數,將流中的每個值轉換成另一個流,然後把所有流連線成一個流。每個部分流中的每個值成單獨小流,再串成一個整體流。

對比map對映:
1. map對映是將集合中的部分流新增到整體流中,而flatMap對映是將集合中的部分流中的每個元素單獨一個個地新增到整體流中
2. map對映: Stream<Stream<Character>> , flatMap對映:Stream<Character>

測試用例
1. 寫一個函式用於flatMap對映

/**
 * 字串拆分成字元後組成一個字元型別的流
 * @param str
 * @return
 */
public static Stream<Character> filterCharacter(String str){
    List<Character> characterList = new ArrayList<>();
    for (Character ch: str.toCharArray()
         ) {
        characterList.add(ch);
    }
    return characterList.stream();
}
  1. 用該函式分別測試map對映型別和flatMap對映型別
List<String> stringList = Arrays.asList("aa", "bb", "cc", "dd");
Stream<Stream<Character>> st1 = stringList.stream()
    .map(TestStream::filterCharacter);
//此時流的內容為 {{"aa"},{"bb"},{"cc"},{"dd"}} 4個單獨的字元流物件組成的流
st1.forEach(System.out::println);
/*  再次遍歷後
    結果:4個流物件 即 Stream<Character>  {{"aa"},{"bb"},{"cc"},{"dd"}}
    [email protected]
    [email protected]
    [email protected]
    [email protected]
 */
System.out.println("----------------");

Stream<Character> st2 = stringList.stream().flatMap(TestStream::filterCharacter);
//此時流的內容為{"a","a","b","b","c","c","d","d"}
st2.forEach(System.out::println);
/*  再次遍歷後
    結果直接返回了單個的字元流
    a
    a
    b
    b
    c
    c
    d
    d
 */

2.2.3 排序

2.2.3.1 自然排序

sorted()

  • 自然排序(Comparable方式),按照字典順序進行排序
  • 按照實現的Comparable中的compare to()方法
List<String> stringList = Arrays.asList("ee", "bb", "ff", "dd","哈哈","啊");
//根據String類中Comparable方式進行預設排序,即compare to()方法
stringList.stream()
    .sorted().forEach(System.out::println);

結果:

bb
dd
ee
ff
哈哈
啊

2.2.3.2 指定排序

sorted(Comparator com)

  • 根據實現Comparator介面的指定方法進行排序
stuList.stream().sorted(
            (a,b) ->{
                if (a.getAge().equals(b.getAge())){
                    return a.getName().compareTo(b.getName());
                }else{
                    return a.getAge().compareTo(b.getAge());
                }
            }
    ).forEach(System.out::println);

2.3. 終止Stream操作

終止操作,執行中間鏈操作,並產生結果

2.3.1. 查詢與匹配

  • 匹配 match 利用斷言型函式介面,返回boolean值 是否匹配
  • 查詢返回容器類 Optional型別 避免空指標異常
2.3.1.1 allMatch-檢查是否匹配所有元素

返回結果:
- true 匹配到了所有的元素 注意:和noneMatch()的false 結果代表集合不同
- false 沒有匹配到所有的元素 說明匹配到條件集合中的真子集

boolean b = stuList.stream()
    .allMatch((e) -> e.getAge() > 20);
System.out.println(b);//true

boolean b1 = stuList.stream()
    .noneMatch((e) -> e.getAge() > 20);
System.out.println(b1);//flase

boolean b2 = stuList.stream()
    .noneMatch((e) -> e.getAge() > 40);
System.out.println(b2);//flase
2.3.1.2 anyMatch-檢查是否至少匹配一個元素

返回結果:
- true 匹配到了條件集合中的真子集元素,一個或者多個
- false 一個元素都沒有匹配到,空集

boolean hhh = stuList.stream()
    .anyMatch((e) -> e.getName().equals("hhh"));
System.out.println(hhh);//false

boolean hh = stuList.stream()
    .anyMatch((e) -> e.getName().equals("hh"));
System.out.println(hhh);//true
2.3.1.3 noneMatch-檢查是否所有元素都沒有匹配到

返回結果:
- true 所有元素都沒有匹配到,空集
- false 不是所有的元素都沒有匹配到 即匹配到了元素,有匹配到的元素即返回false,真子集

boolean b1 = stuList.stream()
    .noneMatch((e) -> e.getAge() > 20);
System.out.println(b1);//flase

boolean b2 = stuList.stream()
    .noneMatch((e) -> e.getAge() > 40);
System.out.println(b2);//flase

boolean b3 = stuList.stream()
    .noneMatch((e) -> e.getAge() > 50);
System.out.println(b3);//此時集合中只有一個元素能匹配到,返回了false

boolean b4 = stuList.stream()
    .noneMatch((e) -> e.getAge() > 60);
System.out.println(b3);//所有的元素都沒有匹配到  返回了true
2.3.1.4 findFirst-返回第一個元素

Optional<T> findFirst();

Optional<Stu> first = stuList.stream().findFirst();
System.out.println(first.get());// Stu{id=1, name='hh', age=22}

返回第一個元素,用Optional集合類來封裝,避免了空指標異常

2.3.1.5 findAny-返回當前流中的任意一個元素

Optional<T> findAny();

//從集合中隨便找個age>30的Stu物件  可以使用序列流stream,也可以使用parallelStream 並行流
Optional<Stu> any = stuList.parallelStream()
    .filter((e) -> e.getAge() > 30).findAny();
System.out.println(any.get());//Stu{id=4, name='cc', age=42}
Optional<Stu> any1 = stuList.stream()
    .filter((e) -> e.getAge() > 30).findAny();
System.out.println(any1.get());//Stu{id=3, name='bb', age=32}
2.3.1.6 count-返回流中元素總個數

long count();

long count = stuList.stream().count();
System.out.println(count);//8
2.3.1.7 max-返回流中的最大值

Optional<T> max(Comparator<? super T> comparator);

//根據年齡大小進行正序排序找出最大值
Optional<Stu> max = stuList.parallelStream()
    .max((a, b) -> Integer.compare(a.getAge(), b.getAge()));
System.out.println(max.get()); //Stu{id=5, name='dd', age=52}

//根據年齡大小進行倒序排序找出最大值
Optional<Stu> max1 = stuList.parallelStream()
    .max((a, b) -> Integer.compare(b.getAge(), a.getAge()));
System.out.println(max1.get()); //Stu{id=1, name='hh', age=22}

//提取最大年齡 先對映提取集合中每個物件的年齡 再直接進行max方法比較 最後返回一個年齡值
Optional<Integer> maxAge = stuList.parallelStream()
    .map(Stu::getAge)
    .max(Integer::compare);
System.out.println(maxAge.get()); //52
2.3.1.8 min-返回流中的最小值

Optional<T> min(Comparator<? super T> comparator);

//根據年齡大小進行正序排序找出最小值
Optional<Stu> min = stuList.parallelStream()
    .min((a, b) -> Integer.compare(a.getAge(), b.getAge()));
System.out.println(min.get());//Stu{id=1, name='hh', age=22}

//根據年齡大小進行倒序排序找出最小值
Optional<Stu> min1 = stuList.parallelStream()
    .min((a, b) ->  Integer.compare(b.getAge(), a.getAge()));
System.out.println(min1.get()); //Stu{id=5, name='dd', age=52}

2.3.2. 歸約與收集

2.3.2.1 reduce-將流中元素反覆結合起來,得到一個值
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
//利用reduce歸約函式,可以指定歸約規則,將集合中的元素數值進行求和操作等
//以0為起始值,對集合中的各個值進行相加
Integer sum = list.stream().reduce(0, (x, y) -> x + y);
System.out.println(sum);//45

//求出stuList集合中的年齡總和
//此時利用Integer類中的靜態方法sum求和 無起始值,有可能為空,
// 則返回值自動變為Optional容器類封裝過後的值
Optional<Integer> ageSumOp = stuList.stream()
    .map(Stu::getAge)
    .reduce(Integer::sum);
System.out.println(ageSumOp.get());//296
  • 此時利用Integer類中的靜態方法sum求和 無起始值,有可能為空,則返回值自動變為Optional容器類封裝過後的值
2.3.2.2 collect-將流轉換為其他形式
  • 接收一個Collector介面的實現,用於Stream中元素做彙總的方法

  • 利用Collectors實用工具類中提供的很多靜態實現Collector介面的方法,進行相應的轉換收集操作。

//收集stuList集合中的所有name值,轉換為list集合
List<String> nameList = stuList.stream().map(Stu::getName)
    .collect(Collectors.toList());
nameList.forEach(System.out::println);
/*
    結果: 
    hh
    aa
    bb
    cc
    cc
    cc
    cc
    dd
 */
//獲取年齡轉化成set集合 去掉了重複值
Set<Integer> ageSet = stuList.stream().map(Stu::getAge)
    .collect(Collectors.toSet());
ageSet.forEach(System.out::println);
/*
     結果:
    32
    52
    22
    42
 */
  • 如果想轉換成其他沒有的現成靜態方法的資料結構集合,就使用Collectors.toCollection()方法,該方法具體引數和返回值為:Collector<T, ?, C> toCollection(Supplier<C> collectionFactory)

使用Collectors.toCollection(HashSet::new)方法 轉換成HashSet集合,該方法引數為Supplier供給型函式介面,傳給一個建構函式, 用例如下:

//使用`Collectors.toCollection()`方法 轉換成`其他沒有的現成靜態方法`的資料結構集合 比如HashSet
HashSet<String> nameHashSet = stuList.stream().map(Stu::getName)
    .collect(Collectors.toCollection(HashSet::new));
nameHashSet.forEach(System.out::println);
/*
    result:
    hh
    aa
    bb
    cc
    dd
 */

2.3.3. Collectors類中的常用方法

2.3.3.1 counting-統計數量

Long count() 統計元素個數

Long count = stuList.stream()
        .collect(Collectors.counting());
System.out.println(count);//8
2.3.3.2 averagingDouble-求平均值並轉換成Double型別

<T> Collector<T, ?, Double> averagingDouble(ToDoubleFunction<? super T> mapper)

<T> Collector<T, ?, Double> averagingInt(ToIntFunction<? super T> mapper)

<T> Collector<T, ?, Double> averagingLong(ToLongFunction<? super T> mapper)

測試用例:求年齡的平均值

Double ageAve = stuList.stream()
            .collect(Collectors.averagingDouble(Stu::getAge));
System.out.println(ageAve);//37.0
2.3.3.3 summingDouble-求和並轉換成Double型別

<T> Collector<T, ?, Integer> summingInt(ToIntFunction<? super T> mapper)

<T> Collector<T, ?, Long> summingLong(ToLongFunction<? super T> mapper)

<T> Collector<T, ?, Double> summingDouble(ToDoubleFunction<? super T> mapper)

測試用例:求年齡之和

Double ageSum = stuList.stream()
        .collect(Collectors.summingDouble(Stu::getAge));
System.out.println(ageSum);//296.0
2.3.3.4 maxBy-根據函式條件求最大值

<T> Collector<T, ?, Optional<T>> maxBy(Comparator<? super T> comparator)

測試用例:根據年齡找出最大年齡值的stu物件

//根據年齡找出最大年齡值的stu物件
Optional<Stu> stuOptional = stuList.stream()
        .collect(Collectors.maxBy((a, b) -> Double.compare(a.getAge(), b.getAge())));
System.out.println(stuOptional.get());//Stu{id=5, name='dd', age=52}
2.3.3.5 groupingBy-分組
  • 單級分組 <T, K> Collector<T, ?, Map<K, List<T>>> groupingBy(Function<? super T, ? extends K> classifier)

測試用例:根據年齡分組

//根據年齡分組
Map<Integer, List<Stu>> ageGroup = stuList.stream()
        .collect(Collectors.groupingBy(Stu::getAge));
System.out.println(ageGroup);

結果:

{32=[Stu{id=3, name='bb', age=32}],
52=[Stu{id=5, name='dd', age=52}],
22=[Stu{id=1, name='hh', age=22}, Stu{id=2, name='aa', age=22}],
42=[Stu{id=4, name='cc', age=42}, Stu{id=4, name='cc', age=42}, Stu{id=4, name='cc', age=42}, Stu{id=4, name='cc', age=42}]}
  • 多級分組 兩個引數,第二個引數為Collector,即實現無限分組
    <T, K, A, D> Collector<T, ?, Map<K, D>> groupingBy(Function<? super T, ? extends K> classifier, Collector<? super T, A, D> downstream)

先根據name分組,再根據年齡分組

//先根據name分組,再根據年齡分組
Map<String, Map<String, List<Stu>>> groupmap = stuList.stream()
        .collect(Collectors.groupingBy(Stu::getName, Collectors.groupingBy((e) -> {
            if (e.getAge() <= 20) {
                return "年輕人";
            } else if (e.getAge() <= 50) {
                return "中年人";
            } else {
                return "老年人";
            }
        })));
System.out.println(groupmap);

結果:

{dd={老年人=[Stu{id=5, name='dd', age=52}]},
 cc={中年人=[Stu{id=4, name='cc', age=42}, Stu{id=4, name='cc', age=42}, Stu{id=4, name='cc', age=42}, Stu{id=4, name='cc', age=42}]},
 bb={中年人=[Stu{id=3, name='bb', age=32}]},
 aa={中年人=[Stu{id=2, name='aa', age=22}]},
 hh={中年人=[Stu{id=1, name='hh', age=22}]}}
2.3.3.6 partitioningBy-分割槽

滿足條件的分到一個區,不滿足條件分到另一個區

true , false Map<Boolean,List<>>

測試用例:是否年齡大於40,分兩個區

Map<Boolean, List<Stu>> booleamGroup = stuList.stream()
    .collect(Collectors.partitioningBy((e) -> e.getAge() > 40));
System.out.println(booleamGroup);

結果:

    {
        false=[
            Stu{id=1, name='hh', age=22},
            Stu{id=2, name='aa', age=22},
            Stu{id=3, name='bb', age=32}
            ],
        true=[
            Stu{id=4, name='cc', age=42},
            Stu{id=4, name='cc', age=42},
            Stu{id=4, name='cc', age=42},
            Stu{id=4, name='cc', age=42},
            Stu{id=5, name='dd', age=52}
             ]
    }
2.3.3.7 summarizingDouble-計算方法總括函式

<T> Collector<T, ?, DoubleSummaryStatistics> summarizingDouble(ToDoubleFunction<? super T> mapper)

summarizingDouble
返回 DoubleSummaryStatistics 型別 可以直接呼叫各種計算方法

summarizingInt

summarizingLong

例項:

DoubleSummaryStatistics ageSummaryStatis = stuList.stream()
    .collect(Collectors.summarizingDouble(Stu::getAge));
ageSummaryStatis.getAverage();
ageSummaryStatis.getCount();
ageSummaryStatis.getMax();
ageSummaryStatis.getMin();
ageSummaryStatis.getSum();
2.3.3.7 joining-連線字串

Collector<CharSequence, ?, String> joining()

測試用例:將stuList集合中所有的名字連線在一起

//將集合中所有的名字連線在一起
String allNameStr = stuList.stream().map(Stu::getName)
    .collect(Collectors.joining());
System.out.println(allNameStr);//hhaabbccccccccdd

測試用例:將stuList集合中所有的名字連線在一起,並使用逗號分割

 //將集合中所有的名字連線在一起,並逗號分割
String allNameStr1 = stuList.stream().map(Stu::getName)
    .collect(Collectors.joining(","));
System.out.println(allNameStr1);
//hh,aa,bb,cc,cc,cc,cc,dd

相關推薦

Java8特性-Stream API 常用整版

流(Stream) 1. 流的概念 流是資料渠道,用於操作資料來源,所生成一種新的元素序列。集合講的是資料,流講的是計算,是操作。 Stream是Java8中處理集合的關鍵抽象概念,它可以指定希望對集合的操作,可以執行復雜的查詢、過濾

JAVA8特性-Stream API,函數語言程式設計

首先先拿github上的兩篇文章作為關於Stream API的專業性技術指導 http://www.cnblogs.com/CarpenterLee/p/6545321.html   Java Stream API入門篇 http://www.cnblogs.com/Ca

Java8特性Stream API與Lambda表示式詳解(1)

1 為什麼需要Stream與Lambda表示式? 1.1  為什麼需要Stream Stream作為 Java 8 的一大亮點,它與 java.io 包裡的 InputStream 和 OutputStream 是完全不同的概念。它也不同於 StAX 對 XML 解析的 S

Java8特性 - Stream API

Stream是Java8中處理集合的關鍵抽象概念,它可以指定你希望對集合進行的操作,可以執行非常複雜的查詢、過濾和對映資料等操作。使用Stream API對集合進行操作,就類似與使用SQL執行的資料庫操作。也可以使用Stream API來並行執行操作。簡而言之,Stream API 提供了一種高效且易於使用

Java8特性--Stream API

[TOC](目錄) # Stream ## 寫在前面 Java8中有兩大最為重要的改變: - Lambda表示式 - Stream API(java.util.stream.*) Stream是Java8中處理集合的關鍵抽象概念,它可以指定你希望對集合進行的操作,可以執行非常複雜的查詢、過濾、對映資料

java8特性-Stream

mat color img reac def list collect array java8 Java8中的Collection接口被擴展,提供了兩個獲取流的方法: default Stream<E>

java8 特性 Stream

ons match 方法 ams foreach jpg 在一起 classes ora 1. Stream初體驗 我們先來看看Java裏面是怎麽定義Stream的: A sequence of elements supporting sequential and

Java 8 特性——Stream API

目錄 1. 什麼是stream  2. Stream操作三個步驟 3. 建立Stream 4. Stream 的中間操作 5. Stream 的終止操作 Stream API(java.util.stream.*)。    &n

java8特性——Stream介面

Stream介面 1,stream的foreach方法 Stream不是一個數據結構,不直接儲存資料,它通過管道來操作資料。 建立Stream介面實現類物件: stream():建立一個Stream介面實現類的物件: Stream<Person> stream = P

jdk8特性Stream API

jdk8中新加入流Stream介面,主要為處理集合提供了便利,jdk8以後,在集合介面中新增加了預設的sream方法,用來生成流 物件結合Collection的原始碼增加的stream方法如下: default Stream<E> stream() { re

Java8特性Stream舉例

說明:分別用常規程式碼和Lambda舉例 計算集合空字串數量 List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd", "", "jkl"); //1.

java8特性 stream、lambde、optional

一、stream: stream() − 為集合建立序列流。 parallelStream() − 為集合建立並行流。 forEach Stream 提供了新的方法 'forEach' 來迭代流中的每個資料。以下程式碼片段使用 forEach 輸出了1

Java 8特性stream API用法總結

很難 develop 聚合操作 doc acl 註意 指定 fork 新特性 前言   Stream 作為 Java 8 的一大亮點,它與 java.io 包裏的 InputStream 和 OutputStream 是完全不同的概念。它也不同於 StAX 對 XML 解

java8特性Stream的基本使用

 第一、建立Stream      1.1、根據集合的建立 List<String> list = new ArrayList<>(); Collections.addAll(list,"aa

Java8特性_stream API 練習

equal nbsp cit 查找 port foreach test stream case 交易員類 public class Trader { private String name; private String city; pub

Java8特性——Stream

1、Stream在Java8中被定義為泛型介面 2、Stream介面代表資料流。 3、Stream不是一個數據結構,不直接儲存資料。 4、Stream通過管道操作資料。 5、建立Stream介面實現類物件: stream():建立一個Strea

Java8 特性 —— Stream 流式程式設計

> 本文部分摘自 On Java 8 ## 流概述 集合優化了物件的儲存,大多數情況下,我們將物件儲存在集合是為了處理他們。使用流可以幫助我們處理物件,無需迭代集合中的元素,即可直接提取和操作元素,並添加了很多便利的操作,例如查詢、過濾、分組、排序等一系列操作。 流的一個核心好處是:它使得程式更

Java8特性Stream API有哪些中間操作?看你也可以吊打面試官!!

## 寫在前面 > 在上一篇《[【Java8新特性】面試官問我:Java8中建立Stream流有哪幾種方式?](https://www.cnblogs.com/binghe001/p/12961977.html)》中,一名讀者去面試被面試官暴虐!歸根結底,那哥兒們還是對Java8的新特性不是很瞭解呀!

JAVA8特性Stream API

重要的 Stream API  : java.util.Stream.* Stream提供了一種高效且簡易處理資料的方式 注意:1.Stream自己不會儲存元素            2.對Stream進行操作不會改變資料來源,相反,

看透Java8特性:lambda表示式和Stream API

Java11前兩天都發布了,Java8還沒搞清都有啥,這就很尷尬了~ Java8 的新特性:Lambda表示式、強大的 Stream API、全新時間日期 API、ConcurrentHashMap、MetaSpace。Java8 的新特性使 Java 的執行速度更快、程式碼更少(Lambda 表示式)、便