成人午夜视频全免费观看高清-秋霞福利视频一区二区三区-国产精品久久久久电影小说-亚洲不卡区三一区三区一区

Java8StreamAPI有什么作用

這篇文章主要介紹“Java8 Stream API有什么作用”,在日常操作中,相信很多人在Java8 Stream API有什么作用問(wèn)題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對(duì)大家解答”Java8 Stream API有什么作用”的疑惑有所幫助!接下來(lái),請(qǐng)跟著小編一起來(lái)學(xué)習(xí)吧!

讓客戶滿意是我們工作的目標(biāo),不斷超越客戶的期望值來(lái)自于我們對(duì)這個(gè)行業(yè)的熱愛(ài)。我們立志把好的技術(shù)通過(guò)有效、簡(jiǎn)單的方式提供給客戶,將通過(guò)不懈努力成為客戶在信息化領(lǐng)域值得信任、有價(jià)值的長(zhǎng)期合作伙伴,公司提供的服務(wù)項(xiàng)目有:域名注冊(cè)、網(wǎng)絡(luò)空間、營(yíng)銷軟件、網(wǎng)站建設(shè)、回民網(wǎng)站維護(hù)、網(wǎng)站推廣。

Stream API 作用

為集合而生,簡(jiǎn)化集合操作、支持集合并發(fā)操作。

從迭代器到Stream

String contents = new String(Files.readAllBytes(Paths.get(alice.txt)), StandardCharsets.UTF_8);
List<String> words = Arrays.asList(contents.split("[\\P{L}]+"));

迭代器

int count = 0;
for (String w : words) {
	if (w.length() > 12) count++;
}

Stream

long count = words.stream().filter(w -> w.length() > 12).count();
// 并發(fā)統(tǒng)計(jì)很容易,如下只需要將stream()換成parallelStream()即可:
long count = words.parallelStream().filter(w -> w.length() > 12).count();

Stream與集合的區(qū)別

  • Stream自己不會(huì)存儲(chǔ)元素,元素被存放于底層集合中或者根據(jù)需要被產(chǎn)生出來(lái);

  • Stream操作符不會(huì)改變?cè)碨tream對(duì)象,它會(huì)返回一個(gè)持有結(jié)果新Stream對(duì)象;

  • Stream操作符可能是延遲執(zhí)行的,這意味著它們會(huì)等到需要結(jié)果的時(shí)候才執(zhí)行。例如只需要前5個(gè)長(zhǎng)單詞,那么filter方法將在第5次匹配后停止過(guò)濾。

Stream使用流程

  1. 創(chuàng)建一個(gè)Stream(從集合、數(shù)組、迭代器、生成器等數(shù)據(jù)結(jié)構(gòu));

  2. 通過(guò)一個(gè)或者多個(gè)Stream操作符,將初始Stream轉(zhuǎn)換為另一個(gè)Stream;

  3. 使用一個(gè)Stream終止操作符來(lái)產(chǎn)生一個(gè)結(jié)果,該操作會(huì)強(qiáng)制它之前的操作立即執(zhí)行,且在此之后,該Stream就不會(huì)再被使用了。

創(chuàng)建Stream

  • 集合:Collection的stream()方法,會(huì)產(chǎn)生一個(gè)Stream對(duì)象;

  • 數(shù)組:Stream.of(T... values) 接受一個(gè)可變長(zhǎng)度參數(shù)列表,參數(shù)可以是一個(gè)數(shù)組或者多個(gè)同類型獨(dú)立元素,產(chǎn)生一個(gè)Stream對(duì)象;

  • Arrays.stream(array, from, to)將數(shù)組的一部分轉(zhuǎn)化為Stream;

  • 空Stream:Stream<String> silence = Stream.empty();

  • 無(wú)限Stream:
    Stream<String> echos = Stream.generate(() -> "Echo");
    Stream<Double> randoms = Stream.generate(Math::random);
    Stream<BigInteger> integers = Stream.iterate(BigInteger.ZERO, n -> n.add(BigInteger.ONE));

  • JDK示例:
    Stream<String> words = Pattern.compile("[\\P{L}]+").splitAsStream(contents);
    Stream<String> lines = Files.lines(path);

操作Stream

