中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁(yè) > news >正文

接做網(wǎng)站單子seo營(yíng)銷(xiāo)工具

接做網(wǎng)站單子,seo營(yíng)銷(xiāo)工具,濟(jì)南網(wǎng)站建設(shè) 推搜點(diǎn),wordpress登錄不jdk1.8 List集合Stream流式處理 一、介紹(為什么需要流Stream,能解決什么問(wèn)題?)1.1 什么是 Stream?1.2 常見(jiàn)的創(chuàng)建Stream方法1.3 常見(jiàn)的中間操作1.4 常見(jiàn)的終端操作 二、創(chuàng)建流Stream2.1 Collection的.stream()方法2.2 數(shù)組創(chuàng)建流2.3 靜態(tài)工廠…

jdk1.8 List集合Stream流式處理

  • 一、介紹(為什么需要流Stream,能解決什么問(wèn)題?)
    • 1.1 什么是 Stream?
    • 1.2 常見(jiàn)的創(chuàng)建Stream方法
    • 1.3 常見(jiàn)的中間操作
    • 1.4 常見(jiàn)的終端操作
  • 二、創(chuàng)建流Stream
    • 2.1 Collection的.stream()方法
    • 2.2 數(shù)組創(chuàng)建流
    • 2.3 靜態(tài)工廠方法
    • 2.4 Stream.builder
    • 2.5 從文件創(chuàng)建流
  • 三、中間操作
    • 3.1 過(guò)濾(Filter)
    • 3.2 映射(Map)
    • 3.3 映射(flatMap)
    • 3.4 排序(Sorted)
    • 3.5 distinct(去重,含轉(zhuǎn)Set去重)
    • 3.6 skip limit(分頁(yè))
    • 3.7 peek(循環(huán))
    • 3.8 mapToInt、mapToDouble ...
  • 四、終端操作
    • 4.0 foreach(常用于處理List、Map等數(shù)據(jù))
    • 4.1 收集(Collect)
      • 4.1.1 轉(zhuǎn)換為L(zhǎng)ist
      • 4.1.2 轉(zhuǎn)換為Set
      • 4.1.3 分組匯總(Grouping)
      • 4.1.4 toMap(轉(zhuǎn)成Map)
      • 4.1.5 reducing 規(guī)約(此處只討論簡(jiǎn)單使用,重載方法待研究)
      • 4.1.6 計(jì)數(shù)(Counting)
      • 4.1.7 匯總求和(Summing)
      • 4.1.8 匯總對(duì)象(IntSummaryStatistics)
      • 4.1.9 獲取單個(gè)元素 maxBy、 minBy
      • 4.1.10 toCollection()
      • 4.1.11 mapping
      • 4.1.12 joining
      • 4.1.13 partitioningBy
      • 4.1.14 collectingAndThen
    • 4.2. 自定義收集器
    • 4.3 歸約(Reduce)
    • 4.4 查找元素 findFirst、findAny
    • 4.5 匹配 anyMatch、allMatch、noneMatch
    • 4.6 count max min
  • 五、并行流
  • 六、總結(jié)
    • 6.1 Stream的優(yōu)點(diǎn):
    • 6.2 Stream的缺點(diǎn)

一、介紹(為什么需要流Stream,能解決什么問(wèn)題?)

Java 8 引入了一個(gè)新的抽象層——Stream API,它允許你以聲明性方式處理數(shù)據(jù)集合(包括數(shù)組、集合等)。Stream API 提供了一種高效且易于表達(dá)的方式來(lái)處理數(shù)據(jù)集合,包括過(guò)濾、排序、映射和歸約等操作。這種處理方式極大地提高了代碼的可讀性和可維護(hù)性,同時(shí)也提升了處理大量數(shù)據(jù)的性能。

1.1 什么是 Stream?

Stream(流)是 Java 8 引入的一個(gè)關(guān)鍵抽象概念,它代表了一個(gè)來(lái)自數(shù)據(jù)源的元素隊(duì)列并支持聚合操作。和迭代器(Iterator)不同,Stream 不存儲(chǔ)元素;它們是源到聚合操作的中間橋梁,其操作的執(zhí)行是延遲的,即只有在需要結(jié)果時(shí)才執(zhí)行。
在日常編程中,會(huì)經(jīng)常進(jìn)行數(shù)據(jù)(如List、數(shù)組)的處理,在沒(méi)有stram流時(shí),我們的一般操作方式顯得比較臃腫,不夠優(yōu)雅簡(jiǎn)潔。代碼如下(原寫(xiě)法):

        List<String> list = new ArrayList<>();Collections.addAll(list,"趙子龍","關(guān)云長(zhǎng)","黃忠","張良","張翼德");ArrayList<String> list1 = new ArrayList<>();list.forEach(s -> {if(s.startsWith("張")) {list1.add(s);}});list1.forEach(s -> System.out.println(s));

stream流式寫(xiě)法

        List<String> list = new ArrayList<>();Collections.addAll(list,"趙子龍","關(guān)云長(zhǎng)","黃忠","張良","張翼德");list.stream().filter(p -> p.startsWith("張")).forEach(System.out::println);

這個(gè)例子也告訴我們Stream流寫(xiě)法更加簡(jiǎn)潔優(yōu)雅。
流式操作三部曲如下圖所示:
在這里插入圖片描述
如上圖所示,概括的講,可以將stream流操作分為3種類(lèi)型

  • 創(chuàng)建Stream
  • Stream中間操作
  • 終止Stream(終端操作)

每個(gè)Stream管道操作類(lèi)型都包含若干API方法,先列舉下各個(gè)API方法的功能介紹。

1.2 常見(jiàn)的創(chuàng)建Stream方法

