如何用Java表示范围?

时间:2022-05-25 18:43:07

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

假设一个整数应该在以下范围内:[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?

我想检查整数变量是否在此范围内。我知道它可以通过简单的if-else语句来完成,但有没有更有效的方法来检查它是否在范围内?

I'd rather not do this:

我宁愿不这样做:

if (foo >= 0 && foo <= 2147483647) 
{
    // do something
}

8 个解决方案

#1


36  

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

Apache Commons Lang有一个用于执行任意范围的Range类。

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

Guava Range has similar API.

Guava Range有类似的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.

如果您只是想检查数字是否适合长值或int值,您可以尝试通过BigDecimal使用它。 longValueExact和intValueExact有一些方法,如果值对于那些精度而言太大,则抛出异常。

#2


14  

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
}

#3


6  

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

如果你要检查很多间隔,我建议使用间隔树。

#4


4  

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

我知道这是一个很老的问题,但是使用Java 8的Streams,你可以得到一系列这样的整数:

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

#5


3  

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

您可以使用java.time.temporal.ValueRange,它接受long并且也可以使用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");
}

#6


2  

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?

无论你如何有效地优化这种不那么密集的计算,你都会有一个if-check :)你可以从数字中减去上限,如果它是正数,你知道你已经超出了范围。您可以执行一些布尔位移逻辑来计算出来,如果您愿意,您甚至可以使用费马定理(开玩笑:)但重点是“为什么”您需要优化此比较?目的是什么?

#7


1  

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 )

(这是一个有点短路的版本。完整代码可在此处获得)

#8


-1  

In Java 8 you could do the following :

在Java 8中,您可以执行以下操作:

    import java.util.stream.IntStream;

    IntStream range = IntStream.rangeClosed(5,10);
    // simple example if it contains 4
    range.anyMatch(x -> x == 4);

   // check if it contains multiples of 2 etc
   range.anyMatch(x -> x % 2 == 0);

The important difference is that it will allocate the space needed for the Range. If you dont need this behaviour use java.time.temporal.ValueRange which is allocating space for the min and max value only.

重要的区别在于它将分配Range所需的空间。如果您不需要此行为,请使用java.time.temporal.ValueRange,它仅为最小值和最大值分配空间。

#1


36  

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

Apache Commons Lang有一个用于执行任意范围的Range类。

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

Guava Range has similar API.

Guava Range有类似的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.

如果您只是想检查数字是否适合长值或int值,您可以尝试通过BigDecimal使用它。 longValueExact和intValueExact有一些方法,如果值对于那些精度而言太大,则抛出异常。

#2


14  

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
}

#3


6  

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

如果你要检查很多间隔,我建议使用间隔树。

#4


4  

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

我知道这是一个很老的问题,但是使用Java 8的Streams,你可以得到一系列这样的整数:

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

#5


3  

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

您可以使用java.time.temporal.ValueRange,它接受long并且也可以使用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");
}

#6


2  

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?

无论你如何有效地优化这种不那么密集的计算,你都会有一个if-check :)你可以从数字中减去上限,如果它是正数,你知道你已经超出了范围。您可以执行一些布尔位移逻辑来计算出来,如果您愿意,您甚至可以使用费马定理(开玩笑:)但重点是“为什么”您需要优化此比较?目的是什么?

#7


1  

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 )

(这是一个有点短路的版本。完整代码可在此处获得)

#8


-1  

In Java 8 you could do the following :

在Java 8中,您可以执行以下操作:

    import java.util.stream.IntStream;

    IntStream range = IntStream.rangeClosed(5,10);
    // simple example if it contains 4
    range.anyMatch(x -> x == 4);

   // check if it contains multiples of 2 etc
   range.anyMatch(x -> x % 2 == 0);

The important difference is that it will allocate the space needed for the Range. If you dont need this behaviour use java.time.temporal.ValueRange which is allocating space for the min and max value only.

重要的区别在于它将分配Range所需的空间。如果您不需要此行为,请使用java.time.temporal.ValueRange,它仅为最小值和最大值分配空间。