Java 8 流庫學習筆記(一)

來源:互聯網
上載者:User

標籤:yield   資料   tom   wrap   generate   運算式   entity   seq   []   

core Java學習筆記】Java SE8 流庫 Stream Library從迭代到流

如果要計算一個文本中有多少長單詞(字母>12)。

  • 迭代式:

    words = getlist();//虛構方法,獲得一個List<String>long count = 0;for(String w:words){if(w.length()>12) count++;}
  • 流式:

    words = getlist();//虛構方法,獲得一個List<String>long count = words.stream().filter(w->w.length() > 12).count();
  • 流式運算式相對於迭代式的好處:
    1. 易於閱讀。
    2. 易於最佳化,例如將steam()方法換為parallelStream()方法就可以進行並行計算。
    3. 遵循"what, not how"原則,抽象層次更高。
  • 流的特徵:
    1. 流不儲存元素,元素可能儲存在按需產生的匿名集合中。
    2. 流操作絕不會改變來源資料。例如filter()方法不會移除資料,而是產生新的流。
    3. 流操作是lazy的,意味著直到流操作的結果被需要時才會進行運算。
  • 流操作的範式:
    1. 建立流。例如上例的stream()
    2. 應用intermediate operations使用原流去產生其他需要的流,可以進行多步。例如上例的filter()
    3. 應用terminal operation去產生結果。之後流將不可用。例如count()
建立流
  • 如果有Collection類,調用其stream()或其他流方法。
  • 如果有數組,使用Stream.of(Array array)方法。
  • 建立空流,調用Stream.empty()方法。
  • 建立無限長流,調用Stream.generate(Supplier supplier<T> s)方法。

    Stream<String> echos = Stream.generate(()->"Echo");//上方lambda運算式可寫為如下完整運算式Stream<String> echos = Stream.generate(new Supplier<String>() {        @Override        public String get() {            return "echo";        }    });
    Stream<Double> randoms = Stream.generate(Math::random);//產生隨機數,雙冒號是lambda運算式中的方法引用
  • 建立迭代的無限長流,使用Stream.iterate(T seed,UnaryOperator f)

    Stream<BigInteger> integers = Stream.iterate(BigInteger.ZERO,n->n.addd(BigInteger.ONE))//流的第一個元素為seed,後續元素為f(seed),f(f(seed))...
  • 字串建立流,調用Pattern類中的spliteAsStream(CharSequence input)方法

    Pattern pattern = Pattern.compile(" ");Stream<String> s = pattern.splitAsStream("A B C");
filter, mapflatmap方法

最常用的三種intermediate operations

  • Stream<T> filter 方法:選擇源流中符合一定條件的元素組成新流。

    List<String> wordList = ...;    //省略初始化Stream<String> longWords = wordList.Stream().filter(w -> w.length() > 12);
  • <R> Stream<R> map方法:對源流中所有元素執行同一操作後組成新流。

    List<String> words = ...;       //省略初始化Stream<String> lowercaseWords = words.stream().map(String::toLowerCase);
  • <R> Stream<R> flatmap方法:和map方法的效果大致相同,但對多個流組成的流操作會得到合并的一個流。即對Stream

    提取子流以及合并流
  • 調用Stream<T> limit(n)來提取前n個元素的子流。

    Stream<Double> randoms = Stream.generate(Math::random).limit(100);
  • 調用Stream<T> skip(n)來獲得跳過前n個元素的子流

    Stream<String> words = Stream.of(contents.split("\\PL+")).skip(1);
  • 調用Stream<T> concate(Stream a,Stream b)來建立a,b流合并後的流,b在a後。

    其他流轉換操作
  • Stream<T> distinct()獲得相同順序,但是只保留一個相同項的流。

    Stream<String> uniqueWords = Stream.of("a","a","b","c","a").distinct();
  • 使用Stream<T> sorted()對comparable排序,或使用Stream<T> sorted(Comparator<? super T> comparator)對普通對象元素排序。

    Stream<String> longestFirst = words                        .stream()                        .sorted(Comparator.comparing(String::length))                        .reversed();
  • 使用Stream<T> peek(Consumer<? super T> action)在每次元素實際被訪問時觸發動作(action),利於debug。

    Object[] powers = Stream.iterate(1.0,p -> p * 2)        .peek(e - > System.out.println("Peeking"+e))        .limit(20).toArrays();
    簡單的還原(reduction)操作
  • 還原作業是將流對象轉換為非流對象的操作。
  • 還原作業是終止操作(terminal operations),操作之後流不可用。
  • count()計算流中元素個數。(上例有)
  • max(Comparator<? super T> comparator)min(Comparator<? super T> comparator)獲得最大/最小元素。他們返回一個Optional<? super T>類。

    Optional<String> largest = words.max(String::compareToIgnoreCase);System.out.println("largest:" + largest.orElse(""));
  • findFirst()findAny()獲得過濾器過濾到的第一個/所有元素。他們返回一個Optional<? super T>類。

    Optional<String> startsWithQ = words.filter(s -> s.startWith("Q")).findFirst();
  • anyMatch(Predicate<? super T> p),allMatch(Predicate<? super T> p),noneMatch(Predicate<? super T> p)返回匹配結果(boolean)。

    boolean aWordStartsWithQ = words.parallel().anyMatch(s -> s.startWith("Q"));
