我需要从之前的查询中解析一个巨大的ResultSet,我想出了一些东西,但它太慢了。
public LinkedList<CountryFirstData> sortCountryFirst() throws SQLException {
long parsingStart = System.nanoTime();
LinkedList<CountryFirstData> list = new LinkedList<CountryFirstData>();
String serie;
String unit;
String country;
BigDecimal value;
int year;
int index;
while (rs.next()) {
serie = rs.getString(1); // rs is the previously built resultSet
unit = rs.getString(2);
country = rs.getString(3);
value = rs.getBigDecimal(4);
year = rs.getInt(5);
if ((index = list.indexOf(new CountryFirstData(country, serie, unit))) != -1) {
list.get(index).getDuo().add(new YearValueDuo(year, value));
}
else {
CountryFirstData data = new CountryFirstData(country, serie, unit);
data.getDuo().add(new YearValueDuo(year, value));
list.add(data);
}
}
long parsingEnd = System.nanoTime();
Collections.sort(list);
long sortEnd = System.nanoTime();
System.out.println("Parsing Time = " + ((parsingEnd - parsingStart)/1000000000)); // gives 112s
System.out.println("Sorting Time = " + ((sortEnd - parsingEnd)/1000000000)); // gives 0s
return list;
}
我会尝试解释一下代码:
resultSet列包含5个不同的值。要考虑的第一个三重奏由country
,serie
和unit
组成。当我第一次得到这样的三重奏(else
情况)时,我需要创建一个新的CountryFirstData
并将结果集行中的剩余二人年/值添加到YearValueDuo
列表字段中。创建了对象。
当country
(serie
案例中)已经存在三个unit
,list
和if
时,我需要检索它并添加二重奏年/值到YearValueDuo
列表。
因此,基本上,resultSet rs长度为4000行,整个解析(排除排序)需要2分钟。我觉得这只有4k线太多了。排序仍然很快(不到一秒钟)。
我在LinkedList
上为CountryFirstData
选择ArrayList
,因为稍后我会在文件中按顺序写出整个列表(这很快)。
你们可以建议我一些改进吗?
答案 0 :(得分:1)
一个List,实际上是一个Set(没有双打),然后排序。并返回实现类,强制进一步使用该类型,防止实现更改。
public Set<CountryFirstData> sortCountryFirst() throws SQLException {
long parsingStart = System.nanoTime();
SortedMap<CountryFirstData, CountryFirstData> identityMap = new TreeMap<>();
// Comparator.comparing(CountryFirstData::getCountry)
// .thenComparing(CountryFirstData::getSerie))
// .thenComparing(CountryFirstData::getUnit));
while (rs.next()) {
String serie = rs.getString(1); // rs is the previously built resultSet
String unit = rs.getString(2);
Stribg country = rs.getString(3);
BigDecimal value = rs.getBigDecimal(4);
int year = rs.getInt(5);
CountryFirstData data = new CountryFirstData(country, serie, unit));
CountryFirstData oldData = identityMap.putIfAbsent(data, data);
if (oldData != null) {
data = oldData;
}
data.getDuo().add(new YearValueDuo(year, value));
}
long parsingEnd = System.nanoTime();
System.out.println("Parsing Time = " + ((parsingEnd - parsingStart)/1_000_000_000L));
return (SortedSet<CountryFirstData>) identityMap.keySet();
}
这取决于equals上现有的比较和。
这里的诀窍是 - 虽然你只需要一个Set - ,但需要一个身份图来获取旧的相等值&#39;(Set.add
只返回一个布尔值)。
因为这仍然很慢:
确保ResultSet已按SQL ORDER BY serie, unit, country
排序。 (如果已经排序,那将解释先前解决方案的缓慢:树形图,它变成线性列表。)
public List<CountryFirstData> sortCountryFirst() throws SQLException {
long parsingStart = System.nanoTime();
List<CountryFirstData> identityMap = new ArrayList<>();
CountryFirstData oldData = null;
while (rs.next()) {
String serie = rs.getString(1); // rs is the previously built resultSet
String unit = rs.getString(2);
Stribg country = rs.getString(3);
BigDecimal value = rs.getBigDecimal(4);
int year = rs.getInt(5);
CountryFirstData data = new CountryFirstData(country, serie, unit));
if (oldData == null || data.compareTo(oldData) != 0) {
oldData = data;
list.add(data);
}
oldData.getDuo().add(new YearValueDuo(year, value));
}
long parsingEnd = System.nanoTime();
System.out.println("Parsing Time = " + ((parsingEnd - parsingStart)/1_000_000_000L));
return list;
}
这使得数据库付出了艰辛的努力。什么是最快的,可以利用指数。