在Java中,創(chuàng)建Stream的方法多種多樣,可以從各種數(shù)據(jù)源生成Stream。以下是一些常見(jiàn)的創(chuàng)建Stream的方法:

方法類(lèi)型示例代碼描述
集合轉(zhuǎn)StreamList<String> list = Arrays.asList("a", "b", "c");<br>Stream<String> stream = list.stream();通過(guò)Collection接口(如List、Set等)的stream()方法創(chuàng)建Stream。
數(shù)組轉(zhuǎn)StreamString[] array = {"d", "e", "f"};<br>Stream<String> stream = Arrays.stream(array);通過(guò)Arrays類(lèi)的stream(T[] array)靜態(tài)方法,將數(shù)組轉(zhuǎn)換為Stream。
Stream類(lèi)靜態(tài)方法Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5);使用Stream類(lèi)的of(T... values)靜態(tài)方法,從一組值中創(chuàng)建Stream。
無(wú)限流生成Stream<Double> randomStream = Stream.generate(Math::random);
Stream<Integer> infiniteStream = Stream.iterate(0, i -> i + 1);
使用Stream類(lèi)的generate(Supplier<T> s)iterate(T seed, UnaryOperator<T> f)靜態(tài)方法生成無(wú)限流。generate接受一個(gè)供應(yīng)器(Supplier),每次需要新值時(shí)調(diào)用其get()方法;iterate接受一個(gè)初始值和一個(gè)函數(shù),每次迭代時(shí)將當(dāng)前值作為參數(shù)傳遞給函數(shù),返回的結(jié)果作為下一次迭代的值。
空StreamStream<String> emptyStream = Stream.empty();使用Stream類(lèi)的empty()靜態(tài)方法創(chuàng)建一個(gè)空的Stream。
構(gòu)建器Stream.Builder<String> builder = Stream.builder();<br>builder.add("Java");<br>builder.add("Python");<br>Stream<String> stream = builder.build();使用Stream.Builder來(lái)構(gòu)建復(fù)雜的Stream。首先創(chuàng)建一個(gè)Builder對(duì)象,然后調(diào)用其add方法添加元素,最后調(diào)用build方法生成Stream。

1.3 常見(jiàn)的中間操作

操作名稱操作方法描述
過(guò)濾filter(Predicate<? super T> predicate)通過(guò)給定的謂詞(predicate)測(cè)試元素,保留使謂詞返回true的元素
映射map(Function<? super T, ? extends R> mapper)將每個(gè)元素映射到其對(duì)應(yīng)的轉(zhuǎn)換結(jié)果上,轉(zhuǎn)換結(jié)果可以是一個(gè)新的類(lèi)型
扁平映射flatMap(Function<? super T, ? extends Stream<? extends R>> mapper)類(lèi)似于map,但每個(gè)元素都可以被映射成一個(gè)Stream,然后所有這些Stream會(huì)被合并成一個(gè)Stream
排序sorted() / sorted(Comparator<? super T> comparator)對(duì)流中的元素進(jìn)行排序,可以選擇自然排序或自定義排序器
截?cái)?/td>limit(long maxSize)限制流中元素的數(shù)量,使其不超過(guò)給定的最大值
跳過(guò)skip(long n)跳過(guò)流中的前n個(gè)元素
并行流.parallel()將順序流轉(zhuǎn)換為并行流,以便并行處理
串行流.sequential()將并行流轉(zhuǎn)換回順序流,以便順序處理
去重distinct()返回一個(gè)由流中不同元素組成的流(基于元素的equalshashCode方法)
逐元素替換peek(Consumer<? super T> action)提供一個(gè)消費(fèi)者函數(shù),該函數(shù)會(huì)在處理每個(gè)元素時(shí)執(zhí)行,但不影響流的內(nèi)容

請(qǐng)注意,盡管peek操作可以看作是一種中間操作(因?yàn)樗祷豐tream本身),但它主要用于調(diào)試目的,并不改變流的內(nèi)容或結(jié)構(gòu)。

1.4 常見(jiàn)的終端操作

操作名稱操作方法描述
匹配操作anyMatch(Predicate<? super T> predicate)是否存在至少一個(gè)元素匹配給定的謂詞?
allMatch(Predicate<? super T> predicate)是否所有元素都匹配給定的謂詞?
noneMatch(Predicate<? super T> predicate)是否沒(méi)有元素匹配給定的謂詞?
查找操作findFirst()返回流中的第一個(gè)元素(作為Optional),如果流為空,則返回Optional.empty()
findAny()返回流中的任意元素(作為Optional),對(duì)于并行流,行為可能不同
歸約操作reduce(BinaryOperator<T> accumulator)通過(guò)給定的歸約操作(如求和、求積)將流中的所有元素組合起來(lái),結(jié)果為Optional
reduce(T identity, BinaryOperator<T> accumulator)類(lèi)似于上一個(gè),但提供了一個(gè)初始值,結(jié)果為T(mén)類(lèi)型,而非Optional
收集操作collect(Collectors.toList()) / collect(Collectors.toSet())將流中的元素收集到一個(gè)列表、集合或其他容器中,Collectors類(lèi)提供了多種收集器
最大值/最小值max(Comparator<? super T> comparator) / min(Comparator<? super T> comparator)根據(jù)給定的比較器找到流中的最大或最小元素,結(jié)果為Optional
數(shù)組操作toArray(T[] generator) / toArray(IntFunction<T[]> generator)將流中的元素收集到一個(gè)數(shù)組中,需要提供一個(gè)數(shù)組生成器或類(lèi)型信息
計(jì)數(shù)操作count()返回流中的元素?cái)?shù)量,結(jié)果為long類(lèi)型
遍歷操作forEach(Consumer<? super T> action)對(duì)流中的每個(gè)元素執(zhí)行給定的操作,這是一個(gè)終端操作,因?yàn)樗懈弊饔?#xff08;即執(zhí)行操作)
歸納操作summaryStatistics()(針對(duì)IntStream, LongStream, DoubleStream)返回包含各種統(tǒng)計(jì)數(shù)據(jù)的對(duì)象,如計(jì)數(shù)、平均值、最大值、最小值等

