前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >Java 集合数据处理技巧:使用 Stream API 实现多种操作

Java 集合数据处理技巧:使用 Stream API 实现多种操作

作者头像
小码农薛尧
发布2025-02-26 14:22:38
发布2025-02-26 14:22:38
16100
代码可运行
举报
文章被收录于专栏:小码农薛尧小码农薛尧
运行总次数:0
代码可运行
在 Java 开发中,对集合数据进行处理是非常常见的需求,例如去重、排序、分组、求和等。Java 8 引入的 Stream API 为我们提供了一种简洁、高效的方式来处理集合数据。本文将详细介绍如何使用 Stream API 实现多种集合数据处理操作,并给出相应的代码示例。

1. List 根据某个属性去重

在处理 List 数据时,有时需要根据对象的某个属性进行去重。可以使用 TreeSetStream 来实现这一功能。以下是示例代码:

代码语言:javascript
代码运行次数:0
复制

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.TreeSet;
import java.util.stream.Collectors;

// 定义 SKU 类
class SKU {
    private String gid;

    public SKU(String gid) {
        this.gid = gid;
    }

    public String getGid() {
        return gid;
    }
}

publicclass ListDistinctByProperty {
    public static void main(String[] args) {
        List<SKU> skuList = new ArrayList<>();
        skuList.add(new SKU("1"));
        skuList.add(new SKU("2"));
        skuList.add(new SKU("1"));

        ArrayList<SKU> skus = skuList.stream().collect(
                Collectors.collectingAndThen(
                        Collectors.toCollection(
                                () -> new TreeSet<>(Comparator.comparing(SKU::getGid))
                        ), ArrayList::new
                )
        );

        skus.forEach(sku -> System.out.println(sku.getGid()));
    }
}

在上述代码中,首先创建了一个 SKU 类,包含 gid 属性。然后使用 StreamskuList 进行处理,通过 Collectors.toCollection 将其转换为 TreeSet,利用 TreeSet 的特性根据 gid 去重,最后再将 TreeSet 转换为 ArrayList

2. 指定字段排序 2.1 升序排序

可以使用 Streamsorted 方法和 Comparator.comparing 来实现指定字段的升序排序。以下是示例代码:

代码语言:javascript
代码运行次数:0
复制

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

// 定义 Order 类
class Order {
    privatelong createTime;

    public Order(long createTime) {
        this.createTime = createTime;
    }

    public long getCreateTime() {
        return createTime;
    }
}

publicclass ListSortAsc {
    public static void main(String[] args) {
        List<Order> orderList = new ArrayList<>();
        orderList.add(new Order(3));
        orderList.add(new Order(1));
        orderList.add(new Order(2));

        List<Order> sortedList = orderList.stream()
               .sorted(Comparator.comparing(Order::getCreateTime))
               .collect(Collectors.toList());

        sortedList.forEach(order -> System.out.println(order.getCreateTime()));
    }
}

2.2 降序排序

如果需要降序排序,只需在 Comparator.comparing 后调用 reversed 方法。以下是示例代码:

代码语言:javascript
代码运行次数:0
复制

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

// 定义 Order 类
class Order {
    privatelong createTime;

    public Order(long createTime) {
        this.createTime = createTime;
    }

    public long getCreateTime() {
        return createTime;
    }
}

publicclass ListSortDesc {
    public static void main(String[] args) {
        List<Order> orderList = new ArrayList<>();
        orderList.add(new Order(3));
        orderList.add(new Order(1));
        orderList.add(new Order(2));

        List<Order> sortedList = orderList.stream()
               .sorted(Comparator.comparing(Order::getCreateTime).reversed())
               .collect(Collectors.toList());

        sortedList.forEach(order -> System.out.println(order.getCreateTime()));
    }
}

2.3 null 排前面

如果需要将 null 值排在前面,可以使用 Comparator.nullsFirst 方法。以下是示例代码:

代码语言:javascript
代码运行次数:0
复制

import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

// 定义 LuckyBoysVo 类
class LuckyBoysVo {
    private Date usageTime;

    public LuckyBoysVo(Date usageTime) {
        this.usageTime = usageTime;
    }

    public Date getUsageTime() {
        return usageTime;
    }
}

publicclass ListSortNullFirst {
    public static void main(String[] args) {
        List<LuckyBoysVo> luckyBoysList = new ArrayList<>();
        luckyBoysList.add(new LuckyBoysVo(new Date(2000)));
        luckyBoysList.add(new LuckyBoysVo(null));
        luckyBoysList.add(new LuckyBoysVo(new Date(1000)));

        List<LuckyBoysVo> luckyBoysVoList = luckyBoysList.stream()
               .sorted(Comparator.comparing(LuckyBoysVo::getUsageTime, Comparator.nullsFirst(Date::compareTo)))
               .collect(Collectors.toList());

        luckyBoysVoList.forEach(vo -> System.out.println(vo.getUsageTime()));
    }
}

3. 指定字段相同,指定值计算和

