java代碼大全及詳解「java流的概念」

Stream基本概念

  • Stream流是來自數據源的元素隊列並支持聚合操作: 元素: 是特定類型的對象,是數據源形成的一個隊列.Java中的Stream不會存儲元素,而是按需計算 數據源: Stream流數據的來源.可以是集合,數組,I/O Channel,產生器Generator等 聚合操作: 類似SQL語句的一系列操作,比如filter,map,reduce,match和sorted等
  • Stream不是集合元素,不是數據結構來保存數據,是一個有關數據算法和計算的流: 獲取一個數據源source => 數據轉換 => 執行操作獲取需要的結果 每次轉換後原來的Stream對象不變,返回一個新的Stream對象 這樣可以使得對Stream的操作鏈式排列,形成一個管道
  • Stream是對集合Collection對象功能的增強: Stream可以對集合對象進行便利高效的聚合操作和大批量的數據操作 集合類持有的元素都是存儲在內存中,數據量很大的集合類會佔用大量的內存 .Stream的元素是延遲計算的,只有在訪問時才會進入內存進行計算 集合類的迭代邏輯是調用者負責的,通常使用for循環 .Stream中的迭代是隱含在對Stream的各種操作當中
  • Stream操作的兩個基礎特徵: Pipelining: 中間操作都會返迴流本身.多個操作可以串成一個管道.這樣就可以對操作進行優化,比如延遲執行laziness和短路short-circuiting 內部迭代: 通常對集合的遍歷都是通過Iterator或者forEach操作,顯式地在集合外部進行迭代 .Stream提供了內部迭代的方式,通過訪問者模式Visitor實現
  • Stream的特點: 不存儲: 數據流Stream不是存儲元素的數據結構 數據流Stream將數據元素從源數據結構,數組,生成器函數和輸入輸出管道中傳遞到計算操作的管道中 功能性: 一個數據流Stream中的流操作都會產生一個結果,不會修改源數據流Stream中的元素 延遲計算: 許多流操作中的各種操作,比如過濾,映射,去重等,只有訪問時才會進行計算,這樣可以有更多的機會進行優化 無界性: 集合的大小是有界的,但是數據流Stream可以是無界的 短路操作等可以允許無限流計算在有限的時間內完成
  • 示例: 將流程轉化為Java代碼
+--------------------+       +------+   +------+   +---+   +-------+
| stream of elements +-----> |filter+-> |sorted+-> |map+-> |collect|
+--------------------+       +------+   +------+   +---+   +-------+
List<Integer> transactionsIds = widgets.stream()
	.filter(b -> b.getColor == RED)
	.sorted((x, y) -> x.getWeight() - y.getWeight())
	.mapToInt(Widget :: getWeight)
	.sum();

生成流

  • 集合接口有兩種方法來生成流:
    • stream(): 為集合創建串行流
    • parallelStream(): 為集合創建並行流 並行流可以充分發揮多核處理器的優勢 使用fork和join並行方式來拆分任務和加速處理過程
List<String> strings = Arrays.asList("I", "want", "to", "be", "", "great");
List<String> filter = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());

Stream的創建方式

數組

  • 通過數組來生成Stream流
String[] arrayStr = {"a", "b", "c"};
// 使用Stream中的靜態方法
Stream<String> stream = Stream.of(arrayStr);

集合

  • 通過集合來生成Stream流
List<String> list = Arrays.asList("a", "b", "c");
Stream<String> strem = list.stream();

Stream.generate()

  • 通過Stream.generate()方法來生成Stream流
Stream<Integer> generate = Stream.generate(() -> 1);

Stream.iterate()

  • 通過Stream.iterate()方法來生成Stream流
Stream<Integer> iterate = Stream.iterate(1, x -> x + 1);

API

  • 通過其餘相關的API進行創建
String str = "api";
IntStream stream = str.chars();

Stream常用方法

中間操作

  • 中間操作: 如果調用方法之後返回的結果是Stream對象的操作是一個中間操作

filter

  • filter方法用於通過設置的條件過濾出元素
/*
 * 過濾出空字符串的個數
 */
List<String> strings = Arrays.asList("I", "want", "to", "be", "", "great");
long count = Strings.stream().filter(string -> string.isEmpty()).count();

/*
 * 過濾出偶數
 */
 Arrays.asList(1, 2, 3, 4, 5).stream()
 	.filter(x -> x % 2 == 0)
 	// 2, 4
 	.forEach(System.out :: println)

/*
 * 求出所有的偶數和
 */
 int count = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9).stream()
 	.filter(x -> x % 2 == 0)
 	.mapToInt(x -> x)
 	.sum();
 System.out.println(count);

distinct

  • distinct方法通過元素的hashcode()和equals()去除重複元素
Arrays.asList(1, 2, 3, 3, 3, 4, 5).stream()
	.distinct()
	// 1, 2, 3, 4, 5
	.forEach(System.out :: println);

集合Set去重:

Arrays.asList(1, 2, 3, 4, 5).stream() .collect(Collectors.toSet()) // 1, 2, 3, 4, 5 .forEach(System.out :: println); 複製代碼

sorted

  • sorted方法根據自然排序返回Stream流
  • sorted(Comparator comparator)方法根據提供的Comparator進行排序
/*
 * 使用sorted方法實現min求最小值和max求最大值
 */
 List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
 // 數字的自然排序就是從小到大
 Optional<Integer> min = list.stream().sorted().findFirst();
 System.out.println(min :: get());

 Optional<Integer> max = list.stream.sorted((a, b) -> b - a).findFirst();
 System.out.println(max :: get());