請(qǐng)注意,forEach雖然是一個(gè)終端操作,但它主要用于執(zhí)行副作用(即不返回結(jié)果的操作),而不是為了獲取結(jié)果。同樣,reducecollectmax/min等操作既可以看作是中間操作(因?yàn)樗鼈兛梢栽诹硪粋€(gè)流的上下文中使用,盡管這在實(shí)際中并不常見(jiàn)),也可以看作是終端操作(因?yàn)樗鼈儠?huì)觸發(fā)流的執(zhí)行并返回一個(gè)結(jié)果)。但是,在典型的用法中,我們更傾向于將它們視為終端操作。

二、創(chuàng)建流Stream

2.1 Collection的.stream()方法

    public static void main(String[] args) {// 1.list創(chuàng)建流List<String> list = new ArrayList<>();Collections.addAll(list, "趙子龍", "關(guān)云長(zhǎng)", "黃忠", "張良", "張翼德");// 創(chuàng)建一個(gè)Stream流Stream<String> stream = list.stream();// 使用流進(jìn)行操作stream.filter(p -> p.startsWith("張")).forEach(System.out::println);// 2.map創(chuàng)建流(先轉(zhuǎn)換成keySet或entrySet)Map<Object, Object> map = new HashMap<>();map.put("張三", 1);map.put("李四", 8);map.put("王五", 5);// 2.1 keySetmap.keySet().stream().forEach(System.out::println);map.keySet().stream().forEach(p -> System.out.println(p + "= " + map.get(p)));// 2.2 entrySetmap.entrySet().stream().forEach(System.out::println);}

示例中,用list.stream()創(chuàng)建流,用map裝換成keySet或entrySet后用.stream()創(chuàng)建流。

2.2 數(shù)組創(chuàng)建流

        int[] array = {5,6,8,7,5,6,1,0};// 1.從整數(shù)數(shù)組創(chuàng)建IntStreamIntStream intStream = Arrays.stream(array);String[] strArray = {"東邪","西毒","南帝","北丐","中神通"};// 2.從字符串?dāng)?shù)組創(chuàng)建StreamStream<String> stringStream = Arrays.stream(strArray);

示例中,用Arrays.stream()創(chuàng)建流(IntStream 、Stream),為開(kāi)發(fā)中最常用創(chuàng)建流的方式。

2.3 靜態(tài)工廠方法

Stream.of(T… values):通過(guò)將一個(gè)可變參數(shù)的元素列表傳遞給Stream.of方法來(lái)創(chuàng)建一個(gè)包含這些元素的Stream流。這對(duì)于創(chuàng)建具有少量元素的流非常方便。
Stream.empty():使用Stream.empty()方法創(chuàng)建一個(gè)空的Stream流。
Stream.generate(Supplier s):通過(guò)提供一個(gè)Supplier函數(shù)來(lái)創(chuàng)建一個(gè)無(wú)限大小的Stream流,該函數(shù)會(huì)生成元素。通常,需要使用limit操作限制生成的元素?cái)?shù)量。
Stream.iterate(T seed, UnaryOperator f):通過(guò)提供初始值(seed)和一個(gè)一元操作函數(shù)(UnaryOperator)來(lái)創(chuàng)建一個(gè)包含無(wú)限序列的Stream流。例如,可以使用Stream.iterate(0, n -> n + 1)來(lái)創(chuàng)建一個(gè)自然數(shù)序列的Stream流。

  • Stream.of(T… values)創(chuàng)建流
		// 1.String數(shù)組String[] strArr = {"東邪","西毒","南帝","北丐","中神通"};Stream<String> strArrStream = Stream.of(strArr);strArrStream.forEach(System.out::println);// 2.注意:int類(lèi)型數(shù)組,會(huì)將數(shù)組僅當(dāng)作一個(gè)處理,如下圖所示打印的是一個(gè)int[]的地址int[] intArr = {5,6,8,7,5,6,1,0};Stream<int[]> intArrStram = Stream.of(intArr);intArrStram.forEach(System.out::println);

打印如下:
在這里插入圖片描述

  • Stream.generate(Supplier s)創(chuàng)建流
        // generate創(chuàng)建streamStream<Integer> randomIntStream = Stream.generate(() -> new Random().nextInt(100));randomIntStream.limit(10).forEach(System.out::println);

2.4 Stream.builder

  • Stream.builder創(chuàng)建Stream<Integer>
        // 1.逐個(gè)添加1到10的整數(shù)Stream.Builder<Integer> builder = Stream.builder();for (int i = 0; i < 10; i++) {builder.accept(i);}Stream<Integer> builderIntStream = builder.build();
  • Stream.builder創(chuàng)建Stream<Long>
        // 2.斐波那契數(shù)列的前10個(gè)數(shù)字Stream.Builder<Long> builder1 = Stream.builder();long a = 0; long b = 1;int count = 10;for (int i = 0; i < count; i++) {builder1.accept(a);long next = a + b;a = b;b = next;}Stream<Long> longStream = builder1.build();

2.5 從文件創(chuàng)建流

  • 使用Files.lines方法創(chuàng)建文本文件的流
        // 逐行讀取,創(chuàng)建StreamString path = "names.txt";try {Stream<String> lines = Files.lines(Paths.get(path));List<String> names = lines.collect(Collectors.toList());} catch (IOException e) {throw new RuntimeException(e);}

