Using headMap()
and tailMap()
is probably the most straightforward solution. If one fears the overhead of making the same search twice, using a list instead of a map is probably the solution. I extended Petar’s suggestion. It can now handle key-value pairs, represented by the small subclass Pair
:
public class DataSet {
// Usage example
public static void main (String [] args) {
DataSet nn = new DataSet ();
nn.add(0.2,1);
nn.add(0.3,2);
nn.add(0.4,3);
nn.add(0.6,4);
nn.add(0.8,5);
nn.add(0.9,6);
nn.add(1.0,7);
int n = 5;
int m = 2;
double v = 0.5;
ListIterator <Pair> it = nn.iterator(v);
for (int i=0; i<m; ++i)
it.previous();
for (int i=0; i<n; ++i)
System.out.append(it.next()+"\n");
}
// Implementation
TreeSet <Pair> set = new TreeSet <Pair> (new PairComparator());
ArrayList <Pair> list = new ArrayList <Pair> ();
boolean listUpToDate = false;
// Add data
boolean add (double x, double y) {
listUpToDate = false;
return set.add(new Pair(x,y));
}
// Get iterator at specified position
ListIterator <Pair> iterator (double v) {
if (!listUpToDate) {
list = new ArrayList (set);
listUpToDate = true;
}
int pos = Collections.binarySearch(list,v);
if (pos < 0)
pos = -pos - 1;
return list.listIterator(pos);
}
// Helper class
static class Pair implements Comparable <Double> {
double x, y;
Pair (double x, double y) {
this.x = x; this.y = y;
}
public int compareTo (Double d) {
return Double.valueOf(x).compareTo(d);
}
public String toString () {
return String.format("[%.1f,%.1f]",x,y);
}
}
// Used for sorting
class PairComparator implements Comparator <Pair> {
public int compare (Pair n0, Pair n1) {
return Double.valueOf(n0.x).compareTo(Double.valueOf(n1.x));
}
}
}
Of course, one could also just use the list, and make sure it is sorted before calling binarySearch()
. But the TreeSet
has also the advantage, besides the ordering, that it prevents duplicate keys.