# JDK8 stream 流的简单使用 - 2020年4月15日 - 排序,分组,遍历,求和,去重等 --- ### 测试Demo 实体 ```java package com.ezhiyang.controller; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; /** * @author Caixiaowei * @ClassName Demo.java * @Description 测试demo * @createTime 2020年04月15日 15:01:00 */ @Data @AllArgsConstructor @NoArgsConstructor public class Demo { /** * 姓名 */ private String name; /** * 年龄 */ private Integer age; } ``` - 使用了lombok 插件 - @Data 所有属性的get和set方法,toString(), hashCode(), equals() - @AllArgsConstructor 生成含所有属性的构造函数 - @NoArgsConstructor 生成无参构造 ### 测试 ```java @Test public void testStream() { List list = Lists.newArrayList(new Demo("张三", 15), new Demo("李四", 20)); System.out.println("list: " + JSONObject.toJSONString(list)); // 过滤 List collect = list.stream().filter(demo -> demo.getAge() > 15).collect(Collectors.toList()); System.out.println("过滤 age > 15 data: " + JSONObject.toJSONString(collect)); // 分组 Map> listMap = list.stream().collect(Collectors.groupingBy(demo -> demo.getName())); System.out.println("按名字分组 listMap: " + JSONObject.toJSONString(listMap)); // 遍历 list.stream().forEach(demo -> { System.out.print("name: "); System.out.println(demo.getName()); }); // 排序1 collect.clear(); collect = list.stream().sorted((d1, d2) -> { return d2.getAge().compareTo(d1.getAge()); }).collect(Collectors.toList()); System.out.println("按age倒序 collect: " + JSONObject.toJSONString(collect)); // 排序2--正序 collect.clear(); collect = list.stream() .sorted(Comparator.comparing(Demo::getAge)) .collect(Collectors.toList()); System.out.println("按age正序 collect: " + JSONObject.toJSONString(collect)); // 排序3--倒叙 collect.clear(); collect = list.stream() .sorted(Comparator.comparing(Demo::getAge).reversed()) .collect(Collectors.toList()); System.out.println("按age倒叙 collect: " + JSONObject.toJSONString(collect)); // 求和 Integer sum = list.stream().map(Demo::getAge).reduce(0, (a, b) -> a + b); System.out.println("求和 sum: " + sum); Integer sum = list.stream() .filter(e ->(e.getAge() != null)) // 过滤null, 否则报空指针 .map(Demo::getAge).reduce(0, Integer::sum); List list = Lists.newArrayList(1, null, 3); Integer reduce = list.stream() .filter(x -> x != null) // // 过滤null, 否则报空指针 .reduce(Integer::sum).get(); } ``` - 控制台打印 ``` list: [{"age":15,"name":"张三"},{"age":20,"name":"李四"}] 过滤 age > 15 data: [{"age":20,"name":"李四"}] 按名字分组 listMap: {"李四":[{"age":20,"name":"李四"}],"张三":[{"age":15,"name":"张三"}]} name: 张三 name: 李四 按age倒序 collect: [{"age":20,"name":"李四"},{"age":15,"name":"张三"}] 求和 sum: 35 ``` ### 按对象属性值去重 - 测试User对象 ```java @Data @AllArgsConstructor public class User { private Long id; private String name; private Integer sex; private String email; } ``` - 测试, 注意去重属性为空或者null 则会报错,先过滤空/null ```java public static void main(String[] args) { List users = new ArrayList(); users.add(new User(1L, "张三", 1, "1111@qq.com")); users.add(new User(2L, "大漂亮", 2, "2222@qq.com")); users.add(new User(3L, "大漂亮", 1, "3333@qq.com")); if (!CollectionUtils.isEmpty(users)) { List list = users.stream() .filter(c -> !StringUtils.isEmpty(c.getName())) // 过滤null, 否则报空指针 .filter(distinctByKey(user -> user.getName())).collect(Collectors.toList()); System.out.println(list); } } /** * 按属性去重 * @param keyExtractor * @param * @return */ private static Predicate distinctByKey(Function keyExtractor) { Map seen = new ConcurrentHashMap(); return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null; } ``` 输出结果: [User(id=1, name=张三, sex=1, email=1111@qq.com), User(id=2, name=大漂亮, sex=2, email=2222@qq.com)] ### list 转 map ```java Map map = list.stream().collect(Collectors.toMap(User::getId, Function.identity())); ``` #### 当id出现重复的时候会报错, 1. 可以用 Collectors.toMap(keyMapper, valueMapper, mergeFunction) 的重载方法解决, 用后面的值覆盖前面的值 ```java Map map = list.stream().collect(Collectors.toMap(User::getId, u -> u, (u1, u2) -> u1)); ```