三、中間操作

基礎(chǔ)代碼創(chuàng)建list

        List<User> userList = new ArrayList<>();User user1 = User.builder().name("曹操").age(12).desc("許昌").build();User user2 = User.builder().name("劉備").age(22).desc("西蜀").build();User user3 = User.builder().name("曹操").age(42).desc("許昌").build();User user4 = User.builder().name(null).age(32).desc("許昌").build();userList.add(user1);userList.add(user2);userList.add(user3);userList.add(user4);

3.1 過(guò)濾(Filter)

filter(Predicate<? super T> predicate) 方法接收一個(gè)謂詞(即返回布爾值的函數(shù)),并返回一個(gè)包含所有匹配該謂詞的元素的流。如下所示,常規(guī)過(guò)濾可直接簡(jiǎn)單寫(xiě),復(fù)雜的過(guò)濾,可抽取方法,使代碼更加清晰。

{...// 1.常規(guī)簡(jiǎn)單過(guò)濾List<User> overNList1 = userList.stream().filter(p -> p.getAge() > 18).collect(Collectors.toList());// 2.復(fù)雜過(guò)濾時(shí),可抽取方法List<User> overNList2 = userList.stream().filter(p -> isOverN(p)).collect(Collectors.toList());...
}// 示例:isOverNprivate static boolean isOverN(User p) {return p.getAge() > 18;}

3.2 映射(Map)

map(Function<? super T, ? extends R> mapper) 方法將流中的每個(gè)元素映射到另一個(gè)對(duì)象,并返回一個(gè)新的流。

        // 1.裝換成簡(jiǎn)單數(shù)據(jù)集合,如StringList<String> names = userList.stream().map(User::getName).collect(Collectors.toList());// 2.裝換成其它對(duì)象集合List<Address> addressList = userList.stream().map(p -> Address.builder().content(p.getDesc()).build()).collect(Collectors.toList());// 3.mapToInt maxToDouble maxToLong等,此類(lèi)轉(zhuǎn)換好處是可以獲取如max、min、average、count等統(tǒng)計(jì)類(lèi)數(shù)據(jù)long count = userList.stream().mapToInt(User::getAge).count();System.out.println("count = " + count);

3.3 映射(flatMap)

flatMap(Function<? super T, ? extends Stream<? extends R>> mapper) flatMap操作與map類(lèi)似,但它被設(shè)計(jì)用來(lái)處理那些將每個(gè)輸入元素映射到多個(gè)輸出元素的場(chǎng)景。flatMap首先應(yīng)用一個(gè)函數(shù)來(lái)映射每個(gè)元素,這個(gè)函數(shù)返回一個(gè)流(而不是單個(gè)元素)。然后,flatMap將這些流“扁平化”成一個(gè)流。

List<String> sentences = Arrays.asList("apple,banana", "cherry,date");  
List<String> words = sentences.stream()  .flatMap(sentence -> Arrays.stream(sentence.split(",")))  .collect(Collectors.toList());  
// words: ["apple", "banana", "cherry", "date"]

適用于元素逐個(gè)拆分,并組成新的集合。每個(gè)元素處理并返回一個(gè)新的Stream,然后將多個(gè)Stream展開(kāi)合并為了一個(gè)完整的新的Stream。

3.4 排序(Sorted)

sorted()sorted(Comparator<? super T> comparator) 方法對(duì)流中的元素進(jìn)行排序,關(guān)于sorted的用法非常多。

        // 0.默認(rèn)規(guī)則排序 適用于基本類(lèi)型List<String> users = Arrays.stream(new String[]{"東邪", "西毒", "南帝", "北丐", "中神通"}).sorted().collect(Collectors.toList());// 1.自定義排序規(guī)則List<User> users2 = userList.stream().sorted((o1, o2) -> o2.getAge().compareTo(o1.getAge())).collect(Collectors.toList());// 2.年齡排序 倒敘List<User> ageSortedList = userList.stream().sorted(Comparator.comparing(User::getAge).reversed()).collect(Collectors.toList());// 3.姓名排序 (忽略大小寫(xiě))List<User> nameSortedList = userList.stream().sorted(Comparator.comparing(User::getName, String.CASE_INSENSITIVE_ORDER)).collect(Collectors.toList());// 4.先按年齡排序,如果年齡相同則按姓名排序List<User> ageAndNameSortedList = userList.stream().sorted(Comparator.comparing(User::getAge).thenComparing(User::getName, String.CASE_INSENSITIVE_ORDER)).collect(Collectors.toList());// 5.排序處理null值 nullsLast或nullsFirst// 6.null排在最前面,其他非null對(duì)象根據(jù)age倒敘排列 Comparator.reverseOrder()List<User> nullLastSortedList = userList.stream().sorted(Comparator.comparing(User::getAge, Comparator.nullsFirst(Comparator.reverseOrder()))).collect(Collectors.toList());nullLastSortedList.forEach(System.out::println);// 7.null排在最前面,其他非null對(duì)象根據(jù)age正序排列 Comparator.naturalOrder()List<User> nullLastSortedList1 = userList.stream().sorted(Comparator.comparing(User::getAge, Comparator.nullsFirst(Comparator.naturalOrder()))).collect(Collectors.toList());nullLastSortedList1.forEach(System.out::println);// 8.null排在最前面,其他非null對(duì)象根據(jù)age正序排列,并將最終結(jié)果反轉(zhuǎn)List<User> nullLastSortedList2 = userList.stream().sorted(Comparator.comparing(User::getAge, Comparator.nullsFirst(Comparator.naturalOrder())).reversed()).collect(Collectors.toList());nullLastSortedList2.forEach(System.out::println);System.out.println("++++++++++++++++++++++++++++++++");// 9.先根據(jù)age排序,null排在最前面,其他的倒序排列; null相同的按照l(shuí)evel正序排列  level中為null的排前面; 其他的正序排列List<User> nullLastSortedList3 = userList.stream().sorted(Comparator.comparing(User::getAge, Comparator.nullsFirst(Comparator.reverseOrder())).thenComparing(Comparator.comparing(User::getLevel, Comparator.nullsFirst(Comparator.naturalOrder())).reversed())).collect(Collectors.toList());nullLastSortedList3.forEach(System.out::println);System.out.println("///");// 10.先根據(jù)age排序,null排在最前面,其他的正序排列;List<User> nullLastSortedList4 = userList.stream().sorted(Comparator.comparing(User::getAge, Comparator.nullsFirst(Integer::compareTo))).collect(Collectors.toList());nullLastSortedList4.forEach(System.out::println);// 11.先根據(jù)age排序,null排在最前面,其他的正序排列,并將最終結(jié)果反轉(zhuǎn)List<User> nullLastSortedList6 = userList.stream().sorted(Comparator.comparing(User::getAge, Comparator.nullsFirst(Integer::compareTo).reversed())).collect(Collectors.toList());nullLastSortedList6.forEach(System.out::println);// 12.自定義復(fù)雜排序規(guī)則userList.stream().sorted(new Comparator<User>() {@Overridepublic int compare(User o1, User o2) {Date o1OpTime = DateUtil.parse(o1.getOpTime(), DateUtil.FULL_DAY_FORMAT);Date o2OpTime = DateUtil.parse(o2.getOpTime(), DateUtil.FULL_DAY_FORMAT);// 正序
