java8之stream【一】steam的說明以及創建

一、Stream說明

Stream與IO無任何關係。
Java 8 中的Stream是對集合 (Collection) 對象功能的增強, 他專注於對集合對象進行各種非常便利,高效的聚合操作(aggregate operation), 或者大批量數據操作 (bulk data operation).
Stream API藉助於同樣新出現的Lambda 表達式, 極大的提高編程效率和程序可讀性. 同時他提供穿行和並行兩種模式進行匯聚操作, 併發模式能夠成分利用多核處理器的優勢, 使用fork/join 並行法師來拆分任務和加速處理過程.
通常編寫並行代碼很難而且容易出錯, 但使用Stream API無需編寫一行多線程的代碼, 就可以很方便地寫出高性能的併發代碼.
Java 8中首次出現的java.util.stream是一個函數式語言+多核時代綜合影響的產物.

二、java7於java8 Stream的使用對比

需要使用到的實體類

@Setter
@Getter
public class Apple {
    private Long appleId;
    private String appleName;

    public Apple(){}

    public Apple(Long appleId,String appleName){
        this.appleId=appleId;
        this.appleName=appleName;
    }
}

以下是一個java7對list的操作,包括了篩選、排序、取值等操作。

    public static void java7(){
        //目標,獲取id大於10的蘋果名稱,並對結果集按照id大小排序
        List<Apple> list=getList();
        List<Apple> targetList=new ArrayList<>();
        for(Apple apple : list){
            if(apple.getAppleId()>10){
                targetList.add(apple);
            }
        }

        Collections.sort(targetList, new Comparator<Apple>() {
            @Override
            public int compare(Apple o1, Apple o2) {
                return o2.getAppleId().compareTo(o1.getAppleId());
            }
        });

        List<String> nameList=new ArrayList<>();
        for(Apple apple : targetList){
            nameList.add(apple.getAppleName());
        }
        XLogUtils.info(jsonToString(nameList));
    }

java8對列表進行篩選、排序、取值操作
是不是很清爽?那麼…那麼代價是什麼呢?看完全文你就知道啦。

    public static void java8(){
        List<Apple> list=getList();
        List studentList = list.stream()
                .filter(x->x.getAppleId()>10)
                .sorted(Comparator.comparing(Apple::getAppleId).reversed())
                .map(Apple::getAppleName)
                .collect(Collectors.toList());
        XLogUtils.info(jsonToString(studentList));
    }

三、Stream概述

1、Stream的特性

  • 不存儲數據
  • 不改變數據源
  • 延遲執行

2、Stream的創建

  • 可以通過已存在的數組創建
  • 可以通過已存在集合創建
  • 可以創建一個空的流
  • 可以創建一個無限的流
  • 可以創建一個規律的流

3、對Stream的操作

  • 一般使用
  • 提取流、組合流
  • 聚合操作
  • Optional類型說明
  • 分組與分片
  • 收集結果

4、並行流

5、原始類型流

四、Stream使用以及說明

1、Stream的延遲特性

(1)延遲性驗證

    public static boolean filter(Apple s) {
        System.out.println("begin compare");
        return s.getAppleId() > 5;
    }
   
    /**
     * 驗證延遲性
     */
    public static void f2() {
        List<Apple> list=getList();
        Stream<Apple> stream = list.stream()
                .filter(apple -> filter(apple));
        System.out.println("split-----------------------------------");
        List<Apple> studentList = stream.collect(Collectors.toList());
        System.out.println("end-------------------------------------");
    }

輸出:

split-----------------------------------
begin compare
begin compare
begin compare
begin compare
begin compare
begin compare
begin compare
begin compare
begin compare
begin compare
end-------------------------------------

由上述可確認,Stream確實是具有延遲性。