可以使用 Collectors.groupingBy 方法对数据进行分组,然后使用 reduce 方法计算相同字段对应的值的和。以下是示例代码:

代码语言:javascript
代码运行次数:0
复制

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

// 定义 ExportAgentVo 类
class ExportAgentVo {
    private String dealCode;
    private String agentId;
    private String goodsId;
    private String goodName;
    privateint count;
    private String name;
    private String address;

    public ExportAgentVo(String dealCode, String agentId, String goodsId, String goodName, int count, String name, String address) {
        this.dealCode = dealCode;
        this.agentId = agentId;
        this.goodsId = goodsId;
        this.goodName = goodName;
        this.count = count;
        this.name = name;
        this.address = address;
    }

    public String getDealCode() {
        return dealCode;
    }

    public String getAgentId() {
        return agentId;
    }

    public String getGoodsId() {
        return goodsId;
    }

    public String getGoodName() {
        return goodName;
    }

    public int getCount() {
        return count;
    }

    public String getName() {
        return name;
    }

    public String getAddress() {
        return address;
    }
}

publicclass ListSumByField {
    public static void main(String[] args) {
        List<ExportAgentVo> exportAgentVoList = new ArrayList<>();
        exportAgentVoList.add(new ExportAgentVo("1", "A", "G1", "Good1", 10, "Name1", "Addr1"));
        exportAgentVoList.add(new ExportAgentVo("2", "A", "G1", "Good1", 20, "Name1", "Addr1"));
        List<ExportAgentVo> exportAgentVoListResult = new ArrayList<>();

        exportAgentVoList.stream()
               .collect(Collectors.groupingBy(o -> (o.getGoodsId() + o.getAgentId()), Collectors.toList()))
               .forEach((id, transfer) -> {
                    transfer.stream()
                           .reduce((a, b) ->
                                    new ExportAgentVo(a.getDealCode(),
                                            a.getAgentId(),
                                            a.getGoodsId(),
                                            a.getGoodName(),
                                            a.getCount() + b.getCount(), a.getName(), a.getAddress())
                            )
                           .ifPresent(exportAgentVoListResult::add);
                });

        exportAgentVoListResult.forEach(vo -> System.out.println(vo.getCount()));
    }
}

4. 指定字段相同,计算相同个数

可以使用 Collectors.groupingByCollectors.counting 方法来计算指定字段相同的个数。以下是示例代码:

代码语言:javascript
代码运行次数:0
复制

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

// 定义 TkDetailMaskLayerMapping 类
class TkDetailMaskLayerMapping {
    private String maskId;

    public TkDetailMaskLayerMapping(String maskId) {
        this.maskId = maskId;
    }

    public String getMaskId() {
        return maskId;
    }
}

publicclass ListCountByField {
    public static void main(String[] args) {
        List<TkDetailMaskLayerMapping> list = new ArrayList<>();
        list.add(new TkDetailMaskLayerMapping("M1"));
        list.add(new TkDetailMaskLayerMapping("M1"));
        list.add(new TkDetailMaskLayerMapping("M2"));

        Map<String, Long> map = list.stream()
               .collect(Collectors.groupingBy(TkDetailMaskLayerMapping::getMaskId, Collectors.counting()));

        map.forEach((key, value) -> System.out.println(key + ": " + value));
    }
}

5. 指定字段分组

可以使用 Collectors.groupingBy 方法对 List 进行指定字段分组。以下是示例代码:

代码语言:javascript
代码运行次数:0
复制

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

// 定义 ExportAgentVo 类
class ExportAgentVo {
    private String agentId;

    public ExportAgentVo(String agentId) {
        this.agentId = agentId;
    }

    public String getAgentId() {
        return agentId;
    }
}

publicclass ListGroupByField {
    public static void main(String[] args) {
        List<ExportAgentVo> exportAgentVoListResult = new ArrayList<>();
        exportAgentVoListResult.add(new ExportAgentVo("A1"));
        exportAgentVoListResult.add(new ExportAgentVo("A2"));
        exportAgentVoListResult.add(new ExportAgentVo("A1"));

        Map<String, List<ExportAgentVo>> exportAgentVoMap = exportAgentVoListResult.stream()
               .collect(Collectors.groupingBy(ExportAgentVo::getAgentId));

        exportAgentVoMap.forEach((key, value) -> System.out.println(key + ": " + value.size()));
    }
}

6. 分组并求和

可以使用 Collectors.groupingByCollectors.summingInt 方法对数据进行分组并求和。以下是示例代码:

代码语言:javascript
代码运行次数:0
复制

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

// 定义 ExportGoodsProcurementDetailVo 类
class ExportGoodsProcurementDetailVo {
    private String supplierName;
    private String agentId;
    private String goodsId;
    privateint count;

    public ExportGoodsProcurementDetailVo(String supplierName, String agentId, String goodsId, int count) {
        this.supplierName = supplierName;
        this.agentId = agentId;
        this.goodsId = goodsId;
        this.count = count;
    }