/*
 * 按照字母順序a - z排序
 */
 Arrays.asList("java", "python", "c").stream().sorted().forEach(System.out :: println);
 
/*
 * 按照字母的長度進行排序
 */
 Arrays.asList("java", "python", "c").stream().sorted((a, b) -> a.length() - b.length()).forEach(System.out :: println);

limit

  • limit方法用來截取指定長度的Stream流
  • skip方法用來丟棄指定長度的流數據,可以與limit配合實現分頁
/*
 * 打印出集合中20 - 30的數據 
 */
 Stream.iterate(x -> x + 1).limit(50)
 	// 跳過前20個
 	.skip(20)
 	// 輸出20 - 30 
 	.forEach(System.out :: println);

map

  • map用來將Stream流中的元素按照指定的函數映射成一個新的元素的Stream流
  • flatMap用來將Stream流中的每個元素轉換成另一個流,然後將所有流連接成一個新的流
List<String> list = Arrays.asList("a, b, c", "1, 2, 3");
/*
 * 將字符串轉換為不帶逗號的元素
 */
 Stream<String> mapList = list.stream().map(s -> s.replace(",", ""));
 // abc 123
 mapList.forEach(System.out :: println);

 Stream<String> flatMapList = list.stream().flatMap(s -> {
 	// 將每一個元素轉換為流數據
 	String[] arrayStr = s.split(",");
 	Stream<String> stream = Arrays.stream(arrayStr);
 	return stream;
 });
 // a  b c 1 2 3
 flatMapList.forEach(System.out :: println);

peek

  • peek方法用來獲取Stream流中的每一個元素 類似於map, 但是map中接收的是一個Function表達式,有返回值 peek中接收的是一個Consumer表達式,沒有返回值
String str = "11, 22, 33, 44, 55";
// 11 22 33 44 55 165
System.out.println(Stream.of(str.split(",")).peek(System.out :: println).mapToInt(Integer :: valueOf).sum());

終止操作

循環-forEach

  • forEach用來循環遍歷每一個元素
// 創建一個實體類,包含有一個屬性為num屬性.並且有一個build()方法用於為num賦值
String str = "1, 2, 3"

/*
 * 輸出 num = 1, num = 2, num = 3
 */
Stream.of(str.split(",")).map(x -> new User(x)).forEach(System.out :: println);
Stream.of(str.split(",")).map(User :: new).forEach(System.out :: println);
Stream.of(str.split(",")).map(x -> User.build(x)).forEach(System.out :: println);
Stream.of(str.split(",")).map(User :: build).forEach(System.out :: println);

計算-min,max,count,sum

  • min: 返回Stream流元素中的最小值
  • max: 返回Stream流元素中的最大值
  • count: 返回Stream流元素中的總個數
  • sum:Stream流元素進行求和
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6);

// 求集合的最大值 - 6
System.out.println(list.stream().max((a, b) -> a - b).get());
// 求集合的最小值 - 1
System.out.println(list.stream().min((a, b) -> a - b).get());
// 統計元素的個數 - 6
System.out.println(list.stream().count());

// 元素求和
String str = "11, 22, 33, 44, 55";
System.out.println(Stream.of(str.split(",")).mapToInt(x -> Integer.valueOf(x)).sum());
System.out.println(Stream.of(str.split(",")).mapToInt(Integer :: valueOf).sum());
System.out.println(Stream.of(str.split(",")).map(x -> Integer.valueOf(x)).mapToInt(x -> x).sum());
System.out.println(Stream.of(str.split(",")).map(Integer :: valueOf).mapToInt(x -> x).sum());

匹配-anyMatch,allMatch,noneMatch,findFirst,findAny

  • anyMatch: 接收一個Predicate函數,只要Stream流中有一個元素滿足該斷言則返回true, 否則返回false
  • allMatch: 接收一個Predicate函數,當Stream流中每一個元素都滿足該斷言則返回true, 否則返回false
  • noneMatch: 接收一個Predicate函數,當Stream流中每一個元素都不符合該斷言則返回true, 否則返回false
  • findFirst: 返回Stream流中的第一個元素
  • findAny: 返回Stream流中的任意一個元素
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6);

// 如果集合的元素都大於等於0則返回true
System.out.println(list.stream().allMatch(x -> x >= 0));
// 如果集合中有大於5的元素,返回false
Systemm.out.println(list.stream().noneMatch(x -> x > 5));
// 如果集合中有大於3的元素則返回true
System.out.println(list.stream().anyMatch(x -> x > 3));
// 取第一個偶數
System.out.println(list.stream().filter(x -> x % 2 == 0).findFirst().get());
// 取任意一個偶數
System.out.println(list.stream().filter(x -> x % 2 == 0).findAny().get());                       

收集器-toArray,collect

  • collect: 接收一個Collector實例,將流中元素轉變為另外一種數據結構
  • Collector<T, A, R> 是一個接口,包含5個抽象方法: Supplier< A > supplier(): 創建一個結果容器 BiConsumer<A, T> accumulator(): 消費型接口. 第一個參數為容器A, 第二個參數為流中元素T BinaryOperator< A > combiner(): 函數接口. 該函數的作用是將各個子流程的運行結果,即accumulator函數操作後的容器A進行合併 Function<A, R> finisher(): 函數式接口. 參數為容器A, 返回類型為collect方法需要的結果類型R Set< Chracteristics > characteristics(): 返回一個不可變的Set集合,用來表明該Collector的特性
