1

这是一个简化的例子。我有这个枚举声明如下:

public enum ELogLevel {
    None,
    Debug,
    Info,
    Error
}

我在另一个类中有这段代码:

if ((CLog._logLevel == ELogLevel.Info) || (CLog._logLevel == ELogLevel.Debug) || (CLog._logLevel == ELogLevel.Error)) {
    System.out.println(formatMessage(message));
}

我的问题是是否有办法缩短考试时间。理想情况下,我想要一些调子(这是从 Pascal/Delphi 借来的):

if (CLog._logLevel in [ELogLevel.Info, ELogLevel.Debug, ELogLevel.Error])

而不是一长串的比较。Java中是否有这样的东西,或者可能有一种方法来实现它?我正在使用一个简单的示例,我的目的是找出是否存在模式,以便我可以使用更多元素的枚举值列表进行这些类型的测试。

编辑:看起来 EnumSet 是最接近我想要的东西。实现它的朴素方式是通过以下方式:

if (EnumSet.of(ELogLevel.Info, ELogLevel.Debug, ELogLevel.Error).contains(CLog._logLevel))

但是在基准测试下,这比长 if/then 语句慢两个数量级,我猜是因为 EnumSet 每次运行时都会被实例化。这仅对于经常运行的代码来说是一个问题,即使这样它也是一个非常小的问题,因为超过 100M 的迭代我们在我的盒子上谈论的是 7ms 和 450ms;无论哪种方式,时间都很短。

对于经常运行的代码,我选择的是在静态变量中预先实例化 EnumSet,并在循环中使用该实例,这会将运行时间缩短到 100M 迭代中更可口的 9ms。

所以看起来我们有一个赢家!谢谢你们的快速回复。

4

4 回答 4

5

你想要的是一个枚举集

http://docs.oracle.com/javase/1.5.0/docs/api/java/util/EnumSet.html

将要测试的元素放入集合中,然后使用 Set 方法 contains()。

import java.util.EnumSet;


public class EnumSetExample
{
  enum Level { NONE, DEBUG, INFO, ERROR };

  public static void main(String[] args)
  {
    EnumSet<Level> subset = EnumSet.of(Level.DEBUG, Level.INFO);

    for(Level currentLevel : EnumSet.allOf(Level.class))
    {
      if (subset.contains(currentLevel))
      {
        System.out.println("we have " + currentLevel.toString());
      }
      else
      {
        System.out.println("we don't have " + currentLevel.toString());
      }
    }
  }

}
于 2012-08-10T03:38:52.450 回答
2

在 Java 中没有办法简洁地做到这一点。最接近的方法是将值转储到集合中并调用 contains()。EnumSet 在您的情况下可能是最有效的。您可以使用双括号习惯用法稍微缩短集合初始化,尽管这样做的缺点是每次使用它时都会创建一个新的内部类,因此会稍微增加内存使用量。

于 2012-08-10T03:39:14.007 回答
1

通常,日志记录级别以整数形式实现:

public static int LEVEL_NONE  = 0;
public static int LEVEL_DEBUG = 1;
public static int LEVEL_INFO  = 2;
public static int LEVEL_ERROR = 3;

然后您可以使用简单的比较来测试严重性:

if (Clog._loglevel >= LEVEL_DEBUG) {
    // log
}
于 2012-08-10T03:39:57.093 回答
1

您可以使用所需级别的列表,即:

List<ELogLevel> levels = Lists.newArrayList(ELogLevel.Info,
        ELogLevel.Debug, ELogLevel.Error);
if (levels.contains(CLog._logLevel)) {
    //
}
于 2012-08-10T03:40:34.210 回答