我目前有一个ArrayList
持有我创建的类的对象,然后在ArrayList
搜索中解析for loop
并比较来自ArrayList
的一些数据还有一些全局variables
加载到其他位置,但是这个ArrayList
不断增长,并且最终会有大约115个元素到达终点,然后需要很长时间来搜索,函数对于我从文本文件中读取的每一行,这也会调用一次,文本文件通常大约为400-500行,因此即使在测试小文件时也可以判断它是非常慢的过程。有没有办法通过使用另一个collection
而不是ArrayList
来加快速度,我使用ArrayList
的理由是我必须知道它找到时的索引是什么匹配。
这是班级:
private ArrayList<PanelData> panelArray = new ArrayList<PanelData>(1);
public class PanelData {
String dev = "";
String inst = "";
double tempStart = 0.0;
double tempEnd = 0.0;
}
功能:
public void panelTimeHandler (double timeStart, double timeEnd) throws SQLException {
PanelData temps = new PanelData();
temps.dev = devIDStr;
temps.inst = instanceStr;
temps.tempStart = timeStart;
temps.tempEnd = timeEnd;
boolean flag = false;
if(!flag)
{
panelArray.add(temps);
flag = true;
}
for(int i = 0; i < panelArray.size(); ++i ) {
if(panelArray.get(i).dev.equals(devIDStr) && panelArray.get(i).inst.equals(instanceStr)) {
if(panelArray.get(i).tempStart <= timeStart && panelArray.get(i).tempEnd >= timeEnd ) {
//Do Nothing
}
else
{
temps.dev = devIDStr;
temps.inst = instanceStr;
temps.tempStart = timeStart;
temps.tempEnd = timeEnd;
insert();
panelArray.set(i, temps);
}
}
else
{
temps.dev = devIDStr;
temps.inst = instanceStr;
temps.tempStart = timeStart;
temps.tempEnd = timeEnd;
panelArray.add(temps);
insert();
}
}
}
如果还有更多你想看到的东西,谢谢。牛肉。
更新:添加了insert()函数
private void insert() throws SQLException
{
stmt = conn.createStatement();
String sqlStm = "update ARRAY_BAC_SCH_Schedule set SCHEDULE_TIME = {t '" + finalEnd + "'} WHERE SCHEDULE_TIME >= {t '" + finalStart + "'} AND" +
" SCHEDULE_TIME <= {t '" + finalEnd + "'} AND VALUE_ENUM = 0 AND DEV_ID = " + devIDStr + " and INSTANCE = " + instanceStr;
int updateSuccess = stmt.executeUpdate(sqlStm);
if (updateSuccess < 1)
{
sqlStm = "insert into ARRAY_BAC_SCH_Schedule (SITE_ID, DEV_ID, INSTANCE, DAY, SCHEDULE_TIME, VALUE_ENUM, Value_Type) " +
" values (1, " + devIDStr + ", " + instanceStr + ", " + day + ", {t '" + finalStart + "'}, 1, 'Unsupported')";
stmt.executeUpdate(sqlStm);
sqlStm = "insert into ARRAY_BAC_SCH_Schedule (SITE_ID, DEV_ID, INSTANCE, DAY, SCHEDULE_TIME, VALUE_ENUM, Value_Type) " +
" values (1," + devIDStr + ", " + instanceStr + ", " + day + ", {t '" + finalEnd + "'}, 0, 'Unsupported')";
stmt.executeUpdate(sqlStm);
}
if(stmt!=null)
stmt.close();
}
更新
感谢Matteo,我意识到我正在添加数组,即使我没有找到匹配,直到第10个元素,然后它将添加到数组前9次,这会在数组中创建许多额外的元素,这就是为什么它是如此之慢,我添加了一些休息并在功能中做了一些调整,它提高了很多性能。感谢所有输入
答案 0 :(得分:3)
您可以使用LinkedHashSet。看起来你只在列表的末尾添加了元素,这正是LinkedHashSet
在插入元素时的作用。
但请注意,LinkedHashSet
不允许重复,因为它是一个集合。
搜索元素是否存在将使用contains()
使用LinkedHashSet
还可以跟踪元素的添加位置,并按插入顺序进行迭代。
答案 1 :(得分:1)
如何使用hashmap
?
我会为密钥创建一个小类:
class Key {
String dev, instr;
// todo: implements equals & hashCode
}
并创建地图:
Map<Key, PanelData> map = new HashMap...
然后您可以通过调用map.get(new Key(...))
轻松找到所需的元素。
您可以调整PanelData类,而不是创建一个新类,实现方法等于&amp; hashcode,以便当dev
和instr
相等时,两个类是相等的。在这种情况下,您的地图将变为:
Map<PanelData, PanelData> map ...
// to add:
map.put(temps, temps)
// to search:
PanelData elem = map.get(new PanelData(desiredDev, desiredInstr));
答案 2 :(得分:1)
这里有一些优化。
1)重复使用call:panelArray.get(i)。在循环之外声明一个PanelData变量,但在循环开始时只初始化一次:
PanelData pd = null;
for (int i = 0; i < panelArray.size(); ++i) {
pd = panelArray.get(i);
...
}
2)如果您的数据集允许,请考虑使用一些地图来帮助加快查找速度:
HashMap<String, PanelData> devToPanelDataMapping = new HashMap<String,PanelData>();
HashMap<String, PanelData> instToPanelDataMapping = new HashMap<String,PanelData>();
3)考虑将字符串散列为整数或长整数,因为String.equals()与(int == int)相比较慢
4)如果ArrayList只是只读,那么多线程解决方案可能会有所帮助。从文本文件中读取行的线程可以将各行数据分发给不同的“工作者”线程。
答案 3 :(得分:1)
1)首次创建PanelArray时,最大预期大小为+ 10%。
List<PanelData> panelArray = new ArrayList<PanelData>(130)
- 这将阻止数组的动态重新分配,这将节省处理时间。
2)insert()
做了什么?赔率是你的资源匮乏。
答案 4 :(得分:0)
使用HashMap
或SortedSet
等不同的数据结构最有可能解决此问题。
为了使用HashMap
,您需要定义一个可以为dev
和inst
字符串对生成哈希码的类。一种解决方案就像:
public class DevAndInstPair
{
private String dev, inst;
@Override
public int hashCode() {
return ((dev.hashCode() * 0x490aac18) ^ inst.hashCode());
}
@Override
public boolean equals(Object o) {
if (o == null || !(o instanceof DevAndInstPair)) {
return false;
}
DevAndInstPair other = (DevAndInstPair) o;
return (dev.equals(other.dev) && inst.equals(other.inst));
}
}
然后,您可以使用HashMap<DevAndInstPair, PanelData>
作为地图类型。
或者,如果您知道某个字符永远不会出现在dev
字符串中,那么您可以将该字符用作将dev
值与inst
值分隔开的分隔符。假设此字符是连字符(' - '),键值为dest + '-' + inst
,地图的键类型为String
。
要使用SortedSet
,您可以PanelData
实施Comparable<PanelData>
或撰写实施Comparator<PanelData>
的课程。请记住,比较操作必须与equals一致。
使用SortedSet
比使用HashMap
更棘手,但我个人认为这是解决此问题的更优雅方法。