Checking if a String is contained in an Enum Set in O(1)

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP


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 limitin 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





That's an interesting read, thanks.
– Bitswazsky
4 hours ago



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.

Popular posts from this blog

Makefile test if variable is not empty

Will Oldham

Visual Studio Code: How to configure includePath for better IntelliSense results