本篇參見【Modern Java in Action】 2nd-edition
Stream 提供了如上表的 operation,要怎麼使用呢? 直接看例子吧~
假設一個場景,客戶進行證券交易,這裡記錄下客戶在某年交易的金額及客戶的基本資料 (姓名、年齡、居住城市),資料如下:
- Customer steven = new Customer("Steven", 50, "New Taipei");
- Customer shelley = new Customer("Shelley", 48, "Taichung");
- Customer mark = new Customer("Mark", 53, "Taipei");
- Customer kfc = new Customer("KFC", 38, "Taipei");
- Customer clair = new Customer("Clair", 26, "Yunlin");
- List<Trade> trades = Arrays.asList(
- new Trade(steven, 2018, 350000),
- new Trade(shelley, 2018, 535000),
- new Trade(mark, 2018, 1005000),
- new Trade(kfc, 2018, 810000),
- new Trade(clair, 2018, 559000),
- new Trade(steven, 2019, 67000),
- new Trade(mark, 2019, 890100),
- new Trade(clair, 2019, 90900)
- );
- 2018年的所有交易,按交易額排序:
- trades.stream()
- .filter(t -> t.getYear() == 2018)
- .sorted(comparing(Trade::getAmount))
- .forEach(t -> log.info(t.toString()));
- 所有客戶分布於那些城市?
- trades.stream()
- .map(t -> t.getCstm().getCity())
- .distinct()
- .forEach(t -> log.info(t.toString()));
- 列出住台北市的客戶,並以年齡排序:
- trades.stream()
- .filter(t -> t.getCstm().getCity().equals("Taipei"))
- .map(t -> t.getCstm())
- .distinct()
- .sorted(comparing(Customer::getAge))
- .forEach(t -> log.info(t.toString()));
- 住台北市的客戶的交易量總和?
- int total = trades.stream()
- .filter(t -> t.getCstm().getCity().equals("Taipei"))
- .map(t -> t.getAmount())
- .reduce(0, Integer::sum);
- log.info("total = " + total);
- int total = trades.stream()
- .filter(t -> t.getCstm().getCity().equals("Taipei"))
- .mapToInt(Trade::getAmount)
- .sum();
- 歷年來所有交易中,最大的一筆交易的交易量?
- Optional<Integer> optTotal = trades.stream()
- .map(t -> t.getAmount())
- .reduce(Integer::max);
- if (optTotal.isPresent()) {
- int total = optTotal.get();
- log.info("total = " + total);
- }
- else {
- log.info("data not found");
- }
得到如下結果,filter 過濾出 2018 年的交易 (Trade),以 amount 排序,從結果可以看到這些交易是那個客戶交易的。
Trade(cTrade(cstm=Customer(name=Steven, age=50, city=New Taipei), year=2018, amount=350000)
Trade(cstm=Customer(name=Shelley, age=48, city=Taichung), year=2018, amount=535000)
Trade(cstm=Customer(name=Clair, age=26, city=Yunlin), year=2018, amount=559000)
Trade(cstm=Customer(name=KFC, age=38, city=Taipei), year=2018, amount=810000)
Trade(cstm=Customer(name=Mark, age=53, city=Taipei), year=2018, amount=1005000)
用 map 指出要保留的欄位,distinct() 表示重複的只會列出一筆。
New Taipei
Taichung
Taipei
Yunlin
Taichung
Taipei
Yunlin
Customer(name=KFC, age=38, city=Taipei)
Customer(name=Mark, age=53, city=Taipei)
Customer(name=Mark, age=53, city=Taipei)
total = 2705100
上面的寫法會有個「封裝」的成本,int 被封裝成 Integer,或 Integer 拆裝成 int 都會需要一點點時間。為了解決這個問題,Stream 提供了 IntStream、DoubleStream、LongStream 三個原始型別的串流,那麼上面的程式可以改寫成如下:
使用 reduce() 可以將資料歸納,這裡指出要資料中最大的。
total = 1005000
【番外篇】
Arrays.asList(...) 產生的 List 會是固定大小,上面的 trades 中的元素可以更改,但是,如果要加入新元素,例如: trades.add(new Trade()); 會拋出 UnsupportedModificationException。
沒有留言:
張貼留言