package com.laytonsmith.PureUtilities.Common; import java.util.AbstractList; import java.util.List; /** * This class provides various methods for comparing numeric ranges. */ public class Range { private final int leftBound; private final int rightBound; private final boolean leftInclusive; private final boolean rightInclusive; /** * Creates a new Range object. The left bound doesn't have to be * less than the right bound, but if it is greater, then the * range is considered descending, assuming leftBound is not equal * to rightBound. Otherwise, it is ascending. * @param leftBound The left boundary number * @param rightBound The right boundary number * @param leftInclusive If the left bound should be inclusive * @param rightInclusive If the right bound should be inclusive */ public Range(int leftBound, int rightBound, boolean leftInclusive, boolean rightInclusive){ this.leftBound = leftBound; this.rightBound = rightBound; this.leftInclusive = leftInclusive; this.rightInclusive = rightInclusive; } /** * Creates a new Range object with both left and right bounds inclusive. * @param leftBound * @param rightBound */ public Range(int leftBound, int rightBound){ this(leftBound, rightBound, true, true); } /** * Returns true if the left bound equals the right bound. If this returns * true, both {@link #isAscending()} and {@link #isDecending()} will return * false. * @return */ public boolean isEqual(){ return leftBound == rightBound; } /** * Returns true if the left bound is less than the right bound. If this * returns true, both {@link #isEqual()} and {@link #isDecending()} will * return false. * @return */ public boolean isAscending(){ return leftBound < rightBound; } /** * Returns true if the right bound is less than the left bound. If this * returns true, both {@link #isEqual()} and {@link #isAscending()} will * return false. * @return */ public boolean isDecending(){ return rightBound < leftBound; } /** * Returns a range of integers, starting with the left bound, counting up (or down if descending) * by 1, and returning a List of values. The returned List is optimized to prevent * a large memory footprint by generating the returned values via * algorithm, instead of actually storing each value. However, this means that the * List is read only. You can create a new List with a copy constructor to make * a new mutable list. * @return */ public List<Integer> getRange(){ //Calculate the size once double _size = Math.abs(leftBound - rightBound); if(!leftInclusive){ _size--; } if(rightInclusive){ _size++; } final int size = (int)_size; return new AbstractList<Integer>() { @Override public Integer get(int index) { if(isAscending()){ return leftBound + index + (leftInclusive?0:1); } else { return leftBound - index - (leftInclusive?0:1); } } @Override public int size() { return size; } }; } /** * Returns the minimum value in this range, regardless of whether * it is descending or ascending. * @return */ public int getMin(){ if(isAscending()){ if(leftInclusive){ return leftBound; } else { return leftBound + 1; } } else if(isDecending()){ if(rightInclusive){ return rightBound; } else { return rightBound + 1; } } else { return leftBound; } } /** * Returns the maximum value in this range, regardless of whether * it is descending or ascending. * @return */ public int getMax(){ if(isDecending()){ if(leftInclusive){ return leftBound; } else { return leftBound - 1; } } else if(isAscending()){ if(rightInclusive){ return rightBound; } else { return rightBound - 1; } } else { return leftBound; } } /** * Returns true if the specified value is included in this range. * @param value The value to test * @return true, if the value is in this range */ public boolean contains(int value){ return value >= getMin() && value <= getMax(); } @Override public String toString(){ return (leftInclusive?"[":"(") + leftBound + ", " + rightBound + (rightInclusive?"]":")"); } }