Stream 是Java SE 8类库中新增的关键抽象,它被定义于 java.util.stream.*
这个包里有若干流类型:Stream<T> 代表对象引用流,此外还有一系列特化流,如 IntStream,LongStream,DoubleStream等。
目录
一、基础准备
- User 用户实体类
public class User {
private Long id;
private String name;
private int age;
private String sex;
public User() {
}
public User(Long id, String name, int age, String sex) {
this.id = id;
this.name = name;
this.age = age;
this.sex = sex;
}
// get set 省略。。。
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
", sex='" + sex +
'}';
}
}
- Customer 客户实体类
public class Customer {
private String name;
private String no;
public Customer(String name) {
this.name = name;
}
// 省略 get set
}
- CustomerGroup 客户组实体类
public class CustomerGroup {
List<Customer> customerList = new ArrayList<>();
public CustomerGroup(List<Customer> customerList) {
this.customerList = customerList;
}
public CustomerGroup(Customer... objList) {
this.customerList.addAll(Arrays.asList(objList));
}
// 省略 get set
}
二、数据准备
userList 用于流的一些基础操作使用。
List<User> userList = new ArrayList<>();
userList.add(new User(1L,"akumalzw", 27, "M"));
userList.add(new User(2L,"张三", 18, "M"));
userList.add(new User(3L,"李四", 18, "M"));
userList.add(new User(4L,"王五", 19, "M"));
userList.add(new User(5L,"刘大爷", 88, "M"));
userList.add(new User(6L,"马冬梅", 26, "F"));
userList.add(new User(7L,"马冬梅", 36, "F"));
userList.add(new User(8L,"沈妈妈", 68, "F"));
userList.add(new User(9L,"沈妈妈", 60, "F"));
groupList 用于流的 FloatMap() 的操作。
List<CustomerGroup> groupList = Arrays.asList(
new CustomerGroup(new Customer("1"), new Customer("2"), new Customer("3")),
new CustomerGroup(new Customer("4"), new Customer("5"), new Customer("6")),
new CustomerGroup(new Customer("5"), new Customer("8"), new Customer("9")),
new CustomerGroup(new Customer("10"))
三、基础操作
-
filter - 过滤
System.out.println("------- 过滤 -- filter");
// 简单的过滤可以直接写逻辑
userList.stream().filter(user -> user.getAge() > 60).forEach(user -> System.out.println(user.getName()));
// 出现逻辑复杂的,推荐使用 Predicate 类进行处理
userList.stream().filter(new Predicate<User>() {
@Override
public boolean test(User user) {
return user.getName().equalsIgnoreCase("akumalzw");
}
}).forEach(System.out::println);
-
match - 匹配
System.out.println("------- 匹配 -- match(noneMatch、anyMatch、allMatch)");
boolean allMatch = userList.stream().allMatch(user -> user.getAge() > 60);
boolean anyMatch = userList.stream().anyMatch(user -> user.getAge() > 60);
boolean noneMatch = userList.stream().noneMatch(user -> user.getAge() > 60);
System.out.println("all=" + allMatch + ", any=" + anyMatch + ", none=" + noneMatch);
-
sort/sorted - 排序
Comparator 类的灵活运用。注意 逆序 reversed() 的使用。
System.out.println("------- 用户名 升序");
userList.sort(Comparator.comparing(User::getName));
userList.forEach(user -> System.out.println(user.getName()));
System.out.println("------- 年龄 降序");
userList.sort(Comparator.comparing(User::getAge).reversed());
userList.forEach(user -> System.out.println(user.getName() + ":" + user.getAge()));
System.out.println("------- 用户名 升序,年龄 降序");
userList.sort(Comparator.comparing(User::getName).thenComparing(Comparator.comparing(User::getAge).reversed()));
userList.forEach(user -> System.out.println(user.getName() + ":" + user.getAge()));
System.out.println("------- 特殊-计算后降序..");
List<User> collectList = userList.stream().sorted(Comparator.comparing((user -> user.getAge() - 10), Comparator.reverseOrder()))
.collect(Collectors.toList());
collectList.forEach(user -> System.out.println(user.getName() + ":" + user.getAge()));
-
collect<T>
把同类型数据进行收集,输出 T。
System.out.println("------- 获取某个值的集合 -- .collect()");
List<String> sexList = userList.stream().map(User::getSex).collect(Collectors.toList());
sexList.forEach(System.out::println);
System.out.println("------- 转 List<对象>");
List<Customer> customerList = userList.stream()
.map(u -> new Customer(u.getName()))
.collect(Collectors.toList());
-
collect + Collectors
collect 配合 map,能够对列表数据进行分组、拆分、转换的操作。
System.out.println("------- List 转 Map<String,Object>");
Map<String, User> mapByName = userList.stream().collect(Collectors.toMap(User::getName, a -> a, (k1, k2) -> k1));
mapByName.forEach((k, v) -> System.out.println(k + " -> " + v.toString()));
System.out.println("------- List 转 Map<String,List<T>>");
Map<String, List<User>> mapListByName = userList.stream().collect(Collectors.groupingBy(User::getName));
mapListByName.forEach((k, v) -> System.out.println(k + " -> " + v.size()));
System.out.println("------- List 转 Map<String, Long>");
Map<String, Long> mapCount = userList.stream().collect(Collectors.groupingBy(User::getSex, Collectors.counting()));
mapCount.forEach((k, v) -> System.out.println(k + " -> " + v));
-
计算 - sum、count、avg、max、min...
System.out.println("------- 统计某个值的个数");
System.out.println("------- sum:");
int sum = userList.stream().mapToInt(User::getAge).sum();
System.out.println(sum);
System.out.println("------- max:");
User user = userList.stream().max(Comparator.comparingInt(User::getAge)).get();
System.out.println(user.getName());
System.out.println("------- min:");
user = userList.stream().min(Comparator.comparingInt(User::getAge)).get();
System.out.println(user.getName());
System.out.println("------- average:");
double asDouble = userList.stream().mapToInt(User::getAge).average().getAsDouble();
System.out.println(asDouble);
四、FlatMap介绍
flatMap 是把list中的同对象进行合并的操作。
System.out.println("CustomerGroupCount=" + groupList.size() + ", CustomerCount=" + groupList.stream().flatMapToInt(customerGroup -> IntStream.of(customerGroup.getCustomerList().size())).sum());
List<List<Customer>> map = groupList.stream()
.map(CustomerGroup::getCustomerList)
.collect(Collectors.toList());
System.out.println(map.size());
List<Customer> flatMap = groupList.stream()
.flatMap(customerGroup -> customerGroup.getCustomerList().stream())
.collect(Collectors.toList());
System.out.println(flatMap.size());
五、parallelStream介绍
并行流的概念,用法和stream一样,只要把 .stream() 替换成 .parallelStream()。
就是把一个流分成多个数据块,内部用不同的线程分别处理不同的数据块的流,操作的还是流。
数据量小的时候不推荐使用,线程也是需要开销的,会导致可能比传统的操作更慢!但是当数据量足够大,达到上百万的时候,效率就会提升,性能更优。
List<Integer> list = new ArrayList<>();
for (int i = 0; i < 100000000; i++) {
list.add(i);
}
long timeMillis = System.currentTimeMillis();
System.out.println("parallel stream=" + timeMillis);
List<Integer> arrayList = list.parallelStream()
.mapToInt(x -> x)
.sorted()
.boxed().collect(Collectors.toList());
System.out.println("parallel stream=" + (System.currentTimeMillis() - timeMillis));
总结
这里日常用得比较频繁的一些方法,还有很多接口值得我们去挖掘,继续努力,持续更新。。。