【发布时间】:2014-08-29 17:50:23
【问题描述】:
我有一门课(除其他外):
public class TimeSeries {
private final NavigableMap<LocalDate, Double> prices;
public TimeSeries() { prices = new TreeMap<>(); }
private TimeSeries(NavigableMap<LocalDate, Double> prices) {
this.prices = prices;
}
public void add(LocalDate date, double price) { prices.put(date, price); }
public Set<LocalDate> dates() { return prices.keySet(); }
//the 2 methods below are examples of why I need a TreeMap
public double lastPriceAt(LocalDate date) {
Map.Entry<LocalDate, Double> price = prices.floorEntry(date);
return price.getValue(); //after some null checks
}
public TimeSeries between(LocalDate from, LocalDate to) {
return new TimeSeries(this.prices.subMap(from, true, to, true));
}
}
现在我需要在地图上有一个“过滤”视图,其中只有一些日期可用。为此,我添加了以下方法:
public TimeSeries onDates(Set<LocalDate> retainDates) {
TimeSeries filtered = new TimeSeries(new TreeMap<> (this.prices));
filtered.dates().retainAll(retainDates);
return filtered;
}
onDates 方法是一个巨大的性能瓶颈,占程序处理时间的 85%。而且由于该程序正在运行数百万次模拟,这意味着在该方法中花费了数小时。
如何提高该方法的性能?
【问题讨论】:
-
过滤后的
TimeSeries副本会被迭代多少次?retainDates通常比prices小很多吗? -
@biziclop 该地图通常包含 1500 个条目,并且集合的大小几乎相同(可能大小相同,包含相同的日期)。过滤的 TimeSeries 通常只使用(迭代)一次。
-
我对LocalDate不太熟悉,但是简单地做prices.get(localeDate)来获得你想要的值会安全吗?
-
在这种情况下,我唯一能说的是,与其创建地图副本,然后调用
retainAll(),不如先从一张空地图开始,然后添加需要保留的项目。因此,您只需对集合进行一次迭代,而且还可以节省一些内存。 -
@assylias 没关系。我更具体地说是在谈论您的 onDates 方法。创建一个新的空 NavigableMap,然后遍历您的集合,并添加您通过调用 prices.get(localeDate) 获得的任何非空值。
标签: java performance treemap