Optional

Optional類是流還原作業的常用傳回值。Optional<T>持有(wrap)T類型對象或null的對象。這樣的設計思路是為了安全,避免Null 參考。

簡單地處理 Optional對象中持有的對象。
  • T orElse(T other)如果該Optional對象非空,就返回持有的對象,否則返回other

    String result = optionalString.orElse("");//return wrapped string, or "" if null
  • T orElseGet(Supplier<? extends T> other)如果該Optional對象非空,就返回持有對象,否則返回other.get()
  • T orElseThrow(Supplier<? extends X> exceptionSupplier),如果該Optional對象非空,就返回持有的對象,否則拋出一個exceptionSupplier.get()異常。
  • ifPresent接受一個函數,如果option持有對象,則用該函數處理;否則無事發生。
    optionValue.ifPresent(v -> Process v);。該方法無傳回值。
  • map方法和ifPresent類似,但是有一個Optional<T>的傳回值,原Optional<T>對象不變。

正確地使用 Optional
  • 隨時警惕Optional對象可能不持有對象。這種特性可能造成NoSuchElementException錯誤的拋出。

    Optional<T> optionValue = ...;optionValue.get().someMethod();//not safe, cause get() may produce null
    Optional<T> optionValue = ...;if(optionValue.isPresent())optionValue.get().someMethod();//safe, cause isPresent() reports whether an Optional object has a value
    建立Optional類的對象

    建立Optional對象的主要方法是調用Optional類的靜態Factory 方法。

    static <T> Optional<T> of(T value)產生一個Optional對象,如果value是null,則拋出異常static <T> Optional<T> ofNullable(T value)產生一個Optional對象。static<T> Optional
    通過flatMap方法調用Optional<T>對象持有的T對象的方法。
//f() yields an Optional<T>//T has a method g() yields an Optional<U> Optional<U> result = s.f().flatMap(T::g)
收集流到集合中
  • 展示流

    stream.forEach(System.out::println);
  • 獲得數組

    String[] result = stream.toArray(String::new);//toArray get Object[], pass it to constructor to get the right type.
  • 使用collect方法和Collectors類中眾多的Factory 方法來獲得不同容器中的對象集合。

List<String> result = stream.collect(Collectors.toList());Set<String> result = stream.collect(Collectors.toSet());TreeSet<String> result = stream.collect(Collectors.toCollection(TreeSet::new));//control which type of implementation of CollectionString result = stream.collect(Collectors.joining());String result = stream.collect(Collectors.joining(", "));//joing to one StringIterator<T> iterator = stream.iterator();IntSummaryStatistics summary = stream.collect(    Collectors.summarizingInt(String::length));double averageWordLength = summary.getAverage();double maxWordLength = summary.getMax();//summarizing(Int|Long|double) -> (Int|Long|Double)SummaryStatistisc
收集流到字典中

例如有一個Person類

Person{    private int id;    private String name;    public getId(){        return id;    }    public getName(){        return name;    }    public Person(int id,String name){        this.id = id;        this.name = name;    }}
  • 一般情況
Map<Integer, String> keyToValue = stream.collect(    Collectors.toMap(Person::getID,Person::getName));    //(Function keyMapper, Function valueMapper)
  • 將對象整個作為鍵/值
Map<Integer, Person> idToPerson = stream.collect(    Collectors.toMap(Person::getID,Function.identity()));

Java 8 流庫學習筆記(一)

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.