package com.senseidb.clue.util; import java.io.IOException; import org.apache.lucene.search.DocIdSetIterator; /** * DocIdSetIterator implementation from a sorted list of integers */ public class IntArrayDocIdSetIterator extends DocIdSetIterator{ private final int[] docids; private int docid; private int cursor; public IntArrayDocIdSetIterator(int[] ids){ docids = ids; reset(); } // used for testing public void reset(){ docid = -1; for (cursor = 0;cursor < docids.length;++cursor){ if (docids[cursor]>=0) { break; } } cursor--; if (docids.length == 0) { docid = NO_MORE_DOCS; } } private final static int binarySearchForNearest(int[] arr,int val, int begin, int end) { int mid = (begin + end) >> 1; int midval = arr[mid]; if(mid == end) return midval>=val? mid : -1; if (midval < val) { // Find number equal or greater than the target. if (arr[mid + 1] >= val) return mid + 1; return binarySearchForNearest(arr,val, mid + 1, end); } else { // Find number equal or greater than the target. if (midval == val) return mid; return binarySearchForNearest(arr,val, begin, mid); } } @Override public int docID() { return docid; } @Override public int nextDoc() throws IOException { if (cursor < docids.length-1){ cursor++; docid = docids[cursor]; } else{ docid = NO_MORE_DOCS; } return docid; } @Override public int advance(int target) throws IOException { if (docid != NO_MORE_DOCS){ if (target < docid) return docid; if (target == docid) target = docid+1; int end = Math.min(cursor + (target - docid), docids.length-1); int idx = binarySearchForNearest(docids,target, cursor + 1, end); if (idx!=-1){ if (cursor < idx){ cursor = idx; } else if (cursor == idx){ cursor++; } if (cursor>=docids.length){ docid = NO_MORE_DOCS; return docid; } docid = docids[cursor]; return docid; } else{ cursor = docids.length-1; docid = NO_MORE_DOCS; return docid; } } else{ return NO_MORE_DOCS; } } @Override public long cost() { return docids == null ? 0 : docids.length; } }