常見(jiàn)Stream操作函數(shù)

  • filter:過(guò)濾元素,并產(chǎn)生一個(gè)新的Stream對(duì)象;

  • map:轉(zhuǎn)換;

  • flatMap:一對(duì)多轉(zhuǎn)換,即每個(gè)元素映射的結(jié)構(gòu)都是另一個(gè)Stream,最終將所有Stream合并為一個(gè)Stream;

示例

// filter:只獲取長(zhǎng)單詞
List<String> wordList = ... ;
Stream<String> words = wordList.stream();
Stream<String> longWords = words.filter(w -> w.length() > 12);
// map:將所有單詞轉(zhuǎn)換為小寫
Stream<String> lowercaseWords = words.map(w -> w.toLowerCase()); 
// 或者使用方法引用
Stream<String> lowercaseWords = words.map(String::toLowerCase()); 
// 獲取每個(gè)單詞的首字母  
Stream<Character> firstChars = words.map(w -> w.charAt(0));
// flatMap:獲取每個(gè)單詞中的字母
Stream<Character> letters = words.flatMap(w -> Arrays.stream(s.toCharArray()));

Stream提取與組合

  • Stream.limit(n),返回一個(gè)包含源Stream前n個(gè)元素的新Stream,如果源Stream長(zhǎng)度m小于n則返回前m個(gè)元素;

  • Stream.skip(n),丟棄掉源Stream的前n個(gè)元素,返回包含剩余元素的新Stream;

  • 組合兩個(gè)Stream為一個(gè)新的Stream,假設(shè)stream1和stream2為兩個(gè)Character的Stream:Stream<Character> combined = Stream.concat(stream1, stream2);

  • Stream.peek(action),會(huì)產(chǎn)生另一個(gè)與源Stream具有相同元素的Stream,但是在獲取每個(gè)元素時(shí),都會(huì)調(diào)用action參數(shù)指定的函數(shù),這樣是為了便于調(diào)試。

Stream有狀態(tài)轉(zhuǎn)換

Stream的filter和map、flatMap等操作都是無(wú)狀態(tài)的轉(zhuǎn)換,因?yàn)樵谵D(zhuǎn)換每一個(gè)元素時(shí)無(wú)需考慮之前轉(zhuǎn)換過(guò)的元素;
Stream的distinct操作,會(huì)根據(jù)源Stream中的元素,返回一個(gè)元素順序相同,但是沒(méi)有重復(fù)元素的新Stream,是有狀態(tài)的轉(zhuǎn)換,因?yàn)樗谵D(zhuǎn)換每個(gè)元素時(shí)都需要檢查該元素是否之前已讀取過(guò)。

Stream聚合操作

Stream的聚合操作會(huì)將Stream聚合成為一個(gè)值,以便程序中使用,例如Stream.count()、Stream.max()、Stream.min()、Stream.findFirst()、Stream.findAny()等。
聚合方法都是終止操作,執(zhí)行后流就關(guān)閉了,不能再應(yīng)用其它操作了。

聚合操作示例:

Optional<String> longest = words.max(String::compareToIgnoreCase);
if (longest.isPresent()) {
	Sysout.out.println(longest.get());
}
Optional<String> startWithQ = words.filter(s -> s.startsWith("Q")).findFirst();
// 并行提高執(zhí)行效率
Optional<String> startWithQ = words.parallel().filter(s -> s.startsWith("Q")).findAny();
// 并行提高執(zhí)行效率
Optional<String> startWithQ = words.parallel().anyMatch(s -> s.startsWith("Q"));

終止Stream

一個(gè)Stream對(duì)象在執(zhí)行終止操作后,就不能再執(zhí)行其他操作了。

Optional類型

Optional<T>對(duì)象是對(duì)T類型對(duì)象的封裝,或者表示不是任何對(duì)象。
Optional類本身實(shí)現(xiàn)非常簡(jiǎn)單,常用操作有:

  1. of(T value)

  2. ofNullable(T value)

  3. isPresent()

  4. ifPresent(consumer)

  5. orElse(T other)

  6. orElseGet(Supplier other)

  7. map(Function mapper)

  8. flatMap(Function mapper)用于組合可選函數(shù),例如,如果f()返回Optional<T>,T有一個(gè)返回Optional<U>的方法g(),就可以組合調(diào)用:Optional<U> op = f().flatMap(T::g)
    用法和其余的看源碼最直觀。

Stream聚合操作