// 將對象值轉化為List
List<Integer> ageList = userList.stream().map(User :: getAge).collect(Collectors.toList());
// 將對象值轉化為Set
Set<Integer> ageSet = userList.stream().map(User :: getAge).collect(Collectors.toMap());
// 將對象值轉換為Map. 要求key的取值不能相同
Map<String, Integer> userMap = userList.stream().collect(Colletors.toMap(User :: getName, User :: getAge));
// 字符串分隔符連接
String joinName = userList.stream().map(User :: getName).collect(Collectors.join(",", "(", ")"))
// 聚合操作 - 計算對象總數
Long count = userList.stream().collect(Collectors.counting());
// 聚合操作 - 計算最大值
Integer maxAge = userList.stream().map(User :: getAge).collect(Collectors.maxBy(Integer :: compare)).get(); 
// 聚合操作 - 計算對象值總數
Integer sumAge = userList.stream().collect(Collectors.summingInt(User :: getAge));
// 聚合操作 - 計算對象值的平均數
Double averageAge = userList.stream().collet(Collectors.averagingDouble(User :: getAge));
// 根據Age分組
Map<Integer, List<User>> ageMap = userList.stream().collect(Collectors.groupingBy(User :: getAge));
// 根據條件分區: 一部分大於10, 一部分小於10
Map<Boolean, List<User>> partMap = userList.stream().collect(Collectors.partitionBy(x -> x.getAge() > 10));
// 規約
Integer value = userList.stream().map(User :: getAge).collect(Collectors.reducing(Integer :: sum)).get();

parallelStream

  • parallelStream是流並行處理程序的代替方法
List<String> strings = Arrays.asList("I", "want", "to", "be", "", "great");
long count = strings.parallelStream().filter(string -> string.isEmpty()).count();
  • 可以很容易的在順序運行和並行之間進行直接切換

Collectors

  • Collectors類實現很多歸約操作,比如將流轉換成集合和聚合元素
  • Collectors可用於返回列表和字符串
List<String> strings = Arrays.asList("I", "want", "to", "be", "", "great");
// 過濾掉空字符串
List<String> filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());
// 合併字符串
String mergedString = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.joining(","));

averagingDouble

/**
 * 返回一個Collector,生成應用於輸入元素double值函數的算術平均值
 * 結果可能會存在誤差
 *  
 * @param mapper 獲取需要計算算數平均值的值的映射器
 * @return Collector<T, ?, Double> 計算算術平均值的Collector
 */
 public static <T> Collector<T, ?, Double> averagingDouble(ToDoubleFunction<? super T> mapper) {
        /*
         * 在收集操作的數組中:
         * 	索引0 - 運行總和的高位
         * 	索引1 - 補償計算總和的低位
         * 	索引2 - 可見值的數量
         */
        return new CollectorImpl<>(
                () -> new double[4],
                (a, t) -> { double val = mapper.applyAsDouble(t); sumWithCompensation(a, val); a[2]++; a[3]+= val;},
                (a, b) -> { sumWithCompensation(a, b[0]); sumWithCompensation(a, b[1]); a[2] += b[2]; a[3] += b[3]; return a; },
                a -> (a[2] == 0) ? 0.0d : (computeFinalSum(a) / a[2]),
                CH_NOID);
}

averagingInt

/**
 * 返回一個Collector,生成應用於輸入元素int值函數的算術平均值
 *  
 * @param mapper 獲取需要計算算數平均值的值的映射器
 * @return Collector<T, ?, Double> 計算算術平均值的Collector
 */
 public static <T> Collector<T, ?, Double> averagingInt(ToIntFunction<? super T> mapper) {
        return new CollectorImpl<>(
                () -> new long[2],
                (a, t) -> { a[0] += mapper.applyAsInt(t); a[1]++; },
                (a, b) -> { a[0] += b[0]; a[1] += b[1]; return a; },
                a -> (a[1] == 0) ? 0.0d : (double) a[0] / a[1], CH_NOID);
}

averagingLong

/**
 * 返回一個Collector,生成應用於輸入元素long值函數的算術平均值
 *  
 * @param mapper 獲取需要計算算數平均值的值的映射器
 * @return Collector<T, ?, Double> 計算算術平均值的Collector
 */
 public static <T> Collector<T, ?, Double> averagingLong(ToLongFunction<? super T> mapper) {
        return new CollectorImpl<>(
                () -> new long[2],
                (a, t) -> { a[0] += mapper.applyAsLong(t); a[1]++; },
                (a, b) -> { a[0] += b[0]; a[1] += b[1]; return a; },
                a -> (a[1] == 0) ? 0.0d : (double) a[0] / a[1], CH_NOID);
}

collectingAndThen

/**
 * 調整Collector進行額外的轉換 
 *  
 * @param downstream 生成的下游收集器
 * @param finisher 額外執行的操作
 * @return Collector<T,A,RR> 進行額外操作的下游收集器
 */
public static<T,A,R,RR> Collector<T,A,RR> collectingAndThen(Collector<T,A,R> downstream, Function<R,RR> finisher) {
        Set<Collector.Characteristics> characteristics = downstream.characteristics();
        if (characteristics.contains(Collector.Characteristics.IDENTITY_FINISH)) {
            if (characteristics.size() == 1)
                characteristics = Collectors.CH_NOID;
            else {
                characteristics = EnumSet.copyOf(characteristics);
                characteristics.remove(Collector.Characteristics.IDENTITY_FINISH);
                characteristics = Collections.unmodifiableSet(characteristics);
            }
        }
        return new CollectorImpl<>(downstream.supplier(),
                                   downstream.accumulator(),
                                   downstream.combiner(),
                                   downstream.finisher().andThen(finisher),
                                   characteristics);
}

counting

