检查O(1)的枚举集中是否包含字符串

时间:2018-08-01 10:32:11

标签: java enums

假设我有一个如下所示的枚举:

public enum Utils {
    UTIL_1, UTIL_2, ... UTIL_n
}

现在,我有Set<Utils> myUtils,其中包含一堆这些枚举条目。其他一些模块(我没有任何控制权)为我提供了一个这样的实用程序名称(例如“ UTIL_i”)作为String。我需要检查它是否包含在集合myUtils中。有什么方法可以在O(1)中执行此操作吗?我了解,我可以将集合更改为一组字符串,然后对此做一个 .contains(),但我想保留它作为最后的选择。

更新: 按照答案中的建议,我尝试了一个小实验。我创建了一个小代码段来生成一个Java文件,其中包含一个固定大小的枚举。我尝试使用大小1000、2500、5000。大小为10000的枚举向我显示了错误The code for the static initializer is exceeding the 65535 bytes limit在Eclipse中的解释,该错误here。我创建了一个集合myUtils并将所有元素从枚举推到该集合。对于每种不同大小的myUtils,我执行了1000次代码段,看起来像myUtils.contains(Utils.valueOf(<elementName>))。该代码段的平均执行时间(以毫秒为单位)如下:

枚举大小= 1000

UTIL_1     search duration = 1704ms
UTIL_500   search duration = 2316ms
UTIL_1000  search duration = 1732ms

枚举大小= 2500

UTIL_1     search duration = 2326ms
UTIL_1250  search duration = 1886ms
UTIL_2500  search duration = 1860ms

枚举大小= 5000

UTIL_1     search duration = 2569ms
UTIL_2500  search duration = 2709ms
UTIL_5000  search duration = 2361ms

它清楚地表明Enum.valueOf(String element)的平均执行时间随枚举的大小而增加,但是我不确定这种方法的时间复杂度。

3 个答案:

答案 0 :(得分:2)

您可以通过Utils将字符串转换为实际的Utils util = Utils.valueOf(String)成员,然后通过myUtils.contains(util)检查字符串是否包含在集合中,该AFAIK是O(1)运算。

当然,如果您获得的字符串实际上与任何Utils不对应,则应该检查异常。在您的示例中,它不是,因为它应该像枚举名称一样是大写。

public enum Utils {
    UTIL_1, UTIL_2, ... UTIL_n
}

//...

String utilName = someOtherModuleRoutine();
try {
    if (myUtils.contains(Utils.valueOf(utilName))) {
        // found!
    } else {
        // not found :(
    }
} catch (IllegalArgumentException e) {
    // utilName is not an actual Utils name
}

答案 1 :(得分:1)

其中一种选择是使用valueOf的{​​{1}}方法,但是时间复杂度取决于您将要使用的输入。

如果大多数输入不可转换enum枚举,则进行Utils并使用set方法作为contains方法是最好的方法不适用于不可转换的值。

参考: Java enum valueOf efficiency

答案 2 :(得分:0)

我建议您扩展Enum以添加其他模块中的字符串标识符。另外,我将编写一种将String转换为Util枚举的方法。

public enum Utils {

    UTIL_1("Utils_1"),

    UTIL_2("Utils_2"),

    UTIL_3("Utils_3");

    private final String name;

    private Utils(final String name) {
        this.name = name;
    }

    public String getName() {
        return this.name;
    }

    public static Utils of(final String name) {
        if (name != null) {
            for (final Utils util : Utils.values()) {
                if (util.getName().equals(name)) {
                    return util;
                }
            }
        }
        return null;
    }

}

要使用枚举集合,应使用EnumSet或EnumMap。然后您可以执行以下操作:

public static void main(final String[] args) {
    final String utilName = "Utils_1";
    final Utils utilFromModule = Utils.of(utilName);

    final Set<Utils> utils = EnumSet.of(Utils.UTIL_1, Utils.UTIL_2);
    utils.contains(utilFromModule);
}