聚合,即將Stream中的元素聚合成為一個(gè)值,例如:求和、求積、計(jì)數(shù)、字符串追加、最大值、最小值、并積、交積等,只要操作數(shù)x,y,z之間有一個(gè)操作op,滿足(x op y) op z = x op (y op z),那么op操作就是可聚合的;

聚合示例

// 求和
Stream<Integer> values = ...;
Optional<Integer> sum = values.reduce((x, y) -> x + y);
// 如果有一個(gè)標(biāo)識(shí)e,使得e op x = x,那么標(biāo)識(shí)e就可以作為計(jì)算的起點(diǎn),對(duì)于加法來(lái)說(shuō)0就是這個(gè)標(biāo)識(shí),所以另外一種形式:
Optional<Integer> sum = values.reduce(0, (x, y) -> x + y);
// 或者
Optional<Integer> sum = values.reduce(0, Integer::sum);
// 求字符串Stream中所有字符串總長(zhǎng)度
Stream<String> words = ...;
Optional<Integer> sum = words.reduce(0, (total, word) -> total + word.length(), (total1, total2) - > total1 + total2);
// 第二個(gè)參數(shù)accumulator,是為了聚合計(jì)算;
// 第三個(gè)參數(shù)combiner,是為了并行聚合計(jì)算后,對(duì)并行結(jié)果進(jìn)行再聚合;

Stream收集結(jié)果

流處理完成以后,我們對(duì)于處理結(jié)果有兩種用途:

  • 執(zhí)行聚合操作,將整個(gè)Stream聚合成為一個(gè)值,例如:sum、count、max、min等;

  • 收集Stream處理結(jié)果,獲取Stream中的每個(gè)元素,或打印、或轉(zhuǎn)儲(chǔ)、或執(zhí)行其他計(jì)算;

第二種“收集Stream處理結(jié)果”,由兩種操作:

  • collect,兩種方式:

  1. <R, A> R collect(Collector<? super T, A, R> collector); // 使用一個(gè)現(xiàn)成的預(yù)定義的Collector進(jìn)行收集,Collectors工具類還為各種常用的收集類型提供了各個(gè)工廠方法。

示例1:
Stream<String> stream = ...;
List<String> list = stream.collect(Collectors.toList());
Set<String> set = stream.collect(Collectors.toSet());
TreeSet<String> treeSet = stream.collect(Collectors.toCollection(TreeSet::new));//控制得到的set類型
String result = stream.collect(Collectors.join());//將Stream中所有字符串拼接
String result = stream.collect(Collectors.join(“, ”));//將Stream中所有字符串拼接且以", " 分隔
// 將Stream結(jié)果聚合成為一個(gè)包含總和、最大值、最小值、平均值的結(jié)果,可以使用Collectors.summaring{Int | Long | Double}方法中的一種,這些方法會(huì)接受一個(gè)將Stream對(duì)象的元素映射為一個(gè)數(shù)字的函數(shù),并產(chǎn)生一個(gè){Int | Long | Double}SummaryStatistics類型的結(jié)果,其中包含了獲取總和、最大值、最小值、平均值:
IntSummaryStatistics summary = words.collect(Collectors.summarizingInt(String::length));
double arerageWordLength = summary.getAverage();
double maxWordLength = summary.getMax();

  1. <R> R collect(Supplier<R> supplier, BiConsumer<R, ? super T> accumulator, BiConsumer<R, R> combiner); // 自定義supplier、accumulator、combiner

supplier– a function that creates a new result container. For a parallel execution, this function may be called multiple times and must return a fresh value each time.
accumulator– an associative, non-interfering, stateless function for incorporating an additional element into a result.
combiner– an associative, non-interfering, stateless function for combining two values, which must be compatible with the accumulator function.
示例:
Stream<String> stream = ...;
HashSet<String> result = stream.collect(HashSet::new, HashSet::add, HashSet::addAll);

  • 遍歷獲取元素,兩種方式:

  • void forEach(Consumer<? super T> action); 非順序遍歷Stream元素,對(duì)于并行stream則并行遍歷,順序無(wú)法保證,但能提升遍歷效率

  • void forEachOrdered(Consumer<? super T> action);順序遍歷元素,保證順序性,但是犧牲了性能

將結(jié)果收集到Map中:

