Java枚举按数字范围搜索

时间:2011-09-04 14:34:44

标签: java enums

是否可以像下面这样进行枚举

enum {

 10  poor
 100  rich
 1000 very_rich


}

这样当我按输入值搜索时,请说101.它会返回“富”吗?如何在枚举中做到这一点?可举个例子吗?我不想用forloop循环整个枚举来获取string_value。可能的?

8 个答案:

答案 0 :(得分:6)

“标准”方式

使用额外的成员变量(包含值enum10100)创建1000。然后,只需在枚举getWealth中创建一个静态方法,根据money参数找到正确的枚举值:

static enum Wealth {
    POOR(10), RICH(100), VERY_RICH(1000);

    private final int money;

    private Wealth(int money) {
        this.money = money;
    }

    public static Wealth getWealth(int money) {
        Wealth found = POOR;
        for (Wealth w : values())
            if (w.money <= money)
                found = w;

        return found;
    }
}

public static void main(String[] args) {
    System.out.println(Wealth.getWealth(101));
    System.out.println(Wealth.getWealth(9));
    System.out.println(Wealth.getWealth(10000));
}

输出继电器:

RICH
POOR
VERY_RICH

没有循环:

我在你的一条评论中看到你想要在没有循环的情况下做到这一点。这可以通过一些技巧完成。首先,在此解决方案(10,100,1000)中无法更改您的值,因为它使用money参数给出的字符串的长度:

static enum Wealth {
    POOR, RICH, VERY_RICH; // 10, 100, 1000

    public static Wealth getWealth(int money) {
        int len = Integer.toString(money).length();
        int ordinal = Math.max(0, Math.min(len - 2, values().length - 1));
        return values()[ordinal];
    }
}

答案 1 :(得分:5)

使用值enum,正如其他人已经建议的那样。

然后,不是通过枚举值执行暴力迭代搜索,而是提供静态lookup(int)方法,该方法通过所有值的有序列表/数组执行binary search

要执行搜索,请将中间值或中间值作为“root”开始,并将我们要查找的值与之比较。

如果我们正在寻找的价值正是如此,那么我们就完成了。如果它小于那个,那么我们再次从中间开始搜索值的下半部分。如果更大,则将其与之后的值进行比较,看它是否在范围内。如果它仍然更大,那么搜索上半部分,依此类推。


编辑:请求的代码示例。

public enum Wealth {

    BROKE(0),
    DESTITUTE(10),
    POOR(100),
    MIDDLE_CLASS(10000),
    RICH(100000),
    MILLIONAIRE(1000000),
    BILLIONAIRE(1000000000);

    private final int value;

    private Wealth(final int value) {
        this.value = value;
    }

    public final int getValue() {
        return value;
    }

    /**
     * @param v
     *        the value we're looking for
     * @return Wealth
     */
    public static Wealth lookup(final int v) {
        final Wealth[] a = Wealth.values();
        int min = 0;
        int max = a.length  - 1;
        int i;
        do {
            i = (min + max) / 2;
            final int av = a[i].value;
            if (v < av) {
                max = i;
            } else if (v > av) {
                if (i + 1 < a.length && v < a[i + 1].value) {
                    break;
                }
                min = i + 1;
            }
        } while (v != a[i].value && min < max);
        if (min == max) {
            return a[max];
        }
        return a[i];
    }

}

几点说明:

这假定Wealth的值已经订购。否则,快速排序(双关语!)应该可以解决问题。

这可能不是最有效的实现,只是从维基百科上的伪代码改编而来的快速而肮脏的实现。

如果你的数量少于十几个,那么线性搜索可能仍然比二分搜索更有效(并且代码肯定更加不言自明)。二进制搜索只有在您拥有数十或数百个值时才会真正得到回报,并且您可以执行数百万次查找。

鉴于你的原始价值,这是邪恶的,过早的优化。我只是想把它作为那些使用大量价值观的人的选择。

答案 2 :(得分:1)