/**
 * 返回Collector中指定類型元素的數量 
 *  
 * @return Collector<T, ?, Long> 指定輸入元素數量的收集器
 */
public static <T> Collector<T, ?, Long> counting() {
        return summingLong(e -> 1L);
}

groupingBy

/**
 * 返回一個對輸入的指定類型的元素執行分組操作的Collector
 * 	- 根據分組函數進行分組操作
 * 	- 並將結果以Map類型返回 
 *  
 * @param classifier 指定的分組函數
 * @return Collector<T, ?, Map<K, List<T>>> Map類型的返回結果
 */
public static <T, K> Collector<T, ?, Map<K, List<T>>> groupingBy(Function<? super T, ? extends K> classifier) {
        return groupingBy(classifier, toList());
}

/**
 * 返回一個對輸入的指定類型的元素執行級聯分組操作的Collector
 * 	- 根據分組函數進行分組操作
 * 	- 然後根據下游收集器對關聯key的value值執行指定的規約操作 
 *  
 * @param classifier 指定的分組函數
 * @param downstream 指定執行規約操作的下游收集器
 * @return Collector<T, ?, Map<K, D>> 實現了級聯分組操作的結果
 */
public static <T, K, A, D> Collector<T, ?, Map<K, D>> groupingBy(Function<? super T, ? extends K> classifier, Collector<? super T, A, D> downstream) {
        return groupingBy(classifier, HashMap::new, downstream);
}

/**
 * 返回一個對輸入的指定類型的元素執行級聯分組操作的,並以指定的Map實現方式保存結果返回的Collector
 * 	- 根據分組函數進行分組操作
 * 	- 再根據下游收集器對關聯key的value值執行指定的規約操作
 * 	- 然後將結果保存到指定方式實現的Map中 
 *  
 * @param classifier 指定的分組函數
 * @param mapFactory 指定的Map實現
 * @param downstream 指定執行規約操作的下游收集器
 * @return Collector<T, ?, M> 實現了級聯分組操作的Collector結果
 */
public static <T, K, D, A, M extends Map<K, D>> Collector<T, ?, M> groupingBy(Function<? super T, ? extends K> classifier, Supplier<M> mapFactory, Collector<? super T, A, D> downstream) {
        Supplier<A> downstreamSupplier = downstream.supplier();
        BiConsumer<A, ? super T> downstreamAccumulator = downstream.accumulator();
        BiConsumer<Map<K, A>, T> accumulator = (m, t) -> {
            K key = Objects.requireNonNull(classifier.apply(t), "element cannot be mapped to a null key");
            A container = m.computeIfAbsent(key, k -> downstreamSupplier.get());
            downstreamAccumulator.accept(container, t);
        };
        BinaryOperator<Map<K, A>> merger = Collectors.<K, A, Map<K, A>>mapMerger(downstream.combiner());
        @SuppressWarnings("unchecked")
        Supplier<Map<K, A>> mangledFactory = (Supplier<Map<K, A>>) mapFactory;

        if (downstream.characteristics().contains(Collector.Characteristics.IDENTITY_FINISH)) {
            return new CollectorImpl<>(mangledFactory, accumulator, merger, CH_ID);
        }
        else {
            @SuppressWarnings("unchecked")
            Function<A, A> downstreamFinisher = (Function<A, A>) downstream.finisher();
            Function<Map<K, A>, M> finisher = intermediate -> {
                intermediate.replaceAll((k, v) -> downstreamFinisher.apply(v));
                @SuppressWarnings("unchecked")
                M castResult = (M) intermediate;
                return castResult;
            };
            return new CollectorImpl<>(mangledFactory, accumulator, merger, finisher, CH_NOID);
        }
}

groupingByConcurrent

/**
 * 返回一個對輸入的指定類型的元素執行分組操作的並行Collector
 * 	- 根據分組函數進行分組操作
 * 	- 並將結果以Map類型返回 
 *  
 * @param classifier 指定的分組函數
 * @return Collector<T, ?, ConcurrentMap<K, List<T>>> 實現分組操作的並發無序的Collector
 */
public static <T, K> Collector<T, ?, ConcurrentMap<K, List<T>>> groupingByConcurrent(Function<? super T, ? extends K> classifier) {
        return groupingByConcurrent(classifier, ConcurrentHashMap::new, toList());
}

/**
 * 返回一個對輸入的指定類型的元素執行級聯分組操作的並行Collector
 * 	- 根據分組函數進行分組操作
 * 	- 然後根據下游收集器對關聯key的指定value值執行指定的規約操作 
 *  
 * @param classifier 指定的分組函數
 * @downstream 指定執行規約操作的下游收集器
 * @return Collector<T, ?, ConcurrentMap<K, D>> 實現分組操作的並發無序的Collector
 */
public static <T, K, A, D> Collector<T, ?, ConcurrentMap<K, D>> groupingByConcurrent(Function<? super T, ? extends K> classifier, Collector<? super T, A, D> downstream) {
        return groupingByConcurrent(classifier, ConcurrentHashMap::new, downstream);
}

/**
 * 返回一個對輸入的指定類型的元素執行級聯分組操作的並行Collector
 * 	- 根據分組函數進行分組操作
 * 	- 再根據下游收集器對關聯key的指定value值執行指定的規約操作 
 *  - 然後將結果保存到指定方式實現的Map中
 *  
 * @param classifier 指定的分組函數
 * @param mapFactory 指定的Map實現
 * @downstream 指定執行規約操作的下游收集器
 * @return Collector<T, ?, ConcurrentMap<K, D>> 實現分組操作的並發無序的Collector
 */
