JDK8 stream 流的简单使用:过滤、分组、遍历、求和、去重

JDK8 stream 流的简单使用

  • 2020年4月15日
  • 排序,分组,遍历,求和,去重等

测试Demo 实体

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 生成无参构造

测试

    @Test
    public void testStream() {
        List<Demo> list = Lists.newArrayList(new Demo("张三", 15), new Demo("李四", 20));
        System.out.println("list: " + JSONObject.toJSONString(list));

        // 过滤
        List<Demo> collect = list.stream().filter(demo -> demo.getAge() > 15).collect(Collectors.toList());
        System.out.println("过滤 age > 15 data: " + JSONObject.toJSONString(collect));

        // 分组
        Map<String, List<Demo>> 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<Integer> 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对象
@Data
@AllArgsConstructor
public class User {

    private Long id;

    private String name;

    private Integer sex;

    private String email;
}
  • 测试, 注意去重属性为空或者null 则会报错,先过滤空/null
public static void main(String[] args) {
        List<User> 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<User> 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 <T>
     * @return
     */
    private static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
        Map<Object,Boolean> 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

Map<String, User> map = list.stream().collect(Collectors.toMap(User::getId, Function.identity()));
当id出现重复的时候会报错,
  1. 可以用 Collectors.toMap(keyMapper, valueMapper, mergeFunction) 的重载方法解决, 用后面的值覆盖前面的值
 Map<String, User> map = list.stream().collect(Collectors.toMap(User::getId, u -> u, (u1, u2) -> u1));

JDK 1.8 中的 Stream API 是一种用于处理集合数据的强大工具,它支持函数式编程风格,并且可以简化对集合的复杂操作。Stream API 的设计使得数据处理更加直观、简洁,同时也提高了代码的可读性和可维护性。以下是 Stream API 的主要使用场景: ### 数据过滤与筛选 Stream API 提供了 `filter` 方法,可以根据指定的条件对集合中的元素进行筛选。这种操作在处理大量数据时非常高效,尤其是在需要根据某些规则从集合中提取子集的情况下[^2]。 例如,从一个 `Person` 对象列表中筛选出年龄大于 25 岁的人: ```java List<Person> filteredPeople = people.stream() .filter(p -> p.getAge() > 25) .collect(Collectors.toList()); ``` ### 数据映射与转换 通过 `map` 方法,Stream API 可以将集合中的每个元素按照某种方式转换为另一个对象。这种转换在处理数据时非常常见,例如将一个字符串列表转换为它们的长度列表,或者将一组对象转换为另一组对象[^3]。 ```java List<Integer> lengths = strings.stream() .map(String::length) .collect(Collectors.toList()); ``` ### 数据聚合 Stream API 支持多种聚合操作,如 `count`、`max`、`min` 和 `sum`,这些操作可以用于计算集合中元素的统计信息。这些方法通常用于数据分析和报告生成[^2]。 ```java long count = numbers.stream().count(); Optional<Integer> max = numbers.stream().max(Integer::compare); ``` ### 分组与分区 `Collectors.groupingBy` 和 `Collectors.partitioningBy` 是 Stream API 中非常强大的功能,可以按照某个属性对数据进行分组或分区。这种操作在需要根据某个字段对数据进行分类时非常有用[^5]。 例如,按年龄对 `Person` 对象进行分组: ```java Map<Integer, List<Person>> groupedByAge = people.stream() .collect(Collectors.groupingBy(Person::getAge)); ``` ### 并行处理 Stream API 支持串行和并行两种模式进行汇聚操作,并发模式能够充分利用多核处理器的优势,使用 fork/join 并行方式来拆分任务和加速处理过程。这种模式在处理大规模数据集时可以显著提高性能[^2]。 ```java int sum = numbers.parallelStream() .mapToInt(Integer::intValue) .sum(); ``` ### 遍历与消费 Stream API 提供了 `forEach` 方法,可以用于遍历中的每个元素并执行某个操作。这种方法通常用于执行副作用操作,如打印日志或更新外部状态[^4]。 ```java people.stream() .forEach(p -> System.out.println(p.getName())); ``` ### 数据排序 Stream API 提供了 `sorted` 方法,可以对中的元素进行排序。这种操作在需要对数据进行排序时非常方便,尤其是在需要根据多个字段进行排序的情况下[^2]。 ```java List<Person> sortedPeople = people.stream() .sorted(Comparator.comparing(Person::getAge)) .collect(Collectors.toList()); ``` ### 数据缩减 `reduce` 方法允许将中的元素组合成一个单一的结果,例如求和、求积或拼接字符串。这种操作在需要将多个值合并为一个值时非常有用。 ```java Optional<String> concatenatedNames = people.stream() .map(Person::getName) .reduce((name1, name2) -> name1 + ", " + name2); ``` ### 集合操作 Stream API 还支持集合操作,如 `distinct`、`limit` 和 `skip`,这些操作可以用于、截取或跳过某些元素。这些方法在需要处理集合的子集时非常有用。 ```java List<String> uniqueNames = people.stream() .map(Person::getName) .distinct() .collect(Collectors.toList()); ``` ### 相关问题 1. 如何在 Java 8使用 Stream API 进行数据过滤? 2. Stream API 中的 `map` 方法有哪些常见的使用场景? 3. 如何利用 Stream API 对数据进行分组和分区? 4. Stream API 如何支持并行处理以提高性能? 5. Stream API 中的 `reduce` 方法有哪些实际应用?
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值