是的,Oracle的教程向您展示了如何:

http://download.oracle.com/javase/tutorial/java/javaOO/enum.html

答案 3 :(得分:1)

public enum MyEnum {
    POOR(10), RICH(100), VERY_RICH(1000);

    int money; 
    MyEnum(int money) {
        this.money = money;
    }
}

答案 4 :(得分:1)

您正在寻找的是反向查找。需要在构造函数中接受密钥,并且需要查找方法。

借来的例子: http://www.ajaxonomy.com/2007/java/making-the-most-of-java-50-enum-tricks

public enum WealthLevel {
  POOR(10),
  RICH(100),
  VERY_RICH(1000);

private static final Map<Integer,Status> lookup 
      = new HashMap<Integer,Status>();

 static {
      for(WealthLevel w : EnumSet.allOf(WealthLevel.class))
           lookup.put(w.getCode(), w);
 }

 private int code;

 private WealthLevel(int code) {
      this.code = code;
 }

 public int getCode() { return code; }

 public static WealthLevel get(int code) { 
      return lookup.get(code); 
 }

}

答案 5 :(得分:1)

在java中,枚举是一个类。因此,您只需添加要检索值的任何方法。如果方法值不够,您可以使用任何其他方法来满足您的要求。

也许你的问题也是关于将数据成员添加到枚举。你也可以这样做。

enum A {

     A(1),
     B(2);

      private int a;

     A( int a) { this.a=a; }

      A retrieve( int a ) 
     {
        Your code here maybe using a hashmap 
      }
}

答案 6 :(得分:1)

这种方式既不优雅也不高效,但你看不到任何循环。

我从Chip的回答中偷走了基础知识,并将Set添加到了它:

public enum WealthLevel {
  POOR(10),
  RICH(100),
  VERY_RICH(1000);

private static final Map<Integer,Status> lookup 
      = new HashMap<Integer,Status>();
// contains all codes ordered - for headSet call.
private static final SortedSet<Integer> intValues = new TreeSet<Integer>(); 

 static {
      for(WealthLevel w : EnumSet.allOf(WealthLevel.class)) {
           lookup.put(w.getCode(), w);
           intValues.add( w.getCode() );
      }
 }

 private int code;

 private WealthLevel(int code) {
      this.code = code;
 }

 public int getCode() { return code; }

 public static WealthLevel get(int code) { 
      if (lookup.contains(code)) {
          return lookup.get(code); 
      }
      // No visible iteration through performance probably is not great
      SortedSet<Integer> lower = intValues.headSet(code);
      if (lower.size() > 0) {
          return lookup.get( lower.last() );
      }
      return null; // no possible value <= code
 }

}

答案 7 :(得分:0)

如果它必须是枚举,并且查找必须是O(log n)且开销最小:

public enum WealthLevel {
    POOR(10), RICH(100), VERY_RICH(1000);

    private int lowerLimit;

    private WealthLevel(int lowerLimit) {
        this.lowerLimit = lowerLimit;
    }

    // cache for the sake of performance
    private static final WealthLevel[] values = values();

    private final static int[] lowerLimits; 
    static {
        lowerLimits = new int[values.length];
        for (int i = 0; i < values.length; i++) {
            lowerLimits[i] = values[i].lowerLimit;
        }

    }

    public static WealthLevel lookup(int wealth) {
        int i = Arrays.binarySearch(lowerLimits, wealth);
        if (i < 0) {
            i = -i - 2;
        }
        return values[i];
    }
}

如果您在查找期间可以承受一点开销,请考虑使用TreeMap。另外,如果你只需要一个字符串(例如在某处显示它),也不需要枚举:

class WealthConverter {
    NavigableMap<Integer, String> levels = new TreeMap<Integer, String>();
    {
        levels.put(0, "pennyless");
        levels.put(10, "poor");
        levels.put(100, "rich");
        levels.put(1000, "very rich");
    }

    public String lookup(int wealth) {
        return levels.floorEntry(wealth).getValue();
    }
}