//                return o1OpTime.compareTo(o2OpTime);// 倒敘return o2OpTime.compareTo(o1OpTime);}});

其中,nullsLast同理。

3.5 distinct(去重,含轉(zhuǎn)Set去重)

distinct() 為基礎(chǔ)數(shù)據(jù)簡(jiǎn)單去重操作, 后文會(huì)講到通過(guò) Collectors.toCollection結(jié)合TreeSet排序去重

        // 1.基本類(lèi)型簡(jiǎn)單去重List<String> list = Arrays.asList(new String[]{"劉備", "張飛", "趙云", "劉備"});List<String> collect = list.stream().distinct().collect(Collectors.toList());collect.forEach(System.out::println);// 終端操作去重// 2.toCollection()去重:根據(jù)對(duì)象某個(gè)字段去重(去重規(guī)則:取第一條數(shù)據(jù),可排序后再去重,如下所示:取年齡最小的對(duì)象)TreeSet<User> nameSet = userList.stream().sorted(Comparator.comparing(User::getAge)).collect(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(User::getName))));// 3.toCollection()去重:自定義規(guī)則去重(同樣可先排序再去重)TreeSet<User> nameSet2 = userList.stream().sorted(Comparator.comparing(User::getAge)).collect(Collectors.toCollection(() -> new TreeSet<User>(new Comparator<User>() {@Overridepublic int compare(User o1, User o2) {return (o1.getName() + o1.getLevel()).equals(o2.getName() + o2.getLevel()) ? 0 : o1.getName().equals(null) ? 1 : -1 ;}})));nameSet.stream().forEach(System.out::println);

3.6 skip limit(分頁(yè))

skip(long n)limit(long maxSize)搭配實(shí)現(xiàn)分頁(yè)

        int pageSize = 3;int pageNo = 2;// 實(shí)現(xiàn)分頁(yè)功能List<User> users = userList.stream().skip(pageSize * (pageNo - 1)).limit(pageSize).collect(Collectors.toList());users.stream().forEach(System.out::println);

3.7 peek(循環(huán))

peek(Consumer<? super T> action)實(shí)現(xiàn)中間操作的循環(huán)操作

        // peek為中間操作,不對(duì)元素進(jìn)行操作,可用于記錄日志、或調(diào)試,與foreach的區(qū)別是:peek為中間操作(須有終端操作才會(huì)執(zhí)行Consumer)List<User> users3 = userList.stream().peek(p -> Syste
## 3.8 takeWhilem.out.println(p.getName())).collect(Collectors.toList());

3.8 mapToInt、mapToDouble …

		// mapToInt maxToDouble maxToLong等,此類(lèi)轉(zhuǎn)換好處是可以獲取如max、min、average、count等統(tǒng)計(jì)類(lèi)數(shù)據(jù)long count = userList.stream().mapToInt(User::getAge).count();System.out.println("count = " + count);

四、終端操作

4.0 foreach(常用于處理List、Map等數(shù)據(jù))

		// 循環(huán)逐個(gè)元素userList.stream().forEach(System.out::println);

4.1 收集(Collect)

collect操作接受一個(gè)Collector實(shí)例,該實(shí)例封裝了歸約操作的性質(zhì),比如如何添加元素、如何合并兩個(gè)歸約結(jié)果以及如何完成歸約過(guò)程等。不過(guò),在實(shí)際使用中,我們很少直接創(chuàng)建Collector實(shí)例,而是使用Collectors工具類(lèi)提供的靜態(tài)方法,這些方法返回了預(yù)定義的Collector實(shí)例。

以下是一些使用collect操作的常見(jiàn)示例:

4.1.1 轉(zhuǎn)換為L(zhǎng)ist

將流中的元素收集到一個(gè)列表中,可以使用Collectors.toList()。

        // 1.不修改元素類(lèi)型,可做完若干中間操作后,匯聚成listList<User> users = userList.stream().collect(Collectors.toList());// 2.轉(zhuǎn)換成其他類(lèi)型List<String> names = userList.stream().map(User::getName).collect(Collectors.toList());

