Checking if a String is contained in an Enum Set in O(1)
Checking if a String is contained in an Enum Set in O(1)
Let's say I have an enum like the following:
public enum Utils {
UTIL_1, UTIL_2, ... UTIL_n
}
Now, I have Set<Utils> myUtils
, which contains a bunch of these enum entries. Some other module (on which I don't have any control) gives me one such util name (say "UTIL_i
") as a String. I need to check if it is contained in the set myUtils
. Is there any way to perform this operation in O(1)? I understand, I could change the set to be a set of Strings, and then do a .contains() on that, but I want to keep it as a last resort.
Set<Utils> myUtils
UTIL_i
myUtils
Update:
Following the suggestions in the answer, I tried a little experiment. I created a small code snippet to generate a java file which is an enum of a fixed size. I tried with size 1000, 2500, 5000. An enum of size 10000 showed me the error The code for the static initializer is exceeding the 65535 bytes limit
in Eclipse, which is explained here. I created a Set myUtils
and pushed all the elements from the Enum to that set. For each of these different size myUtils
I executed a snippet 1000 times, which looks like myUtils.contains(Utils.valueOf(<elementName>))
. The average execution time of that code snippet in ms is given below:
The code for the static initializer is exceeding the 65535 bytes limit
myUtils
myUtils
myUtils.contains(Utils.valueOf(<elementName>))
Enum size=1000
UTIL_1 search duration = 1704ms
UTIL_500 search duration = 2316ms
UTIL_1000 search duration = 1732ms
Enum size=2500
UTIL_1 search duration = 2326ms
UTIL_1250 search duration = 1886ms
UTIL_2500 search duration = 1860ms
Enum size=5000
UTIL_1 search duration = 2569ms
UTIL_2500 search duration = 2709ms
UTIL_5000 search duration = 2361ms
It clearly shows the average execution time of Enum.valueOf(String element)
increases with the size of the enum, but I'm not sure of the running time complexity of this method.
Enum.valueOf(String element)
3 Answers
3
One of the choices is to use the valueOf
method of enum
but it's time complexity depends on the input which you'll be using.
valueOf
enum
If most of your inputs are nonconvertible to Utils
enum then making a set
and using contains
method is best approach as valueOf
method doesn't work well with values which are nonconvertible.
Utils
set
contains
valueOf
References:
Java enum valueOf efficiency
You can turn the String into an actual Utils
member via Utils util = Utils.valueOf(String)
, and then check if it is contained in the set via myUtils.contains(util)
which AFAIK is a O(1) operation.
Utils
Utils util = Utils.valueOf(String)
myUtils.contains(util)
Of course you should check for exceptions in case the String you got doesn't actually correspond to any Utils
. In your example, it wouldn't, because it should be in uppercase like the enum names.
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
}
Ah, thanks. That "Utils_1" was an overlook on my end, I intended it to be in uppercase. I'll edit my question to reflect that.
– Bitswazsky
4 hours ago
I recommend you to extend your Enum to add the string identifier from the other module. Also, I will write a method to translate a String to a Util enum.
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;
}
}
To work with Collections of Enums you should use EnumSet or EnumMap. Then you can do something like this:
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);
}
I've updated my question to reflect a minor modification. In this case, I think the operation is O(n), because of the for loop.
– Bitswazsky
4 hours ago
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
That's an interesting read, thanks.
– Bitswazsky
4 hours ago