    public String getSupplierName() {
        return supplierName;
    }

    public String getAgentId() {
        return agentId;
    }

    public String getGoodsId() {
        return goodsId;
    }

    public int getCount() {
        return count;
    }
}

publicclass ListGroupAndSum {
    public static void main(String[] args) {
        List<ExportGoodsProcurementDetailVo> goodsProcurementDetailVos = new ArrayList<>();
        goodsProcurementDetailVos.add(new ExportGoodsProcurementDetailVo("S1", "A1", "G1", 10));
        goodsProcurementDetailVos.add(new ExportGoodsProcurementDetailVo("S1", "A1", "G1", 20));
        ExportGoodsProcurementDetailVo exportGoodsProcurementDetailVo = new ExportGoodsProcurementDetailVo("S1", "A1", "", 0);
        ExportGoodsProcurementDetailVo exportGoBeerVo = new ExportGoodsProcurementDetailVo("", "A1", "", 0);

        Map<String, Integer> goodCountMap = goodsProcurementDetailVos.stream()
               .filter(a -> a.getSupplierName().equals(exportGoodsProcurementDetailVo.getSupplierName())
                        && a.getAgentId().equals(exportGoBeerVo.getAgentId()))
               .collect(Collectors.groupingBy(ExportGoodsProcurementDetailVo::getGoodsId,
                        Collectors.summingInt(ExportGoodsProcurementDetailVo::getCount)));

        goodCountMap.forEach((key, value) -> System.out.println(key + ": " + value));
    }
}

7. List 转 Map

可以使用 Collectors.toMap 方法将 List 转换为 Map。需要注意的是,如果集合对象有重复的 key,会报错 Duplicate key,可以使用 (k1, k2) -> k1 来处理重复 key 的情况。以下是示例代码:

代码语言:javascript
代码运行次数:0
复制

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

// 定义 CustomerDetailResp 类
class CustomerDetailResp {
    private String dept;
    private String members;

    public CustomerDetailResp(String dept, String members) {
        this.dept = dept;
        this.members = members;
    }

    public String getDept() {
        return dept;
    }

    public String getMembers() {
        return members;
    }
}

// 定义 Apple 类
class Apple {
    privateint id;

    public Apple(int id) {
        this.id = id;
    }

    public int getId() {
        return id;
    }
}

publicclass ListToMap {
    public static void main(String[] args) {
        List<CustomerDetailResp> result = new ArrayList<>();
        result.add(new CustomerDetailResp("D1", "M1"));
        result.add(new CustomerDetailResp("D2", "M2"));

        Map<String, String> map1 = result.stream().collect(Collectors.toMap(CustomerDetailResp::getDept, CustomerDetailResp::getMembers));
        Map<String, CustomerDetailResp> map2 = result.stream().collect(Collectors.toMap(CustomerDetailResp::getDept, CustomerDetailResp -> CustomerDetailResp));

        List<Apple> appleList = new ArrayList<>();
        appleList.add(new Apple(1));
        appleList.add(new Apple(1));
        Map<Integer, Apple> appleMap = appleList.stream().collect(Collectors.toMap(Apple::getId, a -> a, (k1, k2) -> k1));
    }
}

8. List 转 String

可以使用 Google Guava 库的 Joiner 类将 List 转换为 String。以下是示例代码:

代码语言:javascript
代码运行次数:0
复制

import com.google.common.base.Joiner;
import java.util.ArrayList;
import java.util.List;

publicclass ListToString {
    public static void main(String[] args) {
        List<String> itemNoList = new ArrayList<>();
        itemNoList.add("1");
        itemNoList.add("2");
        itemNoList.add("3");

        String join = Joiner.on(',').join(itemNoList);
        System.out.println(join);
    }
}

9. String 转 List

可以使用 Arrays.streamCollectors.toList 方法将 String 转换为 List。以下是示例代码:

代码语言:javascript
代码运行次数:0
复制

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class StringToList {
    public static void main(String[] args) {
        String sales = "1,2,3,2";
        List<String> saleList = Arrays.stream(sales.split(",")).distinct().collect(Collectors.toList());
        saleList.forEach(System.out::println);
    }
}

通过以上示例,我们可以看到 Java 8 的 Stream API 为集合数据处理提供了非常强大和便捷的功能。合理使用这些功能可以大大提高代码的可读性和开发效率。本文示例已涵盖日常开发中90%的集合处理场景,建议根据具体业务需求灵活组合使用。对于更复杂的操作,可结合Collectors.joining、mapping等收集器实现。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-02-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 小码农薛尧 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. List 根据某个属性去重
  • 2. 指定字段排序 2.1 升序排序
    • 2.2 降序排序
    • 2.3 null 排前面
  • 3. 指定字段相同,指定值计算和
  • 4. 指定字段相同,计算相同个数
  • 5. 指定字段分组
  • 6. 分组并求和
  • 7. List 转 Map
  • 8. List 转 String
  • 9. String 转 List
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档