Java枚举按数字范围搜索

发布于 2024-12-03 04:03:18 字数 196 浏览 5 评论 0原文

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

enum {

 10  poor
 100  rich
 1000 very_rich


}

以便当我按输入值进行搜索时,假设 101. 它将返回“rich”?如何在枚举中做到这一点?可以举例吗?我不想用 forloop 循环整个枚举来获取 string_value。可能的?

Is it possible to do enum like below

enum {

 10  poor
 100  rich
 1000 very_rich


}

so that when i do search by input value let say 101. it will return "rich" ? how to do this in enum? can give example? i do not want to loop entire enum with forloop to get the string_value. possible?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

抠脚大汉 2024-12-10 04:03:18

正如其他人已经建议的那样,使用带有值的 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 的值已经排序。否则,快速排序(双关语!)应该可以解决问题。

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

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

鉴于您的原始值,这是邪恶的、过早的优化。我只是想把它作为那些处理大量价值观的人的一个选择。

Use an enum with values, as the others have already suggested.

Then, instead of performing a brute-force iterative search through the enum values, provide a static lookup(int) method that performs a binary search through an ordered list/array of all the values.

To perform the search, start with the median or middle value as 'root', and compare the value we're looking for with that.

If the value we're looking for is exactly that, then we're done. If it's less than that, then we start searching the lower half of the values, again starting from the middle. If greater, then compare with the value right after it just to see if it falls in range. If it's still larger, then search in the upper half, and so on.


EDIT: Code sample as requested.

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];
    }

}

Several notes:

This assumes that the values for Wealth are already ordered. Otherwise, a quick sort (pun!) should do the trick.

This probably isn't the most efficient implementation, just a quick and dirty one adapted from the pseudo-code on Wikipedia.

If you have fewer than, say, a dozen values, then a linear search might still be more efficient (and the code definitely more self-explanatory) than a binary search. Binary search only really pays off when you have dozens or hundreds of values, and you perform lookups millions of times.

Given your original values, this is evil, premature optimization. I just wanted to bring it up as an option for those who're working with large sets of values.

醉生梦死 2024-12-10 04:03:18

“标准”方式

创建 enum 就像使用额外的成员变量一样(包含值 101001000代码>)。然后只需在枚举 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];
    }
}

"Standard" way

Create the enum as you would with an extra member variable (containing the values 10, 100 and 1000). Then just create a static method in the enum getWealth that finds the correct enum value depending on a money argument:

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));
}

Ouput:

RICH
POOR
VERY_RICH

Without looping:

I saw in one of your comments that you want to do it without looping. This can be done but with some tricks. First, your values cannot be changed in this solution (10, 100, 1000) because it uses the length of the string given by the money argument:

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];
    }
}
空城仅有旧梦在 2024-12-10 04:03:18

这是一种既不优雅也不高效的方法,但是您看不到任何循环。

我从 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
 }

}

Here's a way that's neither elegant nor efficient, but you don't see any looping.

I stole the basics from Chip's answer, and added the Set to it:

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
 }

}
云淡风轻 2024-12-10 04:03:18

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

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

Yes, and the tutorial from Oracle shows you how:

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

谎言月老 2024-12-10 04:03:18
public enum MyEnum {
    POOR(10), RICH(100), VERY_RICH(1000);

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

    int money; 
    MyEnum(int money) {
        this.money = money;
    }
}
云朵有点甜 2024-12-10 04:03:18

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

借用的例子:
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); 
 }

}

What you're looking for is a reverse lookup. The key needs to be accepted in a constructor and you need a lookup method.

An example borrowed from:
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); 
 }

}
葵雨 2024-12-10 04:03:18

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

In java, an enum Is a class. So you can just add any method you want to retrieve values. If the method values is not enough, you could had any other to meet your requirement.

Maybe your question was also about adding data members to enum. You can also do that.

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 
      }
}
或十年 2024-12-10 04:03:18

如果它必须是一个枚举,并且查找必须是 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();
    }
}

If it must be an enum, and lookup must be O(log n) with minimal overhead:

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];
    }
}

If you can live with a little overhead during lookup, consider using a TreeMap instead. Also, if you just need a string (for instance to display it somewhere), an enum is unnecessary, too:

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();
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文