如何使用Java中的特定字段对CSV文件中的数据进行排序?

问题描述 投票:4回答:4

我想用Java读取CSV文件并使用特定列对其进行排序。我的CSV文件如下所示:

 ABC,DEF,11,GHI....
 JKL,MNO,10,PQR....
 STU,VWX,12,XYZ....

考虑到我想使用第三列对其进行排序,我的输出应类似于:

 JKL,MNO,10,PQR....
 ABC,DEF,11,GHI....
 STU,VWX,12,XYZ....

[对用于保存CSV数据的数据结构进行了一些研究之后,这里的人们建议使用将Integer和List作为键和值对in this question的Map数据结构:

 Map<Integer, List<String>>
 where the value, List<String> = {[ABC,DEF,11,GHI....], [JKL,MNO,10,PQR....],[STU,VWX,12,XYZ....]...}
 And the key will be an auto-incremented integer starting from 0.

所以有人可以建议使用Java中“列表”中的元素对地图进行排序的方法吗?另外,如果您认为这种数据结构选择不好,请随时建议一个更简单的数据结构来进行此操作。

谢谢。

java sorting csv map
4个回答
3
投票

我将使用ArrayListArrayListString

ArrayList<ArrayList<String>>

每个条目都是一行,它是字符串列表。您可以通过以下方式初始化列表:

List<ArrayList<String>> csvLines = new ArrayList<ArrayList<String>>();

获得第n行:

List<String> line = csvLines.get(n);

要排序,您要编写一个自定义比较器。在该比较器的构造函数中,您可以传递用于排序的字段位置。

然后,compare方法获取存储位置上的String值,并根据位置将其转换为原始ava类型。例如,您知道csv中的位置2有一个整数,然后将String转换为int。这是正确分类的必要条件。您也可以将Class的ArrayList传递给构造函数,以便它知道哪个字段是什么类型。然后根据列位置使用String.compareTo()Integer.compare()

编辑工作代码示例:

List<ArrayList<String>> csvLines = new ArrayList<ArrayList<String>>();
Comparator<ArrayList<String>> comp = new Comparator<ArrayList<String>>() {
    public int compare(ArrayList<String> csvLine1, ArrayList<String> csvLine2) {
        // TODO here convert to Integer depending on field.
        // example is for numeric field 2
        return Integer.valueOf(csvLine1.get(2)).compareTo(Integer.valueOf(csvLine2.get(2)));
    }
};
Collections.sort(csvLines, comp);

4
投票

在Java 8中可以执行

SortedMap<Integer, List<String>> collect = Files.lines(Paths.get(filename))
    .collect(Collectors.groupingBy(
                                l -> Integer.valueOf(l.split(",", 4)[2]), 
                                TreeMap::new, Collectors.toList()));

注:比较数字是字符串是一个坏主意,因为"100" < "2"可能不是您期望的。

我会使用排序的多图。如果您没有方便,可以执行此操作。

SortedMap<Integer, List<String>> linesByKey = new TreeMap<>();

public void addLine(String line) {
    Integer key = Integer.valueOf(line.split(",", 4));
    List<String> lines = linesByKey.get(key);
    if (lines == null)
         linesByKey.put(key, lines = new ArrayList<>());
    lines.add(line);
}

这将产生行的集合,并按数字排序,其中重复编号的行将保留顺序。例如如果所有行的编号相同,则顺序不变。


0
投票

您也可以使用列表列表:

List<List<String>> Llp = new ArrayList<List<String>>();

然后,您需要调用sort来扩展自定义比较器,该自定义比较器比较列表中的第三项:

    Collections.sort(Llp, new Comparator<LinkedList<String>>() {
            @Override
            public int compare(LinkedList<String> o1, LinkedList<String> o2) {
                try {                      
                    return o1.get(2).compareTo(o2.get(2));
                } catch (IndexOutOfBoundsException e) {
                    return 0;
                }
 }

0
投票

在下面的代码中,我已经根据第二列对CSV文件进行了排序。


public static void main(String[] args) throws IOException {
    String csvFile = "file_1.csv";
    String line = "";
    String cvsSplitBy = ",";
    List<List<String>> llp = new ArrayList<>();
    try (BufferedReader br = new BufferedReader(new FileReader(csvFile))) {
        while ((line = br.readLine()) != null) {
            llp.add(Arrays.asList(line.split(cvsSplitBy)));
        }
        llp.sort(new Comparator<List<String>>() {
            @Override
            public int compare(List<String> o1, List<String> o2) {
                return o1.get(1).compareTo(o2.get(1));
            }
        });
        System.out.println(llp);

    } catch (IOException e) {
        e.printStackTrace();
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.