Dada la siguiente lista si rangos de direcciones IP.
LOW HIGH
192.168.10.34 192.168.11.200
200.50.1.1 200.50.2.2
Suponiendo que la iteración todas las direcciones dentro de todos los rangos y almacenarlos en un HashSet utilizará demasiada memoria.
Por lo que necesitamos para mantener los rangos, que son en realidad sólo los números cambiaban todos modos (bajo y alto). ¿Cómo se podría almacenar los rangos en un árbol y luego utilizar una búsqueda eficiente para encontrar si es o no una dirección particular está dentro de la gama (s).
He mirado RangeTree , pero parece que buscar puntos en un plano cartesiano, y no parece adecuado para mi caso de uso. KDTree permite buscar vecino más cercano, y cuando k == 2 es básicamente el mismo que el árbol alcance.
Me gustaría que todos los partidos, ya que puede haber múltiples golpes.
Lo que funcionaría aquí? Estoy muy seguro de que esto es un problema resuelto.
Una norma TreeMap
va a hacer, suponiendo que tiene no hay intervalos que se solapan.
Basta con crear una TreeMap
, cerrado por el extremo inferior de la gama, con la gama completa como el valor. Busque el rango usando floorEntry(K key)
y verificar el valor está en el rango.
Ejemplo utilizando sencilla Integer
en lugar de IpAddress
objeto, pero cualquier Comparable
objeto puede ser utilizado como límites de rango.
public final class RangeMap<T extends Comparable<T>> {
private TreeMap<T, Range<T>> map = new TreeMap<>();
public void add(Range<T> range) {
Entry<T, Range<T>> entry = this.map.floorEntry(range.getUpperInclusive());
if (entry != null && entry.getValue().overlaps(range))
throw new IllegalArgumentException("Overlap: " + range + " vs " + entry.getValue());
entry = this.map.ceilingEntry(range.getLowerInclusive());
if (entry != null && entry.getValue().overlaps(range))
throw new IllegalArgumentException("Overlap: " + range + " vs " + entry.getValue());
this.map.put(range.getLowerInclusive(), range);
}
public boolean contains(T value) {
Entry<T, Range<T>> entry = this.map.floorEntry(value);
return (entry != null && entry.getValue().contains(value));
}
public Range<T> get(T value) {
Entry<T, Range<T>> entry = this.map.floorEntry(value);
return (entry != null && entry.getValue().contains(value) ? entry.getValue() : null);
}
}
public final class Range<T extends Comparable<T>> {
private final T lowerInclusive;
private final T upperInclusive;
public Range(T lowerInclusive, T upperInclusive) {
this.lowerInclusive = lowerInclusive;
this.upperInclusive = upperInclusive;
}
public T getLowerInclusive() {
return this.lowerInclusive;
}
public T getUpperInclusive() {
return this.upperInclusive;
}
public boolean contains(T value) {
return (value.compareTo(this.lowerInclusive) >= 0 &&
value.compareTo(this.upperInclusive) <= 0);
}
public boolean overlaps(Range<T> that) {
return (this.lowerInclusive.compareTo(that.upperInclusive) <= 0 &&
this.upperInclusive.compareTo(that.lowerInclusive) >= 0);
}
@Override
public String toString() {
return "(" + this.lowerInclusive + "-" + this.upperInclusive + ")";
}
}
Prueba
RangeMap<Integer> map = new RangeMap<>();
map.add(new Range<>(50, 59));
map.add(new Range<>(70, 79));
for (int i = 40; i <= 90; i += 3)
System.out.println(i + ": " + map.contains(i));
Salida
40: false
43: false
46: false
49: false
52: true
55: true
58: true
61: false
64: false
67: false
70: true
73: true
76: true
79: true
82: false
85: false
88: false