Method getContinent()
expects a String
as an argument which can have three possible values: "Africa"
, "Asia"
and "Europe"
.
Depending on the given value I get, I have to match the appropriate enum
and get a list of all its values (as String).
There are repetitions in my code.
Is there a better way to do it?
Is it a good idea to place this in each of the enum
's?:
Stream.of(CountryAsia.values())
.map(country -> country.getName())
.collect(Collectors.toList());
My code
Main
class:
public class Main {
public static void main(String[] args) {
String continent = getContinent() //one of three possible values: "Africa" or "Asia" or "Europe"
List<String> list = null;
switch(continent) {
case "Africa":
list = Stream.of(CountryAfrica.values())
.map(country -> country.getName())
.collect(Collectors.toList());
break;
case "Asia":
list = Stream.of(CountryAsia.values())
.map(country -> country.getName())
.collect(Collectors.toList());
break;
case "Europe":
list = Stream.of(CountryEurope.values())
.map(country -> country.getName())
.collect(Collectors.toList());
break;
}
System.out.println(list);
//next instructions..
}
}
CountryEurope
enum:
public enum CountryEurope {
DENMARK("Denmark"),
ESTONIA("Estonia"),
ICELAND("Iceland");
CountryEurope(String name) {
this.name = name;
}
private final String name;
public String getName() {
return name;
}
}
CountryAsia
enum:
public enum CountryAsia {
AFGHANISTAN("Afghanistan"),
KAZAKHSTAN("Kazakhstan"),
UNITED_ARAB_EMIRATES("United Arab Emirates"),
UZBEKISTAN("Uzbekistan");
CountryAsia(String name) {
this.name = name;
}
private final String name;
public String getName() {
return name;
}
}
CountryAfrica
class:
public enum CountryAfrica {
ALGIERIA("Algeria"),
WESTERN_SAHARA("Western Sahara"),
EGYPT("Egypt");
CountryAfrica(String name) {
this.name = name;
}
private final String name;
public String getName() {
return name;
}
}
CodePudding user response:
You can make use EnumSet.allOf()
in order to get the names of your enum
constants.
EnumSet.allOf()
expects a Class<T>
of enum
as an argument and returns an EnumSet
of its elements (which is special implementation of the Set
designed exclusivelly for enum
s).
Then we can transform a Set
of enum
constants into a list of strings either by using a stream or a plain for
loop.
And if you are using Java 14 , you cane utilize switch expressions. Otherwise, replace the repeating stream statement with a method call.
In order to access the method getName()
with every enum
we can define an interface which all of them will implement.
public interface CountryData {
String getName();
}
Also, it could contain some other methods related to the domain-specific information that could be useful in your application like country area or locale tax rates.
Combining all mentioned above will give a very concise and expressive code:
public static List<String> getCountries(String continent) {
return switch(continent) {
case "Africa" -> getEnumNames(CountryAfrica.class);
case "Asia" -> getEnumNames(CountryAsia.class);
case "Europe" -> getEnumNames(CountryEurope.class);
default -> Collections.emptyList();
};
}
public static <T extends Enum<T> & CountryData> List<String> getEnumNames(Class<T> enumClas) {
return EnumSet.allOf(enumClas).stream()
.map(CountryData::getName)
.collect(Collectors.toList());
}
main()
public static void main(String[] args) {
System.out.println(getCountries("Europe"));
System.out.println(getCountries("Africa"));
System.out.println(getCountries("Asia"));
}
Output
[Denmark, Estonia, Iceland]
[Algeria, Western Sahara, Egypt]
[Afghanistan, Kazakhstan, United Arab Emirates, Uzbekistan]
Is it a good idea to place this in each of the enum's?
No, it's not because:
- the code it will not eliminate the duplication, the same lines will be scattered across multiple files;
- this code ins't specific to any of your
enum
s therefore it must reside in one place (in a class that is meant to process this list).
CodePudding user response:
Looks like you try to store some collection of data inside enum that is a bit wrong IMHO. I would prefer to provide a map where the key is "continent" and the value is a collection of countries. Map<String, Set>.
Then, you don't need to use the switch, you can use Map#get().