public static <T, K, A, D, M extends ConcurrentMap<K, D>> Collector<T, ?, M> groupingByConcurrent(Function<? super T, ? extends K> classifier, Supplier<M> mapFactory, Collector<? super T, A, D> downstream) {
        Supplier<A> downstreamSupplier = downstream.supplier();
        BiConsumer<A, ? super T> downstreamAccumulator = downstream.accumulator();
        BinaryOperator<ConcurrentMap<K, A>> merger = Collectors.<K, A, ConcurrentMap<K, A>>mapMerger(downstream.combiner());
        @SuppressWarnings("unchecked")
        Supplier<ConcurrentMap<K, A>> mangledFactory = (Supplier<ConcurrentMap<K, A>>) mapFactory;
        BiConsumer<ConcurrentMap<K, A>, T> accumulator;
        if (downstream.characteristics().contains(Collector.Characteristics.CONCURRENT)) {
            accumulator = (m, t) -> {
                K key = Objects.requireNonNull(classifier.apply(t), "element cannot be mapped to a null key");
                A resultContainer = m.computeIfAbsent(key, k -> downstreamSupplier.get());
                downstreamAccumulator.accept(resultContainer, t);
            };
        }
        else {
            accumulator = (m, t) -> {
                K key = Objects.requireNonNull(classifier.apply(t), "element cannot be mapped to a null key");
                A resultContainer = m.computeIfAbsent(key, k -> downstreamSupplier.get());
                synchronized (resultContainer) {
                    downstreamAccumulator.accept(resultContainer, t);
                }
            };
        }

        if (downstream.characteristics().contains(Collector.Characteristics.IDENTITY_FINISH)) {
            return new CollectorImpl<>(mangledFactory, accumulator, merger, CH_CONCURRENT_ID);
        }
        else {
            @SuppressWarnings("unchecked")
            Function<A, A> downstreamFinisher = (Function<A, A>) downstream.finisher();
            Function<ConcurrentMap<K, A>, M> finisher = intermediate -> {
                intermediate.replaceAll((k, v) -> downstreamFinisher.apply(v));
                @SuppressWarnings("unchecked")
                M castResult = (M) intermediate;
                return castResult;
            };
            return new CollectorImpl<>(mangledFactory, accumulator, merger, finisher, CH_CONCURRENT_NOID);
        }
}
Java Stream流中的實用操作,各種流操作的參考示例分析

joining

/**
 * 返回一個根據接收元素的順序將元素連接成一個String字符串的Collector
 *  
 * @return Collector<CharSequence, ?, String> 根據接收元素的順序將元素連接成一個字符串的Collector
 */
public static Collector<CharSequence, ?, String> joining() {
        return new CollectorImpl<CharSequence, StringBuilder, String>(
                StringBuilder::new, StringBuilder::append,
                (r1, r2) -> { r1.append(r2); return r1; },
                StringBuilder::toString, CH_NOID);
}

/**
 * 返回一個根據接收元素的順序將元素連接成一個String字符串並以指定的分隔符分割的Collector
 *  
 * @param delimiter 用於每個元素之間的分割符
 * @return Collector<CharSequence, ?, String> 根據接收元素的順序將元素連接成一個字符串並以指定分割符分割的Collector
 */
public static Collector<CharSequence, ?, String> joining(CharSequence delimiter) {
        return joining(delimiter, "", "");
}

/**
 * 返回一個根據接收元素的順序將元素連接成一個String字符串並以指定的分隔符分割和指定前綴和後綴的Collector
 *  
 * @param delimiter 用於每個元素之間的分割符
 * @param prefix 指定的前綴
 * @param suffix 指定的後綴 
 * @return Collector<CharSequence, ?, String> 根據接收元素的順序將元素連接成一個字符串並以指定分割符分割和指定的前綴和後綴的Collector
 */
public static Collector<CharSequence, ?, String> joining(CharSequence delimiter, CharSequence prefix, CharSequence suffix) {
        return new CollectorImpl<>(
                () -> new StringJoiner(delimiter, prefix, suffix),
                StringJoiner::add, StringJoiner::merge,
                StringJoiner::toString, CH_NOID);
}

mapping

/**
 * 在累積元素之前應用映射函數將類型為U的收集器調整為類型為T的收集器
 * mapping操作對多級規約操作最有用
 *  
 * @param mapper 映射函數
 * @param downstream 下游收集器
 * @return Collector<T, ?, R> 執行映射函數操作後的收集器
 */
public static <T, U, A, R> Collector<T, ?, R> mapping(Function<? super T, ? extends U> mapper, Collector<? super U, A, R> downstream) {
        BiConsumer<A, ? super U> downstreamAccumulator = downstream.accumulator();
        return new CollectorImpl<>(downstream.supplier(),
                                   (r, t) -> downstreamAccumulator.accept(r, mapper.apply(t)),
                                   downstream.combiner(), downstream.finisher(),
                                   downstream.characteristics());
}

maxBy

/**
 * 返回一個根據給定的比較器Comparator生成最大元素的Collector,使用Optional<T>描述
 *  
 * @param comparator 指定的比較器
 * @return Collector<T, ?, Optional<T>> 根據比較器生成最大元素的Collector
 */
public static <T> Collector<T, ?, Optional<T>> maxBy(Comparator<? super T> comparator) {
        return reducing(BinaryOperator.maxBy(comparator));
}

minBy

/**
 * 返回一個根據給定的比較器Comparator生成最小元素的Collector,使用Optional<T>描述
 *  
 * @param comparator 指定的比較器
 * @return Collector<T, ?, Optional<T>> 根據比較器生成最小元素的Collector
 */
