2017-04-18 1 views
1

약 200,000의 틱 값 (날짜 및 값)이있는 목록이 있습니다. 목록에는 이 아니며에는 모든 날짜에 대한 틱 값이 있습니다. 하지만 이것이 내 작품에서 필요한 것입니다. 그래서 틈새에 빠진 진드기 값을 추가 할 무언가가 필요합니다.Java 스트림의 보간 값

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

스트림에서 요소를 추가하고 싶지는 않지만 (스트림에는 데이터가 없기 때문에) 목록에 추가하고 싶습니다. 그렇습니다. 분명히 가능합니다. 1을 더하면됩니다. 하루 종일 확인하고 해당 날짜가 목록에 있는지 확인하십시오. – Shadov

+0

그 전날의 값은 "7"이됩니다. 다시 말해서, 갭이없는 결과 스트림을 얻을 수 있습니까? – David

답변

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); 

또는 스트림 기반 구현 :

[ 
    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 
] 

경우 아무 잘못에 정정 해줘 주시기 바랍니다 :

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에 의해 생성) 중간 결과를 평평하게 .

+0

"현실에서"나는 처음부터 목록을 가지고 있지 않습니다. 들어오는 스트림 만 있고 모든 요소가 포함 된 목록을 만들지 않으려합니다. – David

+0

스트림을 사용하는 샘플을 추가했습니다. – Caramiriel

+0

스트림 기반 구현은 항상 병렬 스트림에서 작동합니까? – gr7