【经验分享】Java 8 Stream API使用示例
文章目录
- 前言
- 创建一个流
- 过滤
- map转换
- flatMap 先展开再转换
- distinct 去重
- sort 排序
- limit+skip 可实现分页
- peek 用于执行结果前后查看,方便调试
- collect 收集,是流的一种终止操作
- grouping 分组
- partitioning 分区
- reduce 使用累计函数进行归约
前言
Stream流式操作,针对集合、数组、函数、I/O流等提供了映射、转换、过滤、排序、聚合等一系列API,一些原本非常复杂的查询,使用Stream只需要几行代码就可以搞定,大大简化了代码的复杂度。
创建一个流
public void createStream() { // list构建 Lists.newArrayList(1, 2, 3).stream(); // 数组构建 Arrays.stream(new int[]{1, 2, 3}); // 元素构建 Stream.of(1, 2, 3); // 元素可以是不同类型的 Stream.of(1, 2, "a"); // 迭代器构建,迭代器构建的是一个无限流,必须要有限制 Stream.iterate(2, item -> item * 2).limit(5);}
过滤
public void filter() { // 筛选出不等于“a”的元素 Stream.of(1, 2, "a").filter(item -> !item.equals("a")).forEach(System.out::println); // 从1-10中筛选出大于5的奇数 IntStream.rangeClosed(1, 10).filter(item -> item % 2 == 1).filter(item -> item > 5).forEach(System.out::println);}
map转换
public void map() { // mapToObj IntStream.rangeClosed(1, 10) .mapToObj(item -> new Order(item * 2)) .collect(Collectors.toList()) .forEach(System.out::println); // mapToDouble double sum = IntStream.rangeClosed(1, 10) .mapToObj(item -> new Order(item * 2)) .collect(Collectors.toList()) .stream() .mapToDouble(Order::getAmount) .sum(); System.out.println(sum);}
flatMap 先展开再转换
public void flatMap() { // 构建一个User集合 List<User> userList = IntStream.rangeClosed(1, 10) .mapToObj(item -> new User("user_" + item, IntStream.rangeClosed(1, item).mapToObj(role -> new Role("role_" + role)).collect(Collectors.toList()))) .collect(Collectors.toList()); // 遍历其中的Roles集合,看看map和flatMap的区别 userList.stream().map(User::getRoles).forEach(System.out::println); userList.stream().flatMap(role -> role.getRoles().stream()).forEach(System.out::println);}
distinct 去重
public void distinct() { List<User> userList = IntStream.rangeClosed(1, 10) .mapToObj(item -> new User("user_" + item, IntStream.rangeClosed(1, item).mapToObj(role -> new Role("role_" + role)).collect(Collectors.toList()))) .collect(Collectors.toList()); // 去重后重新拼接 System.out.println(userList.stream().flatMap(user -> user.getRoles().stream()).map(Role::getRole).distinct().collect(Collectors.joining(",")));}
sort 排序
public void sort() { List<Order> orderList = IntStream.rangeClosed(1, 10) .mapToObj(item -> new Order(item * 2)) .collect(Collectors.toList()); // sort+limit,输出前3大的amount orderList.stream() .sorted(Comparator.comparing(Order::getAmount).reversed()) .limit(3) .collect(Collectors.toList()) .forEach(System.out::println);}
limit+skip 可实现分页
public void skip() { List<Order> orderList = IntStream.rangeClosed(1, 10) .mapToObj(item -> new Order(item * 2)) .collect(Collectors.toList()); // sort+limit+skip orderList.stream() .sorted(Comparator.comparing(Order::getAmount).reversed()) .skip(1) .limit(3) .collect(Collectors.toList()) .forEach(System.out::println);}
peek 用于执行结果前后查看,方便调试
public void peek() { Stream.of("one", "two", "three", "four") .filter(e -> e.length() > 3) .peek(e -> System.out.println("Filtered value: " + e)) .map(String::toUpperCase) .peek(e -> System.out.println("Mapped value: " + e)) .collect(Collectors.toList());}
collect 收集,是流的一种终止操作
public void collect() { // 拼接字符串 String concat = Stream.of("a", "b", "c").collect(StringBuilder::new, StringBuilder::append, StringBuilder::append) .toString(); System.out.println(concat); // 转成List集合 List<String> asList = Stream.of("a", "b", "c").collect(ArrayList::new, ArrayList::add, ArrayList::addAll); System.out.println(asList); // 分隔符+前后缀 List<User> userList = IntStream.rangeClosed(1, 10) .mapToObj(item -> new User("user_" + item, IntStream.rangeClosed(1, item).mapToObj(role -> new Role("role_" + role)).collect(Collectors.toList()))) .collect(Collectors.toList()); System.out.println( userList.stream() .flatMap(user -> user.getRoles().stream()) .map(Role::getRole) .distinct(). collect(Collectors.joining(",", "[", "]"))); List<User> users = IntStream.rangeClosed(1, 10) .mapToObj(item -> new User("user_" + item, IntStream.rangeClosed(1, item).mapToObj(role -> new Role("role_" + role)).collect(Collectors.toList()))) .collect(Collectors.toList()); // 转成Map形式 Map<String, List<Role>> collect = users.stream().collect(Collectors.toMap(User::getName, User::getRoles)); collect.entrySet().forEach(System.out::println);}
grouping 分组
public void grouping() { List<Person> persons = Lists.newArrayList(); persons.add(new Person("a", "Nanjing", "Jiangsu")); persons.add(new Person("b", "Nanjing", "Jiangsu")); persons.add(new Person("c", "WuXi", "Jiangsu")); persons.add(new Person("d", "WuXi", "Jiangsu")); persons.add(new Person("e", "Hangzhou", "Zhejiang")); persons.add(new Person("f", "Hangzhou", "Zhejiang")); // 先按照省分组,再按照城市分组 Map<String, Map<String, List<Person>>> collect = persons.stream() .collect(Collectors.groupingBy(Person::getProvince, Collectors.groupingBy(Person::getCity))); collect.entrySet().forEach(System.out::println); // 按照省分组,并统计出每个省的数量 persons.stream().collect(Collectors.groupingBy(Person::getProvince, Collectors.counting())).entrySet().forEach(System.out::println); // 按照省分组,并计算出现次数最多的省 persons.stream().collect(Collectors.groupingBy(Person::getProvince, Collectors.counting())).entrySet().stream().max(Map.Entry.comparingByValue()).map(Map.Entry::getKey).ifPresent(System.out::println);}
partitioning 分区
public void partitioning() { List<Person> persons = Lists.newArrayList(); persons.add(new Person("a", "Nanjing", "Jiangsu")); persons.add(new Person("b", "Nanjing", "Jiangsu")); persons.add(new Person("c", "WuXi", "Jiangsu")); persons.add(new Person("d", "WuXi", "Jiangsu")); persons.add(new Person("e", "Hangzhou", "Zhejiang")); persons.add(new Person("f", "Hangzhou", "Zhejiang")); // 按照城市分组,筛选出城市为“Nanjing”的信息 Stream<Map.Entry<String, List<Person>>> stream = persons.stream().collect(Collectors.groupingBy(Person::getCity)).entrySet().stream(); stream.filter(a -> a.getKey().equals("Nanjing")).forEach(System.out::println); // 使用partitioningBy的方式,partitioningBy返回的分组只有true和false两种 persons.stream().collect(Collectors.partitioningBy(person -> person.getCity().equals("Nanjing"))).entrySet().stream() .filter(Map.Entry::getKey).forEach(System.out::println);}
reduce 使用累计函数进行归约
public void reduce() { // 累加计算 Integer sum = Stream.of(1, 2, 3, 4, 5).reduce(0, Integer::sum); System.out.println(sum);}