在 java8 中的 Collectors 结合Function接口实现了很多配合stream对集合进行分组, 统计, 求最大, 最小值等简单方便的方法, 因此这里做一些记录, 方便后续的参考
一. 资源准备
后续主要使用此类作为集合中的对象, 操作集合流;
package net.stream.entity;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
/**
* @author Hinsteny
* @date 2017-12-11
* @copyright: 2017 All rights reserved.
*/
public class Book {
/**
* 书名
*/
private String name;
/**
* 书价
*/
private double price;
/**
* 出版时间
*/
private Date time;
public Book(String name) {
this(name, 0D);
}
public Book(String name, double price) {
this(name, price, new Date());
}
public Book(String name, double price, Date time) {
this.name = name;
this.price = price;
this.time = time;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public Date getTime() {
return time;
}
public void setTime(Date time) {
this.time = time;
}
@Override
public String toString() {
return "Book{" +
"name='" + name + '\'' +
", price=" + price +
", time=" + time +
'}';
}
@Override
public int hashCode() {
String book = "";
if (null != this.name) {
book += this.name;
}
book += String.valueOf(this.price);
if (null != this.time) {
book += String.valueOf(this.time);
}
return book.hashCode();
}
@Override
public boolean equals(Object obj) {
boolean result = false;
if (obj instanceof Book) {
result = true;
Book book = (Book) obj;
if (result && null != this.name ) {
result = this.name.equals(book.getName());
}
if (result) {
result = this.price == book.getPrice();
}
if (result && null != this.getTime() ) {
result = this.time.equals(book.getTime());
}
}
return result;
}
public static List<Book> getBooks(String ... books) {
List<Book> _books = new ArrayList<Book>();
for (String book : books) {
Book item = new Book(book);
_books.add(item);
}
return _books;
}
}
二. 常用方法操作示例
这里主要演示了 Collectors 的一些常用方法, 配合stream可以实现常见的 分组, 统计, 求最大值, 平均值等
package net.stream;
import net.stream.entity.Book;
import java.io.Serializable;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* @author Hinsteny
* @date 2017-12-11
* @copyright: 2017 All rights reserved.
*/
public class Collectors_Group {
// 短格式时间
private static final String shortDate = "yyyyMMdd";
public static void main(String[] args) {
List<Book> books = Book.getBooks("Notre-Dame de Paris", "朝花夕拾", "朝花夕拾", "挪威的森林");
books.stream().map(Book::getName).forEach(System.out::println);
// 分组
groupByName(books);
books = new ArrayList<>();
books.add(new Book("Notre-Dame de Paris", 86.9, parseDate(shortDate, "18310101")));
books.add(new Book("朝花夕拾", 36.8, parseDate(shortDate, "19260211")));
books.add(new Book("朝花夕拾", 36.8, parseDate(shortDate, "19260211")));
books.add(new Book("挪威的森林", 30.5, parseDate(shortDate, "19870101")));
// 分组后统计
groupByNameCount(books);
// 求一些分析值, 最大, 最小, 平均
calculate(books);
}
/**
* 按照指定的分组key进行分组
*
* @param books
*/
private static void groupByName(List<Book> books) {
// 按照书名分组
Map<String, List<Book>> collect_one = books.stream().collect(Collectors.groupingBy((book) -> book.getName()));
System.out.println(collect_one);
// 按照书名分组, 但是要去重
Map<String, Set<Book>> collect_two = books.stream().collect(Collectors.groupingBy((book) -> book.getName(), Collectors.toSet()));
System.out.println(collect_two);
}
/**
* 按照指定的规则分组统计
*
* @param books
*/
private static void groupByNameCount(List<Book> books) {
// 按书名分组, 统计每种数的总本书
Map<String, Integer> count = books.stream().collect(Collectors.groupingBy(book -> book.getName(), Collectors.summingInt(t -> 1)));
System.out.println(count);
// 按书名分组, 统计每种数的总价格
Map<String, Double> count_2 = books.stream().collect(Collectors.groupingBy(book -> book.getName(), Collectors.summingDouble(book -> book.getPrice())));
System.out.println(count_2);
// 按照某个时间点进行分割, 统计二者总数
Date split = parseDate(shortDate, "19000101");
Map<Boolean, Integer> count_3 = books.stream().collect(Collectors.partitioningBy(book -> book.getTime().before(split), Collectors.summingInt(t -> 1)));
System.out.println(count_3);
}
/**
* 按照指定的规则分组统计
*
* @param books
*/
private static void calculate(List<Book> books) {
// 找出最晚发版的著作
Comparator<Book> byLastPublish = Comparator.comparing((book -> book.getTime()));
Optional<Book> book = books.stream().collect(Collectors.minBy(byLastPublish));
System.out.println(book.orElseGet(null));
// 找出书价最高的书
// Comparator<Book> byMaxPrice = Comparator.comparing((_book -> -_book.getPrice()));
Comparator<Book> byMaxPrice = Collections.reverseOrder(Comparator.comparing((_book -> _book.getPrice())));
book = books.stream().collect(Collectors.minBy(byMaxPrice));
System.out.println(book.orElseGet(null));
// 算出所有书的平均书价
Double averagePrice = books.stream().collect(Collectors.averagingDouble((__book -> __book.getPrice())));
System.out.println(averagePrice);
}
/**
* 解析时间字符串
*
* @param format
* @param dateStr
* @return
*/
public static Date parseDate(String format, String dateStr) {
Date date = new Date();
DateFormat dateFormat = new SimpleDateFormat(format);
try {
date = dateFormat.parse(dateStr);
} catch (ParseException e) {
e.printStackTrace();
}
return date;
}
}