Java枚举按数字范围搜索

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

enum { 10 poor 100 rich 1000 very_rich } 

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

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

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

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

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


编辑:请求的代码示例。

 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的值。 否则,快速排序(双关语!)就可以了。

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

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

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

“标准”的方式

像使用额外的成员变量(包含值1001000 )一样创建enum 。 然后在enum 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]; } } 

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

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

 public enum MyEnum { POOR(10), RICH(100), VERY_RICH(1000); int money; MyEnum(int money) { this.money = money; } } 

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

借鉴的一个例子: 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 lookup = new HashMap(); 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); } } 

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

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

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

 public enum WealthLevel { POOR(10), RICH(100), VERY_RICH(1000); private static final Map lookup = new HashMap(); // contains all codes ordered - for headSet call. private static final SortedSet intValues = new TreeSet(); 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 lower = intValues.headSet(code); if (lower.size() > 0) { return lookup.get( lower.last() ); } return null; // no possible value <= code } } 

如果它必须是枚举,并且查找必须是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 levels = new TreeMap(); { 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(); } }