Reputation: 2036
I have an enum FileType
public static enum FileType {
CSV, XML, XLS, TXT, FIXED_LENGTH
}
FileType fileType = FileType.CSV;
Is there a better (cleaner) way to check fileType
for multiple values than the following (like "myString".matches("a|b|c");
)?
if(fileType == FileType.CSV || fileType == FileType.TXT || fileType == FileType.FIXED_LENGTH) {}
Upvotes: 15
Views: 17791
Reputation: 401
You can write your own generic utility class for this purpose:
public final class EnumUtils {
/**
* Returns true if the given test enum is equal to any of the given search enums.
*/
static public <T> boolean equalsAny(T testEnum, T... searchEnums) {
for (T searchEnum : searchEnums) {
if (testEnum == searchEnum) {
return true;
}
}
return false;
}
}
Use it like this:
MyEnum x = ...;
if (EnumUtils.equalsAny(x, MyEnum.OPTION_A, MyEnum.OPTION_B, MyEnum.OPTION_C)) {
...
}
Upvotes: 0
Reputation: 62864
Why not use a switch
:
switch(fileType) {
case CSV:
case TXT:
case FIXED_LENGTH:
doSomething();
break;
}
This does the same as your if statement check, but it's more readable, imho.
But the problem with this code is not the switch
or the if/else
statement(s). The problem is that it breaks the Open-closed principle.
In order to fix that, I would completely remove the enum
and create an interface:
interface FileType {
boolean isInteresting();
}
Then, for each enum constant we used to have, I would create a separate interface implementation:
public class Txt implements FileType {
@Override
public boolean isInteresting() {
return false;
}
}
How does the switch
statement change? We used to pass a fileType
parameter, on which we checked the value. Now, we will pass an instance of FileType
.
public void method(FileType fileType) {
if (fileType.isInteresting()) {
doSomething();
}
}
The advantage of this is that when you introduce a new FileType
(which you would introduce as a new enum constant), you don't have to modify the switch
/if/else
statement to handle the case when this new file type is interesting or not. The code will simply work here without modification, which is the essence of the Open-closed principle: "Open for extensions, closed for modifications".
Upvotes: 16
Reputation: 59113
Option 1: Add a boolean field to your enum.
public static enum FileType {
CSV(true), XML(false), XLS(false), TXT(true), FIXED_LENGTH(true);
private final boolean interesting;
FileType(boolean interesting) {
this.interesting = interesting;
}
public boolean isInteresting() {
return this.interesting;
}
}
...
if (fileType!=null && fileType.isInteresting()) {
...
}
Option 2: use an EnumSet
.
EnumSets
use bitfields under the hood, so they are very fast and low memory.
Set<FileType> interestingFileTypes = EnumSet.of(FileType.CSV, FileType.TXT, FileType.FIXED_LENGTH);
...
if (interestingFileTypes.contains(fileType)) {
...
}
Option 3: use a switch
, as kocko suggests
Upvotes: 31
Reputation: 2347
Adding a different example:
public class JavaApplication {
public enum CustomerStatus {
ACTIVE("Active"),
DISCONNECTED("Disconnected"),
PENDING("Pending"),
CANCELLED("cancelled"),
NEW("new");
}
public static void main(String[] args) {
EnumSet<CustomerStatus> setA = EnumSet.of(CustomerStatus.ACTIVE, CustomerStatus.NEW);
EnumSet<CustomerStatus> setB = EnumSet.of(CustomerStatus.PENDING, CustomerStatus.CANCELLED);
if (setA.contains(CustomerStatus.ACTIVE)) {
System.out.println("ACTIVE : customer active");
}
if (setB.contains(CustomerStatus.ACTIVE)) {
System.out.println("ACTIVE: Customer is no longer active");
}
if (setB.contains(CustomerStatus.CANCELLED) {
System.out.println("CANCELLED: Customer is no longer active");
}
}
}
**Output**:
ACTIVE : customer active
CANCELLED: Customer is no longer active
Upvotes: -1
Reputation: 2036
I ended up writing a method:
public static enum FileType {
CSV, XML, XLS, TXT, FIXED_LENGTH;
// Java < 8
public boolean in(FileType... fileTypes) {
for(FileType fileType : fileTypes) {
if(this == fileType) {
return true;
}
}
return false;
}
// Java 8
public boolean in(FileType... fileTypes) {
return Arrays.stream(fileTypes).anyMatch(fileType -> fileType == this);
}
}
And then:
if(fileType.in(FileType.CSV, FileType.TXT, FileType.FIXED_LENGTH)) {}
Nice and clean!
Upvotes: 10