Source:
<code>public <T extends LogicalSegment> List<T> filterSegments(SelectQuery query, List<T> segments) { PagingSpec pagingSpec = query.getPagingSpec(); Map<String, Integer> paging = pagingSpec.getPagingIdentifiers(); if (paging == null || paging.isEmpty()) { return segments; } List<Interval> intervals = Lists.newArrayList( Iterables.transform( paging.keySet(), SegmentDesc.INTERVAL_EXTRACTOR ) ); Collections.sort( intervals, new Comparator<Interval>() { @Override public int compare(Interval o1, Interval o2) { return Longs.compare(o1.getStartMillis(), o2.getStartMillis()); } } ); List<T> queryIntervals = Lists.newArrayList(segments); Iterator<T> it = queryIntervals.iterator(); if (query.isDescending()) { final long lastEnd = intervals.get(intervals.size() - 1).getEndMillis(); while (it.hasNext()) { T segment = it.next(); if (segment.getInterval().getStartMillis() > lastEnd) { it.remove(); } } } else { final long firstStart = intervals.get(0).getStartMillis(); while (it.hasNext()) { T segment = it.next(); if (segment.getInterval().getEndMillis() < firstStart) { it.remove(); } } <START> } <END> return queryIntervals; }</code><technical_language>this handles case segments overlaps in intervals ? e.g - Segment 1 - 2016-01-01T00:00:00Z/2016-01-02T00:00:00Z - version v1 - Segment 2 - 2016-01-01T01:00:00Z/2016-01-01T02:00:00Z - version v2 > v1 I remember issues similar case in timeboundary query</technical_language>

Target:
public <T extends LogicalSegment> List<T> filterSegments(SelectQuery query, List<T> segments) { PagingSpec pagingSpec = query.getPagingSpec(); Map<String, Integer> paging = pagingSpec.getPagingIdentifiers(); if (paging == null || paging.isEmpty()) { return segments; } final QueryGranularity granularity = query.getGranularity(); List<Interval> intervals = Lists.newArrayList( Iterables.transform(paging.keySet(), SegmentDesc.INTERVAL_EXTRACTOR) ); Collections.sort( intervals, query.isDescending() ? Comparators.intervalsByEndThenStart() : Comparators.intervalsByStartThenEnd() ); TreeMap<Long, Long> granularThresholds = Maps.newTreeMap(); for (Interval interval : intervals) { if (query.isDescending()) { long granularEnd = granularity.truncate(interval.getEndMillis()); Long currentEnd = granularThresholds.get(granularEnd); if (currentEnd == null || interval.getEndMillis() > currentEnd) { granularThresholds.put(granularEnd, interval.getEndMillis()); } } else { long granularStart = granularity.truncate(interval.getStartMillis()); Long currentStart = granularThresholds.get(granularStart); if (currentStart == null || interval.getStartMillis() < currentStart) { granularThresholds.put(granularStart, interval.getStartMillis()); } } } List<T> queryIntervals = Lists.newArrayList(segments); Iterator<T> it = queryIntervals.iterator(); if (query.isDescending()) { while (it.hasNext()) { Interval interval = it.next().getInterval(); Map.Entry<Long, Long> ceiling = granularThresholds.ceilingEntry(granularity.truncate(interval.getEndMillis())); if (ceiling == null || interval.getStartMillis() >= ceiling.getValue()) { it.remove(); } } } else { while (it.hasNext()) { Interval interval = it.next().getInterval(); Map.Entry<Long, Long> floor = granularThresholds.floorEntry(granularity.truncate(interval.getStartMillis())); if (floor == null || interval.getEndMillis() <= floor.getValue()) { it.remove(); } } } return queryIntervals; }