4.1.2 轉(zhuǎn)換為Set

如果你想要去除流中的重復(fù)元素并將結(jié)果收集到一個(gè)集合中,可以使用Collectors.toSet()

 		// 1.轉(zhuǎn)換成Set, 僅基本類(lèi)型可使用Set<String> set = Arrays.asList(new String[]{"劉備", "張飛", "趙云", "劉備"}).stream().collect(Collectors.toSet());set.stream().forEach(System.out::println);

4.1.3 分組匯總(Grouping)

使用Collectors.groupingBy可以將流中的元素根據(jù)某些屬性進(jìn)行分組。

		// 分組 單個(gè)字段可簡(jiǎn)寫(xiě),多字段組合如下所示Map<String, List<User>> groupList1 = userList.stream().collect(Collectors.groupingBy(User::getName));Map<String, List<User>> groupList2 = userList.stream().collect(Collectors.groupingBy(p -> p.getName() + p.getLevel()));

4.1.4 toMap(轉(zhuǎn)成Map)

默認(rèn)規(guī)定:允許key為null,不允許value為null, 推薦使用3.1寫(xiě)法

        // 1.key不重復(fù)且value不為null的情況下,可用如下簡(jiǎn)單寫(xiě)法(為了保險(xiǎn)起見(jiàn),不推薦這種寫(xiě)法)Map<String, User> collect1 = userList.stream().collect(Collectors.toMap(User::getName, p -> p));// 2.處理key重復(fù)問(wèn)題,重復(fù)時(shí),取最新的valueMap<String, Integer> collect2= userList.stream().collect(Collectors.toMap(User::getName, User::getLevel, (oldValue, newValue) -> newValue));// 3.處理value為null問(wèn)題// 3.1 方案一:Optional設(shè)置orElse值,如0,空字符串等 (***推薦***),這種寫(xiě)法避免了key重復(fù),也可以避免value為null的情況Map<String, Integer> map3 = userList.stream().collect(Collectors.toMap(User::getName, p -> Optional.ofNullable(p.getLevel()).orElse(0), (oldV, newV) -> newV));// 3.2 方案二:規(guī)約轉(zhuǎn)換,null值取最新的Map<String, Integer> collect = userList.stream().collect(HashMap::new, (resultMap, item) -> resultMap.put(item.getName(), item.getLevel()), HashMap::putAll);collect.entrySet().forEach(System.out::println);

4.1.5 reducing 規(guī)約(此處只討論簡(jiǎn)單使用,重載方法待研究)

     	// 1.不指定初始值返回OptionalOptional<Integer> reduceSum = userList.stream().map(User::getAge).collect(Collectors.reducing(Integer::sum));// 2.指定初始值,返回intInteger reduceDefaultSum = userList.stream().map(User::getAge).collect(Collectors.reducing(0, Integer::sum));// 3.也可規(guī)約匯總對(duì)象User reducingLevel = userList.stream().collect(Collectors.reducing(new User(), (o1, o2) -> User.builder().age(o1.getAge() + o2.getAge()).level(o1.getLevel() + o2.getLevel()).build()));

4.1.6 計(jì)數(shù)(Counting)

Collectors.counting()可以返回一個(gè)收集器,它計(jì)算流中的元素?cái)?shù)量。

        // 計(jì)數(shù),與list.size()同效int size = userList.size();Long count = userList.stream().collect(Collectors.counting());

4.1.7 匯總求和(Summing)

        // 獲取單個(gè)字段的和summingIntInteger ageSum = userList.stream().collect(Collectors.summingInt(User::getAge));

4.1.8 匯總對(duì)象(IntSummaryStatistics)

如果你有一個(gè)包含數(shù)值的流,并想要計(jì)算這些數(shù)值的總和,平均值,最大值,最小值等,可以使用Collectors.summingInt()(對(duì)于整數(shù))等方法。

        // 統(tǒng)計(jì)對(duì)象 IntSummaryStatistics,可根據(jù)此對(duì)象獲取max、min...IntSummaryStatistics intSummaryStatistics = userList.stream().collect(Collectors.summarizingInt(User::getAge));long sum1 = intSummaryStatistics.getSum();long count1 = intSummaryStatistics.getCount();int max = intSummaryStatistics.getMax();int min = intSummaryStatistics.getMin();double average = intSummaryStatistics.getAverage();

4.1.9 獲取單個(gè)元素 maxBy、 minBy

        // 根據(jù)某個(gè)字段取最小值(最大值等)對(duì)應(yīng)的元素 maxBy minBy,返回Optional對(duì)象Optional<User> minUserOptinal = userList.stream().collect(Collectors.minBy(Comparator.comparing(User::getAge)));User user = minUserOptinal.orElse(null);User maxUser = userList.stream().collect(Collectors.maxBy(Comparator.comparing(User::getAge))).orElse(new User());

4.1.10 toCollection()

.toCollection() 是一個(gè)收集器(Collector),它用于將流中的元素收集到一個(gè)指定的Collection類(lèi)型中。這個(gè)收集器接受一個(gè)Supplier作為參數(shù),其中C是Collection的一個(gè)子類(lèi)型,這個(gè)Supplier用于提供一個(gè)新的、空的Collection實(shí)例,流中的元素將被添加到這個(gè)實(shí)例中。

        // toCollection 常與TreeSet去重使用// 1.簡(jiǎn)單轉(zhuǎn)SetTreeSet<User> userTreeSet = userList.stream().collect(Collectors.toCollection(TreeSet::new));// 2.基本類(lèi)型轉(zhuǎn)SetTreeSet<String> nameTreeSet = userList.stream().map(User::getName).collect(Collectors.toCollection(TreeSet::new));// 3.自定義不可重復(fù)(去重)規(guī)則TreeSet<User> userDefineSet = userList.stream().collect(Collectors.toCollection(() -> new TreeSet<>(new Comparator<User>() {@Overridepublic int compare(User o1, User o2) {return o1.getName().compareTo(o2.getName());}})));

