比较来自CSV的两个arrayList

时间:2018-11-26 15:51:26

标签: java arrays sorting arraylist

我有一个一般性问题:

在以下情况下,基于彼此的值对两个数组列表进行排序的最佳方法是什么?

(1)每个arrayList都恰好包含导入的CSV的一列(通过inputStream和bufferReader(为简便起见,我不会在下面打印此内容)。

//my arrayLists:

List <String> OpenVal = new Arraylist ();
List <String> CloseVal = new Arraylist();


//lists from above contain column 0 and 1 from CSV:
while((reader.readLine()) != null) {

Sting line = "";
String ColTwo [] = line.split(",");
openVal.add(colOne[1]);
closVal.add(colOne[2]);

(2)为了更加清楚,CSV [colOne [1],colOne [2]的每一列都包含以下信息:

//colOne [1]  colOne [2]
   date        value
   friday       32
   tues         21
   wed          5

(3)我排序的方式将是这样(按值):

//colOne [1]  colOne [2]
   date        value
   wed          5
   tues         21
   friday       32

(4)我发现比较器类不是高效的,因为我不需要将信息写入arraylist的构造函数。该列表以CSV为前缀。

(3)比较两个列表的最佳方法是什么?

2 个答案:

答案 0 :(得分:2)

如果您的csv每个日期仅包含一行,则可以存储要映射的数据而不是列表:

Map<String,Integer> myMap = new HashMap<>();
String line;
while((line = reader.readLine()) != null) {
    myMap.put(line.split(",")[0], Integer.parseInt(line.split(",")[1]));
}

之后,您可以对地图进行排序:

Map<String,Integer> sorted = myMap.entrySet().stream().
                             sorted(Map.Entry.comparingByValue()).
                             collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,(e1, e2) -> e1,LinkedHashMap::new));

并打印排序的地图:

sorted.entrySet().forEach(System.out::println);

或者如DodgyCodeException所评论,将您的行读到List<String[]>

List<String[]> myList = new ArrayList<>();
    String line = "";
    while((line = reader.readLine()) != null) {
        myList.add(line.split(","));
}

并排序:

    Collections.sort(myList, new Comparator<String[]>() {
        @Override
        public int compare(String[] o1, String[] o2) {
            return Integer.compare(Integer.parseInt(o1[1]), Integer.parseInt(o2[1]));
        }
    });

最后要打印列表,只需使用for循环,例如:

for(String[] row : myList){
    System.out.println(row[0] +" : "+ row[1])
}

答案 1 :(得分:1)

与解析成单独的面向列的数组相比,我能想到两条更好的路由。

  • 编写一个包含成员字段的类来保存您的值,并使用其单一方法Comparable实现compareTo接口。实例化对象并将其收集到List中,然后调用Collections.sort。如果您需要做进一步的工作,或者要放置其他业务逻辑,则这种方法是最好的。
  • 使用库来解析您的CSV文件,并编写一些代码来对结果元组进行排序。

我将显示第二个。

Apache Commons CSV库

Apache Commons CSV库对我读写Comma-Separated ValuesTab-Delimited文件的效果很好。令人惊讶的是,这些格式有多种变体。 Common CSV 至少处理其中的九个。

首先,创建一个示例数据文件。我可以自由地将第一列标题从date更改为dow,以使day-of-week更加精确。

dow,value
friday,32
wed,5
tues,21

通用CSV 库返回Iterable个对象中的CSVRecord个。 CSV包含已解析的CSV数据行中每一列的值。因此,我们可以将这些对象用作tuple

List.sort静态方法将为我们对收集到的元组(CSVRecord对象)进行排序。我们需要提供一种Comparator方法来比较每个元组。对于每个元组,我们提取数据文件第一行中定义的第二个column by its name,即数据文件中的名称value

List < CSVRecord > tuples = new ArrayList <>( 3 );
Reader reader = null;
try {
    reader = new FileReader( "/Users/basilbourque/data.csv" );
    CSVFormat csvFormat = CSVFormat.RFC4180.withIgnoreSurroundingSpaces( true ).withHeader();
    Iterable < CSVRecord > iterable = csvFormat.parse( reader );
    // Convert `Iterable` to a `List`. 
    for ( CSVRecord record : iterable ) {
        tuples.add( record );
    }
} catch ( FileNotFoundException e ) {
    e.printStackTrace();
} catch ( IOException e ) {
    e.printStackTrace();
}

Comparator < CSVRecord > comparator = new Comparator < CSVRecord >() {
    @Override
    public int compare ( CSVRecord o1 , CSVRecord o2 ) {
        Integer a = Integer.valueOf( o1.get( "value" ) );
        Integer b = Integer.valueOf( o2.get( "value" ) );
        return a.compareTo( b );
    }
};
System.out.println( "tuples before sort: \n" + tuples );
tuples.sort( comparator );
System.out.println( "tuples after sort: \n" + tuples );
  

排序前的元组:

     

[CSVRecord [评论=空,映射= {dow = 0,值= 1},recordNumber = 1,值= [星期五,32]],CSVRecord [评论=空,映射= {dow = 0,值=} 1},recordNumber = 2,值= [wed,5]],CSVRecord [comment = null,映射= {dow = 0,值= 1},recordNumber = 3,值= [tues,21]]]

     

排序后的元组:

     

[CSVRecord [comment = null,映射= {dow = 0,值= 1},recordNumber = 2,值= [wed,5]],CSVRecord [comment = null,映射= {dow = 0,值==,dow = 0,值= 1},recordNumber = 3,值= [tues,21]],CSVRecord [comment = null,映射= {dow = 0,值= 1},recordNumber = 1,值= [星期五,32]]]

最后,使用CSVRecord::get循环当前排序的元组列表,以提取数据以用于其他目的。