Pour une gamme de Comparable
J'utilise les éléments suivants :
public class Range<T extends Comparable<T>> {
/**
* Include start, end in {@link Range}
*/
public enum Inclusive {START,END,BOTH,NONE }
/**
* {@link Range} start and end values
*/
private T start, end;
private Inclusive inclusive;
/**
* Create a range with {@link Inclusive#START}
* @param start
*<br/> Not null safe
* @param end
*<br/> Not null safe
*/
public Range(T start, T end) { this(start, end, null); }
/**
* @param start
*<br/> Not null safe
* @param end
*<br/> Not null safe
*@param inclusive
*<br/>If null {@link Inclusive#START} used
*/
public Range(T start, T end, Inclusive inclusive) {
if((start == null) || (end == null)) {
throw new NullPointerException("Invalid null start / end value");
}
setInclusive(inclusive);
if( isBigger(start, end) ) {
this.start = end; this.end = start;
}else {
this.start = start; this.end = end;
}
}
/**
* Convenience method
*/
public boolean isBigger(T t1, T t2) { return t1.compareTo(t2) > 0; }
/**
* Convenience method
*/
public boolean isSmaller(T t1, T t2) { return t1.compareTo(t2) < 0; }
/**
* Check if this {@link Range} contains t
*@param t
*<br/>Not null safe
*@return
*false for any value of t, if this.start equals this.end
*/
public boolean contains(T t) { return contains(t, inclusive); }
/**
* Check if this {@link Range} contains t
*@param t
*<br/>Not null safe
*@param inclusive
*<br/>If null {@link Range#inclusive} used
*@return
*false for any value of t, if this.start equals this.end
*/
public boolean contains(T t, Inclusive inclusive) {
if(t == null) {
throw new NullPointerException("Invalid null value");
}
inclusive = (inclusive == null) ? this.inclusive : inclusive;
switch (inclusive) {
case NONE:
return ( isBigger(t, start) && isSmaller(t, end) );
case BOTH:
return ( ! isBigger(start, t) && ! isBigger(t, end) ) ;
case START: default:
return ( ! isBigger(start, t) && isBigger(end, t) ) ;
case END:
return ( isBigger(t, start) && ! isBigger(t, end) ) ;
}
}
/**
* Check if this {@link Range} contains other range
* @return
* false for any value of range, if this.start equals this.end
*/
public boolean contains(Range<T> range) {
return contains(range.start) && contains(range.end);
}
/**
* Check if this {@link Range} intersects with other range
* @return
* false for any value of range, if this.start equals this.end
*/
public boolean intersects(Range<T> range) {
return contains(range.start) || contains(range.end);
}
/**
* Get {@link #start}
*/
public T getStart() { return start; }
/**
* Set {@link #start}
* <br/>Not null safe
* <br/>If start > end they are switched
*/
public Range<T> setStart(T start) {
if(start.compareTo(end)>0) {
this.start = end;
this.end = start;
}else {
this.start = start;
}
return this;
}
/**
* Get {@link #end}
*/
public T getEnd() { return end; }
/**
* Set {@link #end}
* <br/>Not null safe
* <br/>If start > end they are switched
*/
public Range<T> setEnd(T end) {
if(start.compareTo(end)>0) {
this.end = start;
this.start = end;
}else {
this.end = end;
}
return this;
}
/**
* Get {@link #inclusive}
*/
public Inclusive getInclusive() { return inclusive; }
/**
* Set {@link #inclusive}
* @param inclusive
*<br/>If null {@link Inclusive#START} used
*/
public Range<T> setInclusive(Inclusive inclusive) {
this.inclusive = (inclusive == null) ? Inclusive.START : inclusive;
return this;
}
}
(Il s'agit d'une version quelque peu abrégée. Le code complet est disponible aquí )