public static <T> Collector<T, ?, Optional<T>> (Comparator<? super T> comparator) {
        return reducing(BinaryOperator.minBy(comparator));
}

partitioningBy

/**
 * 返回一個根據指定規則分類的Collector,結果保存到Map<Boolean, List>中
 *  
 * @param predicate 指定的分類規則
 * @return Collector<T, ?, Map<Boolean, List<T>>> 按照指定規則進行分類,並將結果保存到Map<Boolean, List>的收集器
 */
public static <T> Collector<T, ?, Map<Boolean, List<T>>> partitioningBy(Predicate<? super T> predicate) {
        return partitioningBy(predicate, toList());
}

/**
 * 返回一個根據指定規則分類的Collector,並將結果值按照下游收集器執行規約操作,然後將規約後的結果保存到Map<Boolean, D>中
 * 
 * @param predicate 指定的分類規則
 * @param downstream 指定的執行規約操作的下游收集器
 * @return Collector<T, ?, Map<Boolean, D>> 按照指定規則進行分類,並將結果值按照下游收集器執行規約操作,然後將規約後的結果保存到Map<Boolean, D>的收集器
 */
public static <T, D, A> Collector<T, ?, Map<Boolean, D>> partitioningBy(Predicate<? super T> predicate, Collector<? super T, A, D> downstream) {
        BiConsumer<A, ? super T> downstreamAccumulator = downstream.accumulator();
        BiConsumer<Partition<A>, T> accumulator = (result, t) ->
                downstreamAccumulator.accept(predicate.test(t) ? result.forTrue : result.forFalse, t);
        BinaryOperator<A> op = downstream.combiner();
        BinaryOperator<Partition<A>> merger = (left, right) ->
                new Partition<>(op.apply(left.forTrue, right.forTrue),
                                op.apply(left.forFalse, right.forFalse));
        Supplier<Partition<A>> supplier = () ->
                new Partition<>(downstream.supplier().get(),
                                downstream.supplier().get());
        if (downstream.characteristics().contains(Collector.Characteristics.IDENTITY_FINISH)) {
            return new CollectorImpl<>(supplier, accumulator, merger, CH_ID);
        }
        else {
            Function<Partition<A>, Map<Boolean, D>> finisher = par ->
                    new Partition<>(downstream.finisher().apply(par.forTrue),
                                    downstream.finisher().apply(par.forFalse));
            return new CollectorImpl<>(supplier, accumulator, merger, finisher, CH_NOID);
        }
}

reducing

/**
 * 返回一個按照指定的規約操作獲得結果的Colletor.結果以Optional<T>描述
 *  
 * @param op 指定的規約操作
 * @return Collector<T, ?, Optional<T>> 按照指定的規約操作執行的結果
 */
public static <T> Collector<T, ?, Optional<T>> reducing(BinaryOperator<T> op) {
        class OptionalBox implements Consumer<T> {
            T value = null;
            boolean present = false;

            @Override
            public void accept(T t) {
                if (present) {
                    value = op.apply(value, t);
                }
                else {
                    value = t;
                    present = true;
                }
            }
        }

        return new CollectorImpl<T, OptionalBox, Optional<T>>(
                OptionalBox::new, OptionalBox::accept,
                (a, b) -> { if (b.present) a.accept(b.value); return a; },
                a -> Optional.ofNullable(a.value), CH_NOID);
}

/**
 * 返回一個使用指定標識,按照指定的規約操作獲得結果的Colletor
 *  
 * @param identity 指定的標識,也是結果為空時的返回值
 * @param op 指定的規約操作
 * @return Collector<T, ?, T> 按照指定的規約操作執行的結果,當結果為空時返回指定的標識identity
 */
public static <T> Collector<T, ?, T> reducing(T identity, BinaryOperator<T> op) {
        return new CollectorImpl<>(
                boxSupplier(identity),
                (a, t) -> { a[0] = op.apply(a[0], t); },
                (a, b) -> { a[0] = op.apply(a[0], b[0]); return a; },
                a -> a[0],
                CH_NOID);
}

/**
 * 返回一個使用指定標識,按照指定的映射操作和規約操作獲得結果的Colletor
 *  
 * @param identity 指定的標識,也是結果為空時的返回值
 * @param mapper 指定的映射操作
 * @param op 指定的規約操作
 * @return Collector<T, ?, Optional<T>> 按照指定的映射操作和規約操作執行的結果,當結果為空時返回指定的標識identity
 */
public static <T, U> Collector<T, ?, U> reducing(U identity, Function<? super T, ? extends U> mapper, BinaryOperator<U> op) {
        return new CollectorImpl<>(
                boxSupplier(identity),
                (a, t) -> { a[0] = op.apply(a[0], mapper.apply(t)); },
                (a, b) -> { a[0] = op.apply(a[0], b[0]); return a; },
                a -> a[0], CH_NOID);
}

summarizingDouble

/**
 * 返回一個使用double類型映射每一個輸入元素並返回結果值匯總信息的Collector
 *  
 * @param mapper 指定的映射操作
 * @return Collector<T, ?, DoubleSummaryStatistics> 匯總信息的規約操作
 */
public static <T> Collector<T, ?, DoubleSummaryStatistics> summarizingDouble(ToDoubleFunction<? super T> mapper) {
        return new CollectorImpl<T, DoubleSummaryStatistics, DoubleSummaryStatistics>(
                DoubleSummaryStatistics::new,
                (r, t) -> r.accept(mapper.applyAsDouble(t)),
                (l, r) -> { l.combine(r); return l; }, CH_ID);
}