(2)延遲性事故
 /**
     * 延遲特性,導致的空指針異常
     */
    public static void f4(){
        List<Apple> list=getList();

        Stream<Apple> appleList= list.stream();
        appleList.forEach(s -> {
            System.out.println("s->"+s);
            if (s.getAppleId() < 4) {
                System.out.println("select->"+s);
                list.remove(s);
                XLogUtils.info(jsonToString(list));
            }
        });
    }

輸出:

select->Stream.Apple@71bbf57e
[info]>>>>null
s->Stream.Apple@7f13d6e
select->Stream.Apple@7f13d6e
[info]>>>>null
s->Stream.Apple@51cdd8a
select->Stream.Apple@51cdd8a
[info]>>>>null
s->null
Exception in thread “main” java.lang.NullPointerException
at Stream.TestStreamClass.lambda$f49(TestStreamClass.java:171)atjava.util.ArrayList9(TestStreamClass.java:171) at java.util.ArrayListArrayListSpliterator.forEachRemaining(ArrayList.java:1382)
at java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:580)
at Stream.TestStreamClass.f4(TestStreamClass.java:169)
at Stream.TestStreamClass.main(TestStreamClass.java:38)

如上,出現了空指針異常。出現異常的是

  if (s.getAppleId() < 4) {

s對象空指針異常。list.remove(s);使對象被remove,但是此處又調用了此對象的方法,導致空指針異常。

(3)延遲性的使用
 		 List<Apple> list=getList();
        Stream<Apple> stream = list.stream()
                .filter(apple -> filter(apple));
        list.add(new Apple(1001L,"New Apple"));
        List<Apple> studentList = stream.collect(Collectors.toList());

指令執行的順序爲:
[1]獲取數據源
[2]聲明Stream
[3]添加數據到數據源
[4]執行Stream業務(過濾),並聚合爲list。
所以,雖然add操作是在聲明Stream之後,但是它也被執行過濾。

2、創建Stream

(1)通過數組創建流
/**
 * 通過數組創建流
 */
@Test
public void testArrayStream(){
    //1.通過Arrays.stream
    //1.1基本類型
    int[] arr = new int[]{1,2,34,5};
    IntStream intStream = Arrays.stream(arr);
    //1.2引用類型
    Student[] studentArr = new Student[]{new Student("s1",29),new Student("s2",27)};
    Stream<Student> studentStream = Arrays.stream(studentArr);
    //2.通過Stream.of
    Stream<Integer> stream1 = Stream.of(1,2,34,5,65);
    //注意生成的是int[]的流
    Stream<int[]> stream2 = Stream.of(arr,arr);
    stream2.forEach(System.out::println);
}
(2)通過集合創建流
@Test
public void testCollectionStream(){
    List<String> strs = Arrays.asList("11212","dfd","2323","dfhgf");
    //創建普通流
    Stream<String> stream  = strs.stream();
    //創建並行流
    Stream<String> stream1 = strs.parallelStream();
}
(3)創建空的流
@Test
public void testEmptyStream(){
    //創建一個空的stream
    Stream<Integer> stream  = Stream.empty();
}
(4)創建無限流
@Test
public void testUnlimitStream(){
    //創建無限流,通過limit提取指定大小
    Stream.generate(()->"number"+new Random().nextInt()).limit(100).forEach(System.out::println);
    Stream.generate(()->new Student("name",10)).limit(20).forEach(System.out::println);
}
(5)創建規律的無限流
@Test
public void testUnlimitStream1(){
    Stream.iterate(0,x->x+1).limit(10).forEach(System.out::println);
    Stream.iterate(0,x->x).limit(10).forEach(System.out::println);
    //Stream.iterate(0,x->x).limit(10).forEach(System.out::println);與如下代碼意思是一樣的
    Stream.iterate(0, UnaryOperator.identity()).limit(10).forEach(System.out::println);
}

參考文章:https://www.cnblogs.com/andywithu/p/7404101.html
參考文章:https://www.jianshu.com/p/9101b2ef96d8

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章