Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Find Range in which value lies in Java

Suppose, I have an unsorted array of ranges. For e.g

class CreditRange{
   long credits;
   int id;
}

Now I want to find, given credit count value belongs to which one of the CreditRange.

Possible Set<CreditRange> of values can be

CreditRange :{id:1,credits:0}
CreditRange :{id:2,credits:100}
CreditRange :{id:3,credits:500}
CreditRange :{id:4,credits:250}

Case 1 : Now when user enters Credits = 50, this range comparator should give answer as

CreditRange :{id:1,credits:0}

Case 2 : Now when user enters Credits = 300, this range comparator should give answer as

CreditRange :{id:4,credits:250}

Case 3 : Now when user enters Credits = 600, this range comparator should give answer as

CreditRange :{id:3,credits:500}

We can assume the ranges array takes ~1M and fits the memory. I am looking for an easy algorithm, which uses only standard JDK collections without any 3d-party libraries and special data structures, but works reasonably fast.

What would you suggest?

like image 686
Yashpal Singla Avatar asked Sep 28 '13 08:09

Yashpal Singla


People also ask

How do you find the range of two numbers in Java?

between() is a static method of the Range which is used to obtain an instance of Range with the specified minimum and maximum value. The specified minimum and maximum values are inclusive in nature.

How do you specify a range in Java?

A range can be further defined as either open or closed based whether the range is exclusive or inclusive of the endpoints. open(a, b) : It represents a < range < b, and in notation form, (a, b). closed(a, b) : It represents a <= range <= b, and in notation form, [a, b].

How do you check if a number lies in a range in Java?

ValueRange. of(minValue, maxValue); range. isValidIntValue(x); it returns true if minValue <= x <= MaxValue - i.e. within the range.

Is there a range function in Java?

In Java, the Range method is available in IntStream as well as LongStream class. In IntStream class, it helps in returning sequentially ordered values of IntStream in the range mentioned as parameters of the function.


2 Answers

I guess, it's not the range you are talking about. Rather you want the largest element that is less than your passed element.

You can follow the below steps to solve the problem:

  • First implement a Comparator for your class, which compares on the basis of credits
  • Then, use a TreeSet, passing an instance of that comparator to it's constructor. It will sort the item inside it, as per the comparator.
  • Then use TreeSet#floor(E) method to get the greatest element which is less than E, as per the comparator. Of course, you have to create an object of CreditRange to search. You can't just search for 300.

Demo code:

NavigableSet<Integer> set = new TreeSet<>();
set.add(0);   set.add(100);
set.add(250); set.add(500);

System.out.println(set.floor(50));  // 0
System.out.println(set.floor(300)); // 250

And please rename your class. It is not depicting the range in any manner. It should perhaps be better named as CreditBound as specified by Jon Skeet in comments.

like image 197
Rohit Jain Avatar answered Sep 22 '22 05:09

Rohit Jain


As mentioned by Rohit, one easy method is to use TreeSet floor (another is to implement a a modified variant of Binary search. this is a more complete answer:

package test;

import java.util.TreeSet;

class CreditRange implements Comparable<CreditRange> {
  long credits;
  int id;

  public CreditRange(int id, long credits) {
    this.id = id;
    this.credits = credits;
  }

  public CreditRange(long credits) {
    this.id = -1;
    this.credits = credits;
  }

  @Override
  public int compareTo(CreditRange o) {
    return credits < o.credits ? -1 : credits > o.credits ? 1 : 0;
  }

  @Override
  public String toString() {
    return "id:" + id + ", credits:" + credits;
  }
}

public class Test {
  public static void main(String[] args) {
    TreeSet<CreditRange> set = new TreeSet<>();
    set.add(new CreditRange(1, 0));
    set.add(new CreditRange(2, 100));
    set.add(new CreditRange(3, 500));
    set.add(new CreditRange(4, 250));
    System.out.println(set.floor(new CreditRange(50)));
    System.out.println(set.floor(new CreditRange(300)));
    System.out.println(set.floor(new CreditRange(600)));
  }
}
like image 21
Omry Yadan Avatar answered Sep 24 '22 05:09

Omry Yadan