查找Java中值所在的范围

查找Java中值所在的范围,java,collections,Java,Collections,假设我有一个未排序的范围数组。 例如 现在我想找出,给定的信用计数值属于哪个信用范围 可能的设置值可以是 CreditRange :{id:1,credits:0} CreditRange :{id:2,credits:100} CreditRange :{id:3,credits:500} CreditRange :{id:4,credits:250} 案例1:现在当用户输入Credits=50时,这个范围比较器应该给出 回答为 CreditRange:{id:1,credits:0} 案例

假设我有一个未排序的范围数组。 例如

现在我想找出,给定的信用计数值属于哪个信用范围

可能的
设置值可以是

CreditRange :{id:1,credits:0}
CreditRange :{id:2,credits:100}
CreditRange :{id:3,credits:500}
CreditRange :{id:4,credits:250}
案例1:现在当用户输入Credits=50时,这个范围比较器应该给出 回答为

CreditRange:{id:1,credits:0}

案例2:现在当用户输入Credits=300时,这个范围比较器应该给出 回答为

CreditRange:{id:4,credits:250}

案例3:现在当用户输入Credits=600时,这个范围比较器应该给出 回答为

CreditRange:{id:3,credits:500}

我们可以假设ranges数组占用约1M的内存。我正在寻找一种简单的算法,它只使用标准的JDK集合,没有任何3d party库和特殊的数据结构,但运行速度相当快


你有什么建议?

我想,这不是你说的范围。而是希望最大的元素小于传递的元素

您可以按照以下步骤解决此问题:

  • 首先为你的班级实施一个基于学分的比较
  • 然后,使用,将该比较器的实例传递给它的构造函数。它将根据比较器对其中的项目进行排序
  • 然后根据比较器,使用该方法获得小于
    E
    的最大元素。当然,您必须创建一个
    CreditRange
    对象进行搜索。你不能只搜索
    300
演示代码:

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
NavigableSet集=新树集();
设置。添加(0);增加(100);
增加(250);增加(500);
系统输出打印LN(设置楼层(50));//0
系统输出打印LN(设置楼层(300));//250

请重新命名你的班级。它没有以任何方式描绘范围。正如Jon Skeet在评论中指出的那样,它的名称应该更好地命名为
CreditBound

正如Rohit所提到的,一种简单的方法是使用TreeSet floor(另一种方法是实现二进制搜索的修改变体。这是一个更完整的答案:

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)));
  }
}
封装测试;
导入java.util.TreeSet;
类CreditRange实现了可比较的{
长期学分;
int-id;
公共信用范围(内部id、长期信用){
this.id=id;
这个。学分=学分;
}
公共信用范围(长期信用){
这个.id=-1;
这个。学分=学分;
}
@凌驾
公共整数比较(CreditRange o){
返回积分o.credits-1:0;
}
@凌驾
公共字符串toString(){
返回“id:+id+”,积分:+credits;
}
}
公开课考试{
公共静态void main(字符串[]args){
树集=新树集();
添加(新的CreditRange(1,0));
增加(新的信用范围(2100));
增加(新的信用范围(3500));
增加(新的信用范围(4250));
系统输出打印LN(设置楼层(新CreditRange(50));
系统输出打印LN(设置楼层(新CreditRange(300));
系统输出打印LN(设置楼层(新CreditRange(600));
}
}

它是一个数组还是一个集合?你试过什么吗?它是一组CreditRange我看不出
CreditRange
实际上是一个范围。它只有一个界限。如果你想它是一个真正的范围,你需要它有上下限。如果你想保持当前的结构,你应该将它重命名为之类的东西e> CreditBound
,确保它是一个有序集合(可能不是集合),然后使用二进制切块。尽管这需要创建一个
CreditRange
对象来查找值,但这有点不幸:(@JonSkeet.Yes。我希望Java具有基于其元素查找对象的功能。:(这将是一个巨大的解脱。当然这是一个完整的答案,但我想让OP知道这一点。这就是为什么我没有发布代码。你给了OP一个简单的复制粘贴配方。好吧,当我第一次看到你的答案时,你没有演示代码和缺少的部分的解释以及如何实现它们,所以我继续创建了是(也尝试了二进制搜索,这就是为什么它花费了一些时间)。现在它在这里,我看不出删除它有什么意义。没有问题。当然我强迫你这么做。不要采取其他方式。:)谢谢你的回答,但我已经使用@RohitJain方法实现了它。
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)));
  }
}