// 普通toMap Collector,如果鍵沖突則會(huì)跑出IllegalStateException
Stream<Person> persons = ...;
Map<String, String> idToName = persons.collect(Collectors.toMap(Person::getId, Person::getName));
Map<String, Person> idToPerson = persons.collect(Collectors.toMap(Person::getId, Function.identity()));
// 定義鍵沖突解決策略,保留舊值
Stream<Locale> locales = Stream.of(Locale.getAvailableLocales());
Map<String, String> languages = locales.collect(Collectors.toMap(lan - > lan.getDisplayCountry(),
	lan -> lan.getDisplayLanguage(),
	(existingValue, newValue) - > existingValue));
Map<String, Person> idToPerson = persons.collect(Collectors.toMap(Person::getId, Function.identity()));
// 定義鍵沖突解決策略,以Set方式保留所有值
Stream<Locale> locales = Stream.of(Locale.getAvailableLocales());
Map<String, String> languages = locales.collect(Collectors.toMap(lan - > lan.getDisplayCountry(),
	lan -> Collections.singleton(lan.getDisplayLanguage(),
	(existingValue, newValue) - > {
		Set<String> mergedSet = new HashSet<>(existingValue);
		mergedSet.addAll(newValue);
		return mergedSet;
	};
));
// 通過(guò)指定第四個(gè)參數(shù),將結(jié)果收集到TreeMap中去
Stream<Locale> locales = Stream.of(Locale.getAvailableLocales());
Map<String, String> languages = locales.collect(Collectors.toMap(lan - > lan.getDisplayCountry(),
	lan -> lan.getDisplayLanguage(),
	(existingValue, newValue) - > existingValue),
	TreeMap::new));

分組和分片

預(yù)定義的分組分片

  • Collectors.groupingBy
    Stream收集到Map過(guò)程中,通過(guò)分組,來(lái)簡(jiǎn)化相同鍵的合并問(wèn)題,示例如下:
    Map<String, List<Locale>> countryToLocales = locales.collect(Collectors.groupingBy(Locale::getCountry));
    函數(shù)Locale::getCountry是進(jìn)行分組的分類函數(shù)。

  • Collectors.partitioningBy
    當(dāng)分組函數(shù)是一個(gè)Prdicate函數(shù)時(shí),即要將Stream中的元素分為是/非兩組時(shí),使用partitioningBy會(huì)更高效些,示例如下:
    Map<Boolean, List<Locale>> englishAndOtherLocales = locales.collect(Collectors.partitioningBy(lan -> lan.getLanguage().equals("en")));
    將元素分為兩組:一組使用英語(yǔ),一組使用其他語(yǔ)言。獲取英語(yǔ)分組列表:
    List<Locale> englishLocales = englishAndOtherLocales.get(true);

  • Collectors.groupingByConcurrent
    會(huì)獲取一個(gè)并發(fā)Map,當(dāng)用于并行流時(shí)可以并發(fā)地插入值。這與toConcurrentMap方法完全類似。

分組分片downstream處理

  • downstream
    方法groupingBy會(huì)產(chǎn)生一個(gè)值為列表的map的對(duì)象,如果希望對(duì)這個(gè)列表進(jìn)行轉(zhuǎn)換,例如轉(zhuǎn)為Set,則可基于downstream實(shí)現(xiàn),例如:
    Map<String, Set<Locale>> countryToLocaleSet = locales.collect(Collectors.groupingBy(Locale::getCountry, Collectors.toSet()));

  • 其他downstream

  • counting()
    Map<String, Long> countryToLocaleCount = locales.collect(Collectors.groupingBy(Locale::getCountry, Collectors.counting())); // 計(jì)算每個(gè)國(guó)家有多少種語(yǔ)言

  • summing{Int | Long | Double}(ToIntFunction mapper)
    Map<String, Integer> stateToCityPopucation = cities.collect(Collectors.groupingBy(City::getState, Collectors.summingInt(City::getPopulation()))); // 計(jì)算每個(gè)下屬所有城市人數(shù)總和

  • maxBy(Comparator comparator) 和minBy(Comparator comparator)
    Map<String, City> stateToLargestCity = cities.collect(Collectors.groupingBy(City::getState, Collectors.maxBy(Comparator.comparing(City::getPopulation)))); // 計(jì)算每個(gè)州中人口最多的城市

  • mapping(Function mapper, Collector downstream)
    Map<String, Optional<String>> stateToLargestCityName = cities.collect(Collectors.groupingBy(City::getState, Collectors.mapping(City::getName, Collectors.maxBy(Comparator.comparing(String::length)))))// 找出每個(gè)州中,名字最長(zhǎng)的城市名稱
    Map<String, Set<String>> countryToLanguages = locales.collect(Collectors.groupingBy(Locale::getDisplayCountry, mapping(Locale::getDisplayLanguage, Collectors.toSet())))

  • 如果grouping或者mapping函數(shù)的返回結(jié)果是int、long、double,可以將元素收集到summaryStatistics對(duì)象中:
    Map<String, IntSummaryStatistics> statistics = locales.collect(Colloctors.groupingBy(Locale::getState, summarizingInt(City::getPopulation)));

  • reducing方法可對(duì)downstream元素進(jìn)行一次普通聚合

  • Collector reducing(BinaryOperator op)

  • Collector reducing(identity, BinaryOperator op)

  • Collector reducing(identity, Function mapper, BinaryOperator op)
    示例:
    Map<String, String> stateToCityNames = cities.collect(groupingBy(City:getState, reducing("", City::getName, (s, t) -> s.length == 0 ? t : s + "," + t)))
    等價(jià)于:
    Map<String, String> stateToCityNames = cities.collect(groupingBy(City:getState, mapping( City::getName, joining(","))));

