【问题标题】:Find biggest prices among huge amount of CSV files在大量 CSV 文件中查找最大价格
【发布时间】:2019-06-10 12:06:14
【问题描述】:

我有 100 个包含以下内容的 CSV 文件

name,price
book,12.4
bread,54.23

每个文件显示内容按价格顺序排序 我需要通过所有这些文件找到 10 个最昂贵的产品。这是我的代码:

import org.apache.commons.io.FileUtils;
import org.junit.Assert;
import org.junit.Test;

import java.io.File;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;

import static java.util.stream.Collectors.toList;

public final class FindBiggest extends Assert {

    static class Data {
        public Data(String str) {
            final String[] split = str.split(",");
            this.name = split[0];
            this.price = Float.parseFloat(split[1]);
        }

        private final String name;
        private final float price;
    }

    @Test
    public void test() throws Exception {
        final List<File> files = Files.walk(Paths.get("/tmp/"))
                .filter(Files::isRegularFile)
                .filter(path -> path.toString().endsWith(".csv"))
                .map(Path::toFile)
                .collect(toList());
        final List<Data> collect =
                files.stream()
                        .map(FindBiggest::content)
                        .map(Data::new)
                        .sorted((o1, o2) -> Float.compare(o1.price, o2.price))
                        .limit(10)
                        .collect(toList());
        System.out.println(collect);

    }

    private static String content(final File file) {
        try {
            return FileUtils.readFileToString(file, StandardCharsets.UTF_8);
        } catch (IOException e) {
            throw new UncheckedIOException(e);
        }
    }

}

如果我有很多 csv 文件程序抛出 UOM(Out of memory) 如何实现程序对所有文件中的内容进行排序而不将所有数据加载到内存?

【问题讨论】:

  • 如果文件按价格排序,您不必从文件中读取所有数据。只需从每个文件中获取 10 条第一条记录。它为您提供了 1000 个最大价格元素的列表,然后您需要对该列表进行排序并获取前 10 个元素
  • 我建议使用缓冲区,如果值大于处理的旧文件,则逐行评估每个文件。这样你就不需要将整个文件加载到内存中。
  • @ngueno 假设在第一个文件中的价格是 50 和 40 在第二个文件中 price 30 ,我加载 8 行,然后我将从第一个文件加载 price 50 到第二个文件并加载 price 30 ,但 40 比 30 大
  • @RafałSokalski 排序并不意味着单独文件中的价格需要相等,例如第一个文件可以包含价格 50、40、20,第二个文件可以包含 30、10、5,如果我只加载一个来自第一个文件,第二个我将有 50 和 30
  • @AlmasAbdrazak,好的,所以你需要一个包含 10 个最大价格的结构(例如列表/集合/地图),第一步是逐行读取每个文件,与此结构的内容,如果它大于某些内容,则将其替换为新值。这样,您将读取所有文件,并以不同的结构保持最大价格,而无需将整个内容加载到内存中,因为您将逐行评估值。

标签: java csv io out-of-memory


【解决方案1】:

您需要一些受一定数量项目限制的排序集。可能是一些第 3 方收藏库提供了它,否则您可以以某种方式制作它:Limited SortedSet。重要的是,如果集合已满且新添加的元素超出限制,则此类排序集合的方法add必须返回false,否则返回true

现在,对 csv 文件进行循环。在循环的主体内,从 csv 文件中读取记录并将它们添加到集合中,直到 add 返回 false(这意味着集合已满,并且当前 csv 中的新记录不会大于当前记录 - 时间继续下一个文件)。

循环完成后,结果集就是答案。

【讨论】:

    猜你喜欢
    • 2014-03-13
    • 2014-12-20
    • 1970-01-01
    • 1970-01-01
    • 2020-12-24
    • 2018-04-11
    • 2021-01-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多