package com.browseengine.bobo.util; import java.util.ArrayList; import java.util.Comparator; import java.util.Iterator; import java.util.List; import org.apache.lucene.util.PriorityQueue; public class SearchResultMerger<T> { private SearchResultMerger() { } public static class MergedIterator<T> implements Iterator<T> { private class IteratorCtx { public Iterator<T> _iterator; public T _curVal; public IteratorCtx(Iterator<T> iterator) { _iterator = iterator; _curVal = null; } public boolean fetch() { if (_iterator.hasNext()) { _curVal = _iterator.next(); return true; } _curVal = null; return false; } } @SuppressWarnings("rawtypes") private final PriorityQueue _queue; @SuppressWarnings("unchecked") public MergedIterator(final List<Iterator<T>> sources, final Comparator<T> comparator) { _queue = new PriorityQueue<Object>(sources.size()) { @Override protected boolean lessThan(Object o1, Object o2) { T v1 = ((IteratorCtx) o1)._curVal; T v2 = ((IteratorCtx) o2)._curVal; return (comparator.compare(v1, v2) < 0); } }; for (Iterator<T> iterator : sources) { IteratorCtx ctx = new IteratorCtx(iterator); if (ctx.fetch()) _queue.add(ctx); } } @Override public boolean hasNext() { return _queue.size() > 0; } @Override @SuppressWarnings("unchecked") public T next() { IteratorCtx ctx = (IteratorCtx) _queue.top(); T val = ctx._curVal; if (ctx.fetch()) { _queue.updateTop(); } else { _queue.pop(); } return val; } @Override public void remove() { throw new UnsupportedOperationException(); } } public static <T> Iterator<T> mergeIterator(List<Iterator<T>> results, Comparator<T> comparator) { return new MergedIterator<T>(results, comparator); } public static <T> ArrayList<T> mergeResult(int offset, int count, List<Iterator<T>> results, Comparator<T> comparator) { Iterator<T> mergedIter = mergeIterator(results, comparator); for (int c = 0; c < offset && mergedIter.hasNext(); c++) { mergedIter.next(); } ArrayList<T> mergedList = new ArrayList<T>(); for (int c = 0; c < count && mergedIter.hasNext(); c++) { mergedList.add(mergedIter.next()); } return mergedList; } }