summarizingInt

/**
 * 返回一個使用int類型映射每一個輸入元素並返回結果值匯總信息的Collector
 *  
 * @param mapper 指定的映射操作
 * @return Collector<T, ?, IntSummaryStatistics> 匯總信息的規約操作
 */
public static <T> Collector<T, ?, IntSummaryStatistics> summarizingInt(ToIntFunction<? super T> mapper) {
        return new CollectorImpl<T, IntSummaryStatistics, IntSummaryStatistics>(
                IntSummaryStatistics::new,
                (r, t) -> r.accept(mapper.applyAsInt(t)),
                (l, r) -> { l.combine(r); return l; }, CH_ID);
}

summarizingLong

/**
 * 返回一個使用long類型映射每一個輸入元素並返回結果值匯總信息的Collector
 *  
 * @param mapper 指定的映射操作
 * @return Collector<T, ?, IntSummaryStatistics> 匯總信息的規約操作
 */
public static <T> Collector<T, ?, LongSummaryStatistics> summarizingLong(ToLongFunction<? super T> mapper) {
        return new CollectorImpl<T, LongSummaryStatistics, LongSummaryStatistics>(
                LongSummaryStatistics::new,
                (r, t) -> r.accept(mapper.applyAsLong(t)),
                (l, r) -> { l.combine(r); return l; }, CH_ID);
}
Java Stream流中的實用操作,各種流操作的參考示例分析

summingDouble

/**
 * 返回一個使用double類型映射每一個輸入元素並返回元素之和的Collector
 * 如果不存在元素則返回0
 *  
 * @param mapper 指定的映射操作
 * @return Collector<T, ?, Double> 執行元素求和規約操作的Collector
 */
public static <T> Collector<T, ?, Double> summingDouble(ToDoubleFunction<? super T> mapper) {
        /*
         * 在為收集操作分配的數組中:
         * 	索引0 - 運行和的高位
         * 	索引1 - 補償計算的和的低階位求和
         * 	索引2 - 當存在無窮大結果和時正確的符號
         */
        return new CollectorImpl<>(
                () -> new double[3],
                (a, t) -> { double val = mapper.applyAsDouble(t);
                            sumWithCompensation(a, val);
                            a[2] += val;},
                (a, b) -> { sumWithCompensation(a, b[0]);
                            a[2] += b[2];
                            return sumWithCompensation(a, b[1]); },
                a -> computeFinalSum(a),
                CH_NOID);
}

summingInt

/**
 * 返回一個使用int類型映射每一個輸入元素並返回元素之和的Collector
 * 如果不存在元素則返回0
 *  
 * @param mapper 指定的映射操作
 * @return Collector<T, ?, Integer> 執行元素求和規約操作的Collector
 */
public static <T> Collector<T, ?, Integer> summingInt(ToIntFunction<? super T> mapper) {
        return new CollectorImpl<>(
                () -> new int[1],
                (a, t) -> { a[0] += mapper.applyAsInt(t); },
                (a, b) -> { a[0] += b[0]; return a; },
                a -> a[0], CH_NOID);
}

summingLong

/**
 * 返回一個使用long類型映射每一個輸入元素並返回元素之和的Collector
 * 如果不存在元素則返回0
 *  
 * @param mapper 指定的映射操作
 * @return Collector<T, ?, Integer> 執行元素求和規約操作的Collector
 */
public static <T> Collector<T, ?, Long> summingLong(ToLongFunction<? super T> mapper) {
        return new CollectorImpl<>(
                () -> new long[1],
                (a, t) -> { a[0] += mapper.applyAsLong(t); },
                (a, b) -> { a[0] += b[0]; return a; },
                a -> a[0], CH_NOID);
}

toCollection

/**
 * 返回一個將接收的元素按照接收順序放入生成的集合的Collector
 *  
 * @param collectionFactory 指定的生成的集合
 * @return Collector<T, ?, C> 將接收的元素按照接收順序生成集合的Collector
 */
public static <T, C extends Collection<T>> Collector<T, ?, C> toCollection(Supplier<C> collectionFactory) {
        return new CollectorImpl<>(collectionFactory, Collection<T>::add,
                                   (r1, r2) -> { r1.addAll(r2); return r1; },
                                   CH_ID);
}

toConcurrentMap

/**
 * 返回一個將接收的元素放入並發的Map中的並發Collector,其中Map的key和value按照指定的映射函數生成
 *  
 * @param keyMapper 鍵的映射器
 * @param valueMapper 值的映射器
 * @return Collector<T, ?, ConcurrentMap<K,U>> 將接收的元素按照放入並發的Map中的並發無序Collector
 */
public static <T, K, U> Collector<T, ?, ConcurrentMap<K,U>> toConcurrentMap(Function<? super T, ? extends K> keyMapper, Function<? super T, ? extends U> valueMapper) {
        return new CollectorImpl<>(ConcurrentHashMap::new,
                                   uniqKeysMapAccumulator(keyMapper, valueMapper),
                                   uniqKeysMapMerger(),
                                   CH_CONCURRENT_ID);
}

/**
 * 返回一個將接收的元素放入並發的Map中的並發Collector,其中Map的key和value按照指定的映射函數生成
 * 如果存在重複的鍵值,則會應用指定的合併函數
 *  
 * @param keyMapper 鍵的映射器
 * @param valueMapper 值的映射器
 * @param mergeFunction 指定的合併函數
 * @return Collector<T, ?, ConcurrentMap<K,U>> 將接收的元素按照放入並發的Map中的並發Collector
 */
