<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
Java 流(Stream)處理操作完成之後,我們可以收集這個流中的元素,使之匯聚成一個最終結果。這個結果可以是一個物件,也可以是一個集合,甚至可以是一個基本型別資料。
以記錄 Record 為例:
@Data @NoArgsConstructor @AllArgsConstructor public static class Record { private String col1; private String col2; private int col3; }
記錄 Record 包含三個屬性:列1(col1)、列2(col2)和 列3(col3)。
建立四個記錄範例:
Record r1 = new Record("a", "1", 1); Record r2 = new Record("a", "2", 2); Record r3 = new Record("b", "3", 3); Record r4 = new Record("c", "4", 4);
新增到列表:
List<Record> records = new ArrayList<>(); records.add(r1); records.add(r2); records.add(r3); records.add(r4);
List<String> col1List = records.stream() .map(Record::getCol1) .collect(Collectors.toList()); log.info("col1List: {}", Json.toJson(col1List));
輸出結果:
col1List: ["a","a","b","c"]
Set<String> col1Set = records.stream() .map(Record::getCol1) .collect(Collectors.toSet()); log.info("col1Set: {}", Json.toJson(col1Set));
輸出結果:
col1Set: ["a","b","c"]
Map<String, Integer> col2Map = records.stream() .collect(Collectors.toMap(Record::getCol2, Record::getCol3)); log.info("col2Map: {}", Json.toJson(col2Map));
輸出結果:
col2Map: {"1":1,"2":2,"3":3,"4":4}
記錄的 列2 不能有重複值,否則會丟擲 Duplicate key 異常。
Record max = records.stream() .collect(Collectors.maxBy(Comparator.comparing(Record::getCol3))) .orElse(null); log.info("max: {}", Json.toJson(max));
輸出結果:
max: {"col1":"c","col2":"4","col3":4}
int sum = records.stream() .collect(Collectors.summingInt(Record::getCol3)); log.info("sum: {}", sum);
輸出結果:
sum: 10
流的收集需要通過 Stream.collect() 方法完成,方法的引數是一個 Collector(收集器) ;收集結果時,需要根據收集結果的目標型別,傳遞特定的收集器範例,如上:
Collectors.toList()
Collectors.toSet()
Collectors.toMap()
Collectors.maxBy()
Collectors.summingInt()
Collectors(java.util.stream.Collectors) 是一個工具類,內建若干收集器,我們可以通過呼叫不同的方法快速獲取相應的收集器範例。
收集器(java.util.stream.Collector)本質是一個 介面 ,包含以下五個方法:
Supplier supplier()
BiConsumer<A, T> accumulator()
BinaryOperator combiner()
Function<A, R> finisher()
Set characteristics()
以 Collectors.toList() 為例演示收集器的工作過程。
supplier() 方法會返回一個 Supplier 範例,呼叫該範例的 get() 方法,會建立一箇中間結果容器。
@Override public Supplier<List<String>> supplier() { return new Supplier<List<String>>() { @Override public List<String> get() { List<String> container = new ArrayList<>(); return container; } }; }
考慮到收集的元素型別 String,這裡的中間結果容器型別為 ArrayList 。
根據收集過程的需要,中間結果容器可以是任意的資料結構。
accumulator() 方法會返回一個 BiConsumer 範例,它有一個 accept() 方法,
引數1:中間結果 引數2:流中遍歷到的某個元素
遍歷過程是 Java 自動完成的,每遍歷一個元素,會自動呼叫 BiConsumer.accept 方法。我們只需要在方法中實現元素的處理過程,然後把元素的處理結果新增到中間結果中就可以了。
@Override public BiConsumer<List<String>, String> accumulator() { return new BiConsumer<List<String>, String>() { @Override public void accept(List<String> container, String col) { container.add(col); } }; }
這個範例中,流中的元素不需要任何處理,直接新增至中間結果即可。
finisher() 方法會返回一個 Fuction 範例,它有一個 apply() 方法,
引數:中間結果 返回:最終結果
遍歷過程結束之後,Java 會自動呼叫 Function.apply() 方法,將中間結果轉換成最終結果。
@Override public Function<List<String>, List<String>> finisher() { return new Function<List<String>, List<String>>() { @Override public List<String> apply(List<String> container) { return container; } }; }
這個範例中,中間結果就是最終結果,不需要任何處理,直接返回中間結果即可。
流中的元素可以被並行處理,這樣的流稱為並行流。並行流相當於把一個大流切分成多個小流,內部使用多執行緒,並行處理這些小流。每一個小流遍歷完成之後,都會產生一個小的中間結果,需要將這些小的中間結果合併成一個大的中間結果。
假設有兩個小流,收集開始時,會建立兩個中間結果:
中間結果也是通過 Supplier.get() 方法建立的。
並行遍歷兩個小流,將各自流的處理結果新增到各自的中間結果中:
combiner() 方法會返回一個 BinaryOperator 範例,它有一個 apply() 方法:
引數1:中間結果1 引數2:中間結果2 返回:中間結果
Java 會在合適的時機自動呼叫 BinaryOperator.apply() 方法,將小的中間結果合併成大的中間結果。
@Override public BinaryOperator<List<String>> combiner() { return new BinaryOperator<List<String>>() { @Override public List<String> apply(List<String> container1, List<String> container2) { container1.addAll(container2); return container1; } }; }
characteristics() 會返回一個 Characteristics(列舉)集合範例,用於設定收集器的特性,支援以下三個值:
CONCURRENT
收集器支援並行使用
UNORDERED
收集器不保證元素順序
IDENTITY_FINISH
收集器中間結果可直接轉換成最終結果
Java 可以根據這些特性值,保證收集器正確地、有效率地執行。
Collector<String, List<String>, List<String>> collector = new Collector<String, List<String>, List<String>>() { @Override public Supplier<List<String>> supplier() { return new Supplier<List<String>>() { @Override public List<String> get() { List<String> container = new ArrayList<>(); return container; } }; } @Override public BiConsumer<List<String>, String> accumulator() { return new BiConsumer<List<String>, String>() { @Override public void accept(List<String> container, String col) { container.add(col); } }; } @Override public BinaryOperator<List<String>> combiner() { return new BinaryOperator<List<String>>() { @Override public List<String> apply(List<String> container1, List<String> container2) { container1.addAll(container2); return container1; } }; } @Override public Function<List<String>, List<String>> finisher() { return new Function<List<String>, List<String>>() { @Override public List<String> apply(List<String> container) { return container; } }; } @Override public Set<Characteristics> characteristics() { return new HashSet<>(); } }; col1List = records.stream() .map(Record::getCol1) .collect(collector); log.info("col1List: {}", Json.toJson(col1List));
到此這篇關於Java 流處理之收集器的文章就介紹到這了,更多相關Java 收集器內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45