用于两个非唯一值的数据结构

时间:2014-01-09 09:32:42

标签: java performance

我正面临着阅读某个number并不是唯一的date的问题,而index也不是唯一的。

该程序计算量非常大,在我的ide上表现不佳,因此我面临使用正确数据结构的问题。

目前我创建了number,我将date读入一个HashMap,将HashMap读入另一个public HashMap<String,String> getEventDates() throws Exception { String csvFile = "C:\\Users\\test.csv"; CSVReader reader = new CSVReader(new FileReader(csvFile), ';'); String [] line; HashMap<String, String> eventMap = new HashMap<String, String>(); while ((line = reader.readNext()) != null) { eventMap.put(line[15], line[13]); } reader.close(); return eventMap; } public HashMap<String,String> getNumberToEventDates() throws Exception { String csvFile = "C:\\Users\\test.csv"; CSVReader reader = new CSVReader(new FileReader(csvFile), ';'); String [] line; HashMap<String, String> isinMap = new HashMap<String, String>(); while ((line = reader.readNext()) != null) { isinMap.put(line[15], line[4]); } reader.close(); return isinMap; } 。如果我需要它,我只是匹配它们。然而,读入需要两个函数,每个函数都有一个while循环。

line[15]

我应该使用哪种数据结构来更好地执行?如何合并这两种方法?

感谢您的回答!

更新

哦,我很抱歉。

事实上,在每次迭代{{1}}之后,这只是我创建的索引。

如何合并这两个功能?

3 个答案:

答案 0 :(得分:4)

我认为你不应该使用两个函数,因为从文件读取速度较慢,而是将函数修改为,

public HashMap<String, SimpleEntry<String,String>> getEventDatesAndNumber() throws Exception 
{
    String csvFile = "C:\\Users\\test.csv";

    CSVReader reader = new CSVReader(new FileReader(csvFile), ';');
    String [] line;
    HashMap<String, SimpleEntry<String,String>> eventMap = new HashMap<String, SimpleEntry<String,String>>();

    while ((line = reader.readNext()) != null) 
    {            
        eventMap.put(line[15], new SimpleEntry<String , String>(line[13],line[4]));
    }

    reader.close();
    return eventMap;
}

修改 Tim B想法也不错,你有MapKey类,然后你改变上面的方法,

public HashMap<String, MapKey> getEventDatesAndNumber() throws Exception 

然后进行必要的更改。

答案 1 :(得分:1)

如果我理解你的唯一索引是数字和日期的组合,那么你想要查找从中映射的值吗?

处理此问题的方法是创建一个包含数字和日期的MapKey对象:

class MapKey {
   final int number;
   final Date date;

   // Use Your IDE To generate equals and hash code. This is important!
}

然后只需要一个Map<MapKey, Data>,您就可以通过执行

来快速查找
map.get(new MapKey(number, date));

如果您已经拥有MapKey对象而不是一直重新创建它,那么速度会更快,但如果您确实需要创建它,那就没什么大不了的了。

实际上再看一下,你似乎正在从一个值映射到两个值,所以要做到这一点,它将是另一种方式:

class Data {
   int number;
   Date date;

   // Generate constructor etc in IDE
}

Map<String, Data> map = new HashMap<>();

然后只需要一个方法并将for循环更改为:

while ((line = reader.readNext()) != null) {            
    eventMap.put(line[15], new Data(line[13], line[4]));
}

答案 2 :(得分:1)

我将首先假设您的CSV数据是以某种理智的格式构建的。

NUM_HEADER,DATE_HEADER
NUM_VALUE,DATE_VALUE
NUM_VALUE,DATE_VALUE

假设以上情况属实,您基本上应该将CSV文件中的行转换为Java中的对象。通常使用与CSV文件中的值一对一匹配的属性。

所以你的代码看起来像这样。

public Events getEvents() throws Exception {
    String csvFile = "C:\\Users\\test.csv";

    CSVReader reader = new CSVReader(new FileReader(csvFile), ';');
    String [] line;
    HashMap<String, String> eventMap = new HashMap<String, String>();

    while ((line = reader.readNext()) != null) {            
        events.put(line[15], new Event(line[13], line[4]));
    }

    reader.close();
    return events;
}

然后你还需要一个新的值类来将这两个变量放在一起。

class Event {
    private int num;
    private int date;

    public Event(int date, int num) {
        this.date = date;
        this.num = num;
    }

    // Use Your IDE To generate equals and hash code. This is important! Because we're going to put this value class into a Java collection
}

Java collections - overriding equals and hashCode

最后是一个用于在一个不错的服务提供者中保存值类的类。

class Events {
     private Map map = new HashMap<Integer, Event>;

     public put(int uniqueId, Event event) {
         map.put(uniqueId, event);
     }

     //Now you can offer any kind of domain specific services to the consumer of the Events class that you want.
}

我喜欢这种结构,因为它在客户端代码上非常容易。在Event and Events类中锁定了很多复杂性和簿记。您也可以在那里进行验证,并提供许多便利方法。

最后一步,根据您的使用情况,只需要在“事件”对象中包装所有内容。如果您想要的唯一功能是Map接口提供的确切功能,那么我就不会包装它。如果您需要特定于您的域的其他功能,那么我会将其包装起来。但通常我倾向于尽可能倾向于OO课程。从客户的角度来看,如果你正在处理Events类而不是Map<foo,bar>类,那么会更清楚。它在语义上更有意义,并且可以帮助客户了解正在发生的事情。