GenericTimeSeries implements Function<T, V>, Iterable<Pair<T, V>> { public GenericTimeSeries<T, V> subSeries(T a, T b) { if (cmp.compare(a, b) >= 0) { throw new IllegalArgumentException(); } int i = binarySearch(times, a, cmp); i = (0 <= i) ? i : -i - 2; int j = binarySearch(times, b, cmp); j = (0 <= j) ? j - 1 : -j - 2; Iterator<Pair<T, V>> result = fluent(of(pairOf(a, this.apply(a)))) .concat(zip(pairOf(times.subList(i, j + 1).iterator(), values.subList(i, j + 1).iterator()), true), of(pairOf(b, null))); return new GenericTimeSeries<>(result); } GenericTimeSeries(Iterator<Pair<T, V>> timestamps);  GenericTimeSeries(Iterable<Pair<T, V>> timestamps);  GenericTimeSeries(Iterator<T> t, Function<T, V> f); static GenericTimeSeries<T, List<V>> merge(Iterable<GenericTimeSeries<T, V>> ts); static GenericTimeSeries<T, V> merge(Iterable<GenericTimeSeries<T, V>> ts, BinaryOperator<V> op); static GenericTimeSeries<T, U> merge(GenericTimeSeries<T, V> tv, GenericTimeSeries<T, V> tw, BiFunction<V, V, U> f); int size(); Pair<T, V> get(int i); GenericTimeSeries<T, V> relocate(Iterator<T> t); V apply(T x); boolean sameLeg(T a, T b); GenericTimeSeries<T, V> subSeries(T a, T b); Iterator<Pair<T, V>> iterator(); void addAttribute(String attribute, Object value); Object getAttribute(String attribute); Iterator<Map.Entry<String, Object>> getAttributes(); @Override boolean equals(Object x); @Override int hashCode();  }
@Test public void testSubSeries() { List<Pair<Integer, Integer>> ts = new ArrayList<>(); ts.add(pairOf(0, 7)); ts.add(pairOf(10, 17)); ts.add(pairOf(20, 27)); GenericTimeSeries<Integer, Integer> tv = new GenericTimeSeries<>(ts.iterator()); try { tv.subSeries(0, 0); fail(); } catch (IllegalArgumentException e) { } assertEquals(tv.subSeries(null, 1000).size(), 5); assertEquals(tv.subSeries(null, -10).size(), 1); assertEquals(tv.subSeries(null, 0).size(), 1); assertEquals(tv.subSeries(null, 7).size(), 3); assertEquals(tv.subSeries(null, 10).size(), 3); assertEquals(tv.subSeries(null, 17).size(), 4); assertEquals(tv.subSeries(null, 20).size(), 4); assertEquals(tv.subSeries(null, 27).size(), 5); assertEquals(tv.subSeries(null, 100).size(), 5); assertEquals(tv.subSeries(-10, 1000).size(), 5); assertEquals(tv.subSeries(0, 1000).size(), 5); assertEquals(tv.subSeries(5, 1000).size(), 5); assertEquals(tv.subSeries(10, 1000).size(), 4); assertEquals(tv.subSeries(15, 1000).size(), 4); assertEquals(tv.subSeries(20, 1000).size(), 3); assertEquals(tv.subSeries(25, 1000).size(), 3); assertEquals(tv.subSeries(null, -100).size(), 1); assertEquals(tv.subSeries(0, 1).size(), 3); }