public static <T, K, U> Collector<T, ?, ConcurrentMap<K,U>> toConcurrentMap(Function<? super T, ? extends K> keyMapper, Function<? super T, ? extends U> valueMapper, BinaryOperator<U> mergeFunction) {
        return toConcurrentMap(keyMapper, valueMapper, mergeFunction, ConcurrentHashMap::new);
}

/**
 * 返回一個將接收的元素放入指定方式實現的並發Map中的並發Collector,其中Map的key和value按照指定的映射函數生成
 * 如果存在重複的鍵值,則會應用指定的合併函數
 *  
 * @param keyMapper 鍵的映射器
 * @param valueMapper 值的映射器
 * @param mergeFunction 指定的合併函數
 * @param mapFactory 指定的Map實現方式
 * @return Collector<T, ?, M> 將接收的元素按照放入指定方式實現的並發Map中的並發Collector
 */
public static <T, K, U, M extends ConcurrentMap<K, U>> Collector<T, ?, M> toConcurrentMap(Function<? super T, ? extends K> keyMapper, Function<? super T, ? extends U> valueMapper,BinaryOperator<U> mergeFunction,Supplier<M> mapFactory) {
        BiConsumer<M, T> accumulator
                = (map, element) -> map.merge(keyMapper.apply(element),
                                              valueMapper.apply(element), mergeFunction);
        return new CollectorImpl<>(mapFactory, accumulator, mapMerger(mergeFunction), CH_CONCURRENT_ID);
}

toList

/**
 * 返回一個將接收的元素按照接收的順序放入List中的收集器Collector
 *  
 * @return Collector<T, ?, List<T>> 包含輸入元素的List類型的收集器Collector
 */
public static <T> Collector<T, ?, List<T>> toList() {
        return new CollectorImpl<>((Supplier<List<T>>) ArrayList::new, List::add,
                                   (left, right) -> { left.addAll(right); return left; },
                                   CH_ID);
}

toMap

/**
 * 返回一個將接收的元素放入Map中的Collector,其中Map的key和value按照指定的映射函數生成
 *  
 * @param keyMapper 鍵映射函數
 * @param valueMapper 值映射函數
 * @return Collector<T, ?, Map<K,U>> 將接收的元素放入Map中的Collector
 */
public static <T, K, U> Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper, Function<? super T, ? extends U> valueMapper) {
        return new CollectorImpl<>(HashMap::new,
                                   uniqKeysMapAccumulator(keyMapper, valueMapper),
                                   uniqKeysMapMerger(),
                                   CH_ID);
}

/**
 * 返回一個將接收的元素放入Map中的Collector,其中Map的key和value按照指定的映射函數生成
 * 如鍵重複,則使用指定的合併函數合併
 *  
 * @param keyMapper 鍵映射函數
 * @param valueMapper 值映射函數
 * @param mergeFunction 指定的合併函數
 * @return Collector<T, ?, Map<K,U>> 將接收的元素放入Map中的Collector
 */
public static <T, K, U> Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper, Function<? super T, ? extends U> valueMapper, BinaryOperator<U> mergeFunction) {
        return toMap(keyMapper, valueMapper, mergeFunction, HashMap::new);
}

/**
 * 返回一個將接收的元素放入指定實現方式的Map中的Collector,其中Map的key和value按照指定的映射函數生成
 * 如鍵重複,則使用指定的合併函數合併
 *  
 * @param keyMapper 鍵映射函數
 * @param valueMapper 值映射函數
 * @param mergeFunction 指定的合併函數
 * @param mapFactory 指定的Map實現方式
 * @return Collector<T, ?, Map<K,U>> 將接收的元素放入指定實現方式的Map中的Collector
 */
public static <T, K, U, M extends Map<K, U>> <T, ?, M> toMap(Function<? super T, ? extends K> keyMapper, Function<? super T, ? extends U> valueMapper, BinaryOperator<U> mergeFunction, <M> mapFactory) {
        BiConsumer<M, T> accumulator
                = (map, element) -> map.merge(keyMapper.apply(element),
                                              valueMapper.apply(element), mergeFunction);
        return new CollectorImpl<>(mapFactory, accumulator, mapMerger(mergeFunction), CH_ID);
}

toSet

/**
 * 返回一個將接收的元素放入Set中的收集器Collector
 *  
 * @return Collector<T, ?, Set<T>> 將接收的元素放入Set中的Collector
 */
public static <T> Collector<T, ?, Set<T>> toSet() {
       return new CollectorImpl<>((Supplier<Set<T>>) HashSet::new, Set::add,
                                   (left, right) -> {
                                       if (left.size() < right.size()) {
                                           right.addAll(left); return right;
                                       } else {
                                           left.addAll(right); return left;
                                       }
                                   },
                                   CH_UNORDERED_ID);
}

統計

  • 產生統計結果的收集器,主要用於int,double,long等類型
List<Integer> numbers = Arrays.asList(3, 2, 3, 7, 3, 5);
IntSummaryStatistics stats = numbers.stream().mapToInt((x) -> x).summaryStatistics();

System.out.println("列表中最大的數:" + stats.getMax());
System.out.println("列表中最小的數:" + stats.getMin());
System.out.println("所有數之和:" + stats.getSum());
System.out.println("平均數:" + stats.getAverage());
Java Stream流中的實用操作,各種流操作的參考示例分析

原創文章,作者:投稿專員,如若轉載,請註明出處:https://www.506064.com/zh-hk/n/269318.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
投稿專員的頭像投稿專員
上一篇 2024-12-16 13:15
下一篇 2024-12-16 13:15

相關推薦

發表回復

登錄後才能評論