我有一个包含大约200,000个刻度值(日期和值)的列表。该列表不具有每个日期的刻度值。但这是我在输出中所需要的。所以我需要在缺口中添加缺少的刻度值。
我正在使用Java Stream API来处理列表。
class Tick {
public LocalDate date;
public BigDecimal value;
public Tick(LocalDate date, BigDecimal value) {
this.date = date;
this.value = value;
}
}
public class DateInterpolator {
public static void main(String [] args)
{
final ArrayList<Tick> list = new ArrayList<>();
list.add(new Tick(LocalDate.of(2017, 1, 1), BigDecimal.valueOf(7)));
list.add(new Tick(LocalDate.of(2017, 1, 3), BigDecimal.valueOf(8)));
final Stream<Tick> stream = list.stream();
// TODO no value for 2017-01-02 given.
// I want to use the value from the day before (7).
// Add black magic here.
}
}
是否可以向流中添加值,或者是否可以获得不包含间隙的结果流?我可以根据流进行预测(以检测间隙)吗?
答案 0 :(得分:2)
您可以通过跟踪之前的值来检查是否存在间隙。一种方法是直接根据条目的索引访问列表。以下解决方案期望输入按日期排序。
final Stream<Tick> stream = IntStream.range(0, list.size())
.mapToObj((i) -> {
// 'sub' should contain one item. If there are gaps,
// sub will contain gap values as well, up to and including the current Tick.
final ArrayList<Tick> sub = new ArrayList<>();
Tick curr = list.get(i);
if(i > 0) {
Tick prev = list.get(i-1);
// Fill the gaps if there are any
for (LocalDate date = prev.date.plusDays(1); date.isBefore(curr.date); date = date.plusDays(1)) {
sub.add(new Tick(date, prev.value));
}
}
sub.add(curr); // add the current value
return sub;
})
.flatMap(List::stream);
或基于流的实现:
private static Stream<Tick> fillGaps(Stream<Tick> ticks) {
final Var prev = new Var(); // required to be final, so a wrapper is needed to modify the instance
Stream<Tick> result = ticks
.map(curr -> {
final ArrayList<Tick> sub = new ArrayList<>();
if(prev.instance != null) {
for (LocalDate date = prev.instance.date.plusDays(1); date.isBefore(curr.date); date = date.plusDays(1)) {
sub.add(new Tick(date, prev.instance.value));
}
}
sub.add(curr);
prev.instance = curr;
return sub;
})
.flatMap( l -> l.stream());
return result;
}
// Helper class
class Var {
public Tick instance;
}
// Usage:
final Stream<Tick> ticks = fillGaps(stream);
flatMap
展平中间结果(由mapToObject
/ map
创建):
[
Tick(2017-1-1, 7) // Last item is always an item in the original list
],
[
Tick(2017-1-2, 7), // Interpolated value based on the previous value
Tick(2017-1-3, 8) // Last item is always an item in the original list
]
如果出现任何问题,请随时纠正我。