You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从CSV文件提取特定数据?基于ArrayList的功能实现求助

先修正你的CSV读取逻辑

首先得说,你当前用Scanner.next()读取CSV的方式有问题——这个方法会把所有空格分隔的内容拆成ArrayList的单个元素,完全破坏了CSV按行、按逗号分隔的结构(比如地址里的空格会把一个字段拆成好几个)。这会导致后续的所有操作都很难做,所以先把读取逻辑改对:

步骤1:创建房产数据类

先定义一个Property类来封装每条房产记录的字段,这样操作起来更清晰:

public class Property {
    private int id;
    private String propertyAddress;
    private String firstName;
    private String lastName;
    private String email;
    private boolean isOwner; // 对应Owner字段,空值可处理为false
    private double price;
    private LocalDate date;
    private boolean isSold; // 对应sold字段

    // 构造方法
    public Property(int id, String propertyAddress, String firstName, String lastName, 
                    String email, boolean isOwner, double price, LocalDate date, boolean isSold) {
        this.id = id;
        this.propertyAddress = propertyAddress;
        this.firstName = firstName;
        this.lastName = lastName;
        this.email = email;
        this.isOwner = isOwner;
        this.price = price;
        this.date = date;
        this.isSold = isSold;
    }

    // 省略getter方法,比如getId(), getPrice(), getDate(), isSold()等,需要自行补充
}

步骤2:正确读取CSV到对象列表

改用nextLine()读取整行,再按逗号分割字段,然后把字段转换成Property对象存入列表:

Path filepath = Paths.get("./data.csv");
List<Property> propertyList = new ArrayList<>();

try (Scanner scanner = new Scanner(filepath)) {
    // 跳过表头行
    if (scanner.hasNextLine()) {
        scanner.nextLine();
    }

    while (scanner.hasNextLine()) {
        String line = scanner.nextLine();
        // 按逗号分割字段(如果字段里有带逗号的情况,建议用专门的CSV解析库比如OpenCSV)
        String[] fields = line.split(",");
        
        // 解析每个字段,注意处理空值和字段位置(对应你提供的CSV结构)
        int id = Integer.parseInt(fields[0].trim());
        // 拼接地址字段(比如把拆分的地址部分合并)
        String propertyAddress = fields[1].trim() + " " + fields[2].trim();
        String firstName = fields[3].trim();
        String lastName = fields[4].trim();
        String email = fields[5].trim();
        boolean isOwner = !fields[6].trim().isEmpty();
        double price = Double.parseDouble(fields[8].trim()); // 对应Price字段位置
        LocalDate date = LocalDate.parse(fields[9].trim()); // 假设日期格式符合ISO标准,否则需要DateTimeFormatter
        boolean isSold = !fields[10].trim().isEmpty();

        Property property = new Property(id, propertyAddress, firstName, lastName, email, isOwner, price, date, isSold);
        propertyList.add(property);
    }
} catch (IOException e) {
    e.printStackTrace();
}

小提示:如果你的CSV字段里有带逗号的内容(比如地址里的逗号),手动用split(",")会出错,建议用成熟的CSV解析库,比如OpenCSV,它能处理带引号的特殊字段。


实现你需要的三个功能

现在有了结构化的Property列表,三个功能就很容易实现了:

1. 通过ID获取房产记录

方法1:遍历列表(适合数据量小的场景)

public Property getPropertyById(List<Property> propertyList, int targetId) {
    for (Property property : propertyList) {
        if (property.getId() == targetId) {
            return property;
        }
    }
    return null; // 没找到返回null
}

方法2:用HashMap做映射(查询更快,适合数据量大的场景)

先把列表转成HashMap做缓存:

Map<Integer, Property> propertyMap = new HashMap<>();
for (Property property : propertyList) {
    propertyMap.put(property.getId(), property);
}

之后查询直接通过Key获取,速度更快:

Property targetProperty = propertyMap.get(targetId);

2. 获取n个最高价房产的列表

对列表按价格降序排序,然后取前n个即可:

public List<Property> getTopNExpensiveProperties(List<Property> propertyList, int n) {
    // 复制原列表避免修改源数据,按价格降序排序
    List<Property> sortedList = new ArrayList<>(propertyList);
    sortedList.sort((p1, p2) -> Double.compare(p2.getPrice(), p1.getPrice()));
    
    // 处理n大于列表长度的情况,避免越界
    int takeCount = Math.min(n, sortedList.size());
    return sortedList.subList(0, takeCount);
}

3. 统计月度总销售额

提取每个已售出房产的月份,然后累加对应月份的销售额:

public Map<Month, Double> getMonthlySales(List<Property> propertyList) {
    Map<Month, Double> monthlySales = new EnumMap<>(Month.class);
    
    for (Property property : propertyList) {
        if (property.isSold()) { // 只统计已售出的房产
            Month month = property.getDate().getMonth();
            double currentSales = monthlySales.getOrDefault(month, 0.0);
            monthlySales.put(month, currentSales + property.getPrice());
        }
    }
    return monthlySales;
}

如果需要按「年份+月份」统计(比如2023年1月、2023年2月),可以把Map的Key换成YearMonth:

Map<YearMonth, Double> monthlySales = new HashMap<>();
// 内部替换为:
YearMonth yearMonth = YearMonth.from(property.getDate());

内容的提问来源于stack exchange,提问作者Kabira S

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 06:55:03