在Java Stream中插值

时间:2017-04-18 09:40:18

标签: java java-stream

我有一个包含大约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.
    }

}

是否可以向流中添加值,或者是否可以获得不包含间隙的结果流?我可以根据流进行预测(以检测间隙)吗?

1 个答案:

答案 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
]

如果出现任何问题,请随时纠正我。