原始類型流

背景

將整型收集到一個(gè)Stream<Integer>的流中,需要將每個(gè)整數(shù)封裝成一個(gè)包裝對(duì)象,這是一個(gè)低效的做法,double/float/long/short/byte/boolean也一樣,所以,Stream API專門設(shè)計(jì)了IntStream、LongStream、DoubleStream用于存放基本數(shù)據(jù)類型;

  • IntStream:用于存放int、short、char、byte和boolean類型的值;

  • LongStream:用于存放long型的值;

  • DoubleStream:用于存放double、float類型的值;

示例

  • 創(chuàng)建IntStream,使用IntStream.of和Arrays.stream
    IntStream stream = IntStream.of(1,1,2,3,5);
    int[] array = new int[]{1,1,2,3,5};
    stream = Arrays.stream(array, 0, array.length);

  • IngStream和LongStream的range和rangeClosed方法:
    IntStream zeroTo99 = IntStream.range(0, 100); //不包括上線100
    IntStream zeroTo100 = IntStream.rangeClosed(0, 100);//包括上線100

  • 對(duì)于對(duì)象流,可使用mapToInt、mapToLong、mapToDouble轉(zhuǎn)換為對(duì)應(yīng)的原始類型的流。例如:
    Stream<String> words = ...;
    IntStream lengths = words.mapToInt(String::length);

  • 原始類型流的常用方法:
    sum、max、min、average、summaryStatistics等。

  • Random類的ints、longs、doubles分別產(chǎn)生對(duì)應(yīng)的原始類型隨機(jī)數(shù)字流。

并行流

  • 默認(rèn)情況下,除了Collection.parallelStream()外,流操作創(chuàng)建的都是串行流。

  • 開啟并行流(在終止方法執(zhí)行前)

Collection.parallelStream()、Stream.parallel()

  • 當(dāng)無(wú)需考慮Stream元素順序時(shí),Stream.unordered()會(huì)使并行操作更好地執(zhí)行,例如distinct(),因?yàn)閷?duì)于一個(gè)有序的流,distinct()操作總會(huì)保留所有相同元素的第一個(gè),同樣的操作還有l(wèi)imit();

到此,關(guān)于“Java8 Stream API有什么作用”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)?lái)更多實(shí)用的文章!

分享文章:Java8StreamAPI有什么作用
標(biāo)題鏈接:http://jinyejixie.com/article40/pppseo.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站設(shè)計(jì)、網(wǎng)站導(dǎo)航、網(wǎng)站收錄、靜態(tài)網(wǎng)站、域名注冊(cè)、響應(yīng)式網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

綿陽(yáng)服務(wù)器托管
高清| 三穗县| 衡东县| 临漳县| 休宁县| 封丘县| 土默特右旗| 佛坪县| 景德镇市| 广饶县| 南城县| 读书| 五华县| 依兰县| 大方县| 万年县| 苍梧县| 阿勒泰市| 宁乡县| 温宿县| 北宁市| 绵阳市| 衡水市| 马鞍山市| 宁明县| 江达县| 中卫市| 河西区| 观塘区| 吐鲁番市| 固原市| 陆良县| 永城市| 佛冈县| 永丰县| 双城市| 保德县| 吴桥县| 西宁市| 修水县| 科尔|