4.1.11 mapping

  • 簡(jiǎn)單使用mapping
        // 1.與.map等效List<String> names1 = userList.stream().map(User::getName).collect(Collectors.toList());List<String> names2 = userList.stream().collect(Collectors.mapping(User::getName, Collectors.toList()));
  • 分組后轉(zhuǎn)換list元素的類(lèi)型,復(fù)雜對(duì)象的屬性轉(zhuǎn)換和收集
// 		2.與groupBy搭配使用,分組后,變換元素類(lèi)型 User -> AddressMap<String, List<Address>> collect = userList.stream().collect(Collectors.groupingBy(User::getName, Collectors.mapping(p -> {Address address = new Address();address.setContent(p.getDesc());return address;}, Collectors.toList())));// 與groupBy和join結(jié)合使用 拼接字符串Map<String, String> map1 =userList.stream().collect(Collectors.groupingBy(User::getName, Collectors.mapping(User::getDesc, Collectors.joining(",", "[", "]"))));map1.entrySet().stream().forEach(p -> {System.out.println(p.getKey() + ":" + p.getValue());});

4.1.12 joining

        // 常用于字符串拼接String str = list.stream().collect(Collectors.joining(",", "[", "]"));System.out.println("str = " + str);

4.1.13 partitioningBy

        // partitioningBy 根據(jù)Predicate<? super T> predicate,匯聚成含有兩個(gè)元素的map,//  其中一個(gè)key為Boolean.TRUE,另一個(gè)為Boolean.FALSE,value為滿足條件的集合Map<Boolean, List<User>> collect1 = userList.stream().collect(Collectors.partitioningBy(p -> {return p.getAge() >= 18;}, Collectors.toList()));

4.1.14 collectingAndThen

該方法的作用可以簡(jiǎn)單地概括為“先收集,再做一些操作”。

                // 1.常用于去重后TreeSet轉(zhuǎn)成List// 解析 通過(guò)Collectors.toCollection收集TreeSet排序去重,然后通過(guò)collectingAndThen收集轉(zhuǎn)成ListList<User> userList5 = userList.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(User::getName))), ArrayList::new));// 最終結(jié)果可以理解為如下操作TreeSet<User> treeSet = userList.stream().collect(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(User::getName))));List<User> users = new ArrayList<>(treeSet);// 2.收集成TreeSet<User>后,轉(zhuǎn)成List<Address>, 詳細(xì)寫(xiě)法List<Address> addressList = userList.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(User::getName))), p -> {List<Address> list1 = new ArrayList<>();p.stream().forEach(c -> {Address build = Address.builder().content(c.getDesc()).build();list1.add(build);});return list1;}));//3.簡(jiǎn)化流式寫(xiě)法如下userList.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(User::getName))), p -> p.stream().collect(Collectors.mapping(c -> Address.builder().content(c.getDesc()).build(), Collectors.toList()))));

4.2. 自定義收集器

你還可以使用Collectors.collectingAndThen()Collector.of()來(lái)創(chuàng)建自定義的收集器。

List<String> namesList = names.stream().collect(Collectors.collectingAndThen(Collectors.toList(),Collections::unmodifiableList));

上面的代碼示例將流中的元素收集到一個(gè)列表中,并立即將這個(gè)列表轉(zhuǎn)換為不可修改的列表。

4.3 歸約(Reduce)

reduce(BinaryOperator<T> accumulator) 方法通過(guò)重復(fù)結(jié)合流中的元素,將它們歸約成一個(gè)值。

        // 1.無(wú)初始值 注意orElse為Optional的方法(不推薦)Integer sumOrElse = userList.stream().map(User::getAge).reduce(Integer::sum).orElse(0);// 2.有初始值這種形式的 reduce 接受一個(gè)初始值和一個(gè) BiFunction<T, T, T> (推薦)Integer sum = userList.stream().map(User::getAge).reduce(0, Integer::sum);// 3.對(duì)象合并,可累加、累乘等User reduce = userList.stream().reduce(new User(), (o1, o2) -> {return User.builder().age(o1.getAge() + o1.getAge()).level(o1.getLevel() & o2.getLevel()).money(o1.getMoney() + o2.getMoney()).build();});

推薦使用有初始值的 reduce,因?yàn)樗梢詢?yōu)雅地處理空流的情況,并允許你指定一個(gè)明確的初始值(可不為0)。

reduce 操作非常靈活,不僅可以用于求和、求積等簡(jiǎn)單單數(shù)據(jù)的聚合操作,還可以實(shí)現(xiàn)更復(fù)雜的歸約邏輯,如字符串連接、對(duì)象合并(如案例3)等。

4.4 查找元素 findFirst、findAny

        // 1.可結(jié)合排序使用,獲取第一個(gè)元素Optional<User> first = userList.stream().findFirst();// 2.任意元素Optional<User> any = userList.stream().findAny();

4.5 匹配 anyMatch、allMatch、noneMatch

        // 1.anyMatch有一個(gè)滿足條件就返回trueboolean anyMatch= userList.stream().anyMatch(p -> p.getAge() == p.getLevel());// 2.allMatch所有元素都滿足條件就返回trueboolean allMatch = userList.stream().allMatch(p -> p.getAge() == p.getLevel());// 3.noneMatch 沒(méi)有元素滿足條件就返回trueboolean noneMatch = userList.stream().noneMatch(p -> p.getAge() == p.getLevel());

