开发者

How can I represent a range in Java?

开发者 https://www.devze.com 2023-04-12 07:19 出处:网络
Let\'s say an integer should be within the range: [0...2147483647] I want to check whether an integer variable falls within this range. I know it can be accomplished by a simple if-else statement, bu

Let's say an integer should be within the range: [0...2147483647]

I want to check whether an integer variable falls within this range. I know it can be accomplished by a simple if-else statement, but is there a more efficient way to check whether it's within the range?

I'd rather not do this:

if (foo >= 0 && foo <= 2147483647) 
{
    // do somethi开发者_如何学运维ng
}


Apache Commons Lang has a Range class for doing arbitrary ranges.

Range<Integer> test = Range.between(1, 3);
System.out.println(test.contains(2));
System.out.println(test.contains(4));

Guava Range has similar API.

If you are just wanting to check if a number fits into a long value or an int value, you could try using it through BigDecimal. There are methods for longValueExact and intValueExact that throw exceptions if the value is too big for those precisions.


You could create a class to represent this

public class Range
{
    private int low;
    private int high;

    public Range(int low, int high){
        this.low = low;
        this.high = high;
    }

    public boolean contains(int number){
        return (number >= low && number <= high);
    }
}

Sample usage:

Range range = new Range(0, 2147483647);

if (range.contains(foo)) {
    //do something
}


I know this is quite an old question, but with Java 8's Streams you can get a range of ints like this:

// gives an IntStream of integers from 0 through Integer.MAX_VALUE
IntStream.rangeClosed(0, Integer.MAX_VALUE); 

Then you can do something like this:

if (IntStream.rangeClosed(0, Integer.MAX_VALUE).matchAny(n -> n == A)) {
    // do something
} else {
    // do something else 
}


You could use java.time.temporal.ValueRange which accepts long and would also work with int:

int a = 2147;

//Use java 8 java.time.temporal.ValueRange. The range defined
//is inclusive of both min and max 
ValueRange range = ValueRange.of(0, 2147483647);

if(range.isValidValue(a)) {
    System.out.println("in range");
}else {
    System.out.println("not in range");
}


If you are checking against a lot of intervals, I suggest using an interval tree.


You will have an if-check no matter how efficient you try to optimize this not-so-intensive computation :) You can subtract the upper bound from the number and if it's positive you know you are out of range. You can perhaps perform some boolean bit-shift logic to figure it out and you can even use Fermat's theorem if you want (kidding :) But the point is "why" do you need to optimize this comparison? What's the purpose?


For a range of Comparable I use the following :

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;
    }
}

(This is a somewhat shorted version. The full code is available here )


import java.util.Arrays;

class Soft{
    public static void main(String[] args){
        int[] nums=range(9, 12);
        System.out.println(Arrays.toString(nums));
    }
    static int[] range(int low, int high){
        int[] a=new int[high-low];
        for(int i=0,j=low;i<high-low;i++,j++){
            a[i]=j;
        }
        return a;

    }
}

My code is similar to Python`s range :)


If you use Spring, you can rely on org.springframework.data.domain that is quite complete including bound and unbound ranges.

0

精彩评论

暂无评论...
验证码 换一张
取 消