4.6 count max min

        // 1.獲取流中元素的個(gè)數(shù),如果List,則與list.size()等效long count = userList.stream().count();// 2.根據(jù)age字段獲取age最大值對(duì)應(yīng)的對(duì)象,返回Optional,可用orElse規(guī)避nullUser user = userList.stream().max(Comparator.comparing(User::getAge)).orElse(new User());// 3.同理,根據(jù)level字段獲取level最小值對(duì)應(yīng)的對(duì)象User user6 = userList.stream().min(Comparator.comparing(User::getLevel)).orElse(new User());

五、并行流

Java 8 引入了并行流的概念,允許你以并行方式處理數(shù)據(jù)集合,以利用多核處理器的優(yōu)勢(shì)。你可以通過(guò)調(diào)用 stream() 方法的并行版本 parallelStream() 來(lái)獲取一個(gè)并行流。

List<String> strings = Arrays.asList("apple", "banana", "cherry", ...);
long count = strings.parallelStream().filter(s -> s.startsWith("a")).count();

注意:并行流可能會(huì)同時(shí)處理多個(gè)元素,因此流中的操作必須是線程安全的。

六、總結(jié)

6.1 Stream的優(yōu)點(diǎn):

  • 代碼更簡(jiǎn)潔、偏聲明式的編碼風(fēng)格,更容易體現(xiàn)出代碼的邏輯意圖
  • 邏輯間解耦,一個(gè)stream中間處理邏輯,無(wú)需關(guān)注上游與下游的內(nèi)容,只需要按約定實(shí)現(xiàn)自身邏輯即可
  • 效率高:并行流場(chǎng)景效率會(huì)比迭代器逐個(gè)循環(huán)更高
  • 函數(shù)式接口,延遲執(zhí)行的特性,中間管道操作不管有多少步驟都不會(huì)立即執(zhí)行,只有遇到終止操作的時(shí)候才會(huì)開(kāi)始執(zhí)行,可以避免一些中間不必要的操作消耗

6.2 Stream的缺點(diǎn)

Stream也不全是優(yōu)點(diǎn),在有些方面也有其弊端:

  • 調(diào)試不便代碼調(diào)測(cè)debug不便
  • 需要時(shí)間適應(yīng)程序員從歷史寫(xiě)法切換到Stream時(shí),需要一定的學(xué)習(xí)、適應(yīng)時(shí)間

以上即為java1.8版本Stream處理集合等數(shù)據(jù)的方法介紹,篇幅較長(zhǎng),僅供參考。

http://www.risenshineclean.com/news/66271.html

相關(guān)文章:

  • 云龍徐州網(wǎng)站開(kāi)發(fā)做網(wǎng)站的軟件叫什么
  • 湖南網(wǎng)站建設(shè)mxtiaseo關(guān)鍵詞排名優(yōu)化制作
  • 男的女的做那個(gè)的視頻網(wǎng)站百度導(dǎo)航下載2022最新版
  • 如何制作自己的網(wǎng)站免費(fèi)福州seo網(wǎng)站管理
  • 百度搜索引擎優(yōu)化方案關(guān)鍵詞優(yōu)化排名公司
  • 網(wǎng)站建設(shè)公司有杭州網(wǎng)絡(luò)
  • 企業(yè)官網(wǎng)網(wǎng)站模板下載不了品牌推廣內(nèi)容
  • 如何查詢網(wǎng)站建立時(shí)間廣告公司經(jīng)營(yíng)范圍
  • 網(wǎng)站鏈群怎么做網(wǎng)絡(luò)自動(dòng)推廣軟件
  • 做網(wǎng)站的主營(yíng)業(yè)務(wù)搜外網(wǎng)
  • 鄭州app開(kāi)發(fā)網(wǎng)站建設(shè)營(yíng)銷(xiāo)推廣公司案例
  • 如何套模板做網(wǎng)站發(fā)帖推廣
  • 網(wǎng)站開(kāi)發(fā)估價(jià)鄭州seo外包
  • 電子商務(wù)公司名字seo營(yíng)銷(xiāo)外包
  • 個(gè)人做論壇網(wǎng)站有哪些重慶seo俱樂(lè)部聯(lián)系方式
  • dreamweaver做網(wǎng)站學(xué)習(xí)解析seo關(guān)鍵詞優(yōu)化怎么收費(fèi)
  • 鄭州網(wǎng)站制作方案微信小程序怎么做
  • 畢業(yè)設(shè)計(jì)網(wǎng)站開(kāi)發(fā)實(shí)施步驟湖南seo排名
  • 凡科 360免費(fèi)建站網(wǎng)站推廣策劃思路的內(nèi)容
  • 手機(jī)排行網(wǎng)站有哪些百度sem推廣
  • 西維科技做網(wǎng)站怎么樣seo優(yōu)化方式包括
  • 網(wǎng)站備案的是空間還是域名短視頻營(yíng)銷(xiāo)常用平臺(tái)有
  • 做整體衣柜宣傳海報(bào)的網(wǎng)站百度站長(zhǎng)平臺(tái)網(wǎng)站收錄
  • 用自己的電腦做服務(wù)器建網(wǎng)站seo優(yōu)化是利用規(guī)則提高排名
  • 佛山做網(wǎng)站百度app免費(fèi)下載
  • wordpress 1.0手機(jī)一鍵優(yōu)化
  • 制作一個(gè)網(wǎng)站難嗎google網(wǎng)站搜索
  • 我要看一集片做網(wǎng)站主流搜索引擎有哪些
  • 阿里云網(wǎng)站更換域名seo自然排名優(yōu)化
  • 企業(yè)手機(jī)網(wǎng)站建設(shè)方案千牛怎么做免費(fèi)推廣引流