在java中用较少的代码将枚举映射到另一个枚举



我有两个enum类,一个是外部的,另一个是内部的。

public enum ExternalEnum
{
EXTERNAL_CAR, EXTERNAL_VAN, EXTERNAL_BUS
}

public enum InternalEnum
{
CAR, VAN, BUS
}

我需要将内部映射到外部,外部映射到内部。所以我做了如下操作,

public class EnumMapper
{
public ExternalEnum toExternal(InternalEnum internalEnum)
{
switch (internalEnum)
{
case BUS:
return ExternalEnum.EXTERNAL_BUS;
case CAR:
return ExternalEnum.EXTERNAL_CAR;
case VAN:
return ExternalEnum.EXTERNAL_VAN;
}
return null;
}
public InternalEnum toInternal(ExternalEnum externalEnum)
{
switch (externalEnum)
{
case EXTERNAL_BUS:
return InternalEnum.BUS;
case EXTERNAL_CAR:
return InternalEnum.CAR;
case EXTERNAL_VAN:
return InternalEnum.VAN;
}
return null;
}
}

同样的映射在两种方法中重复。难道没有一种用更少的代码实现这一目标的好方法吗?

br

InternalEnum.values()[ externalEnum.ordinal() ]
<标题>

详细信息假设等价的枚举对象以相同的顺序声明,我们可以通过访问调用隐式public static T[] values()方法返回的所有枚举对象的数组来从另一个枚举对象中检索一个枚举对象,并通过从错误命名的Enum#ordinal方法检索到的从零开始的索引号来检索。

例如,InternalEnum.values()返回一个数组,其中包含所有enum对象,按照声明顺序排列。然后,我们使用数组访问器[…]来检索与另一个enum中同伴的索引号匹配的对象。

InternalEnum internalEnum = InternalEnum.values()[ externalEnum.ordinal() ] ;

,反之亦然:

ExternalEnum externalEnum = ExternalEnum.values()[ internalEnum.ordinal() ] ;

下面是用法示例。额外提示:在Java 16+中,我们可以在本地声明一个enum——参见JEP 395: Records

enum ExternalEnum { EXTERNAL_CAR, EXTERNAL_VAN, EXTERNAL_BUS }
enum InternalEnum { CAR, VAN, BUS }
System.out.println(
InternalEnum.values()[ ExternalEnum.EXTERNAL_VAN.ordinal() ]
);
System.out.println(
ExternalEnum.values()[ InternalEnum.VAN.ordinal() ]
);

货车

EXTERNAL_VAN

来自Basil Bourque的回答是好的,但我不喜欢使用ordinal(),因为你可以很容易地旋转enum常数和业务逻辑将被打破。

你几乎是正确的,只要记住,enum常量是一个普通的旧javaclass实例,它可以用额外的功能进行扩展。因此,最好将所有映射器逻辑隐藏在enum中。

public enum ExternalEnum {
EXTERNAL_CAR,
EXTERNAL_VAN,
EXTERNAL_BUS
}
public enum InternalEnum {
CAR(ExternalEnum.EXTERNAL_CAR),
VAN(ExternalEnum.EXTERNAL_VAN),
BUS(ExternalEnum.EXTERNAL_BUS);
private final ExternalEnum externalEnum;
InternalEnum(ExternalEnum externalEnum) {
this.externalEnum = externalEnum;
}
public ExternalEnum toExternal() {
return externalEnum;
}
public static Optional<InternalEnum> parseExternal(ExternalEnum externalEnum) {
for (InternalEnum internalEnum : values())
if (internalEnum.externalEnum == externalEnum)
return Optional.of(internalEnum);
return Optional.empty();
}
}

ExternalEnum externalEnum = ExternalEnum.EXTERNAL_CAR;
Optional<InternalEnum> optInternalEnum = InternalEnum.parseExternal(externalEnum);
System.out.println(externalEnum);
System.out.println(optInternalEnum.orElse(null));
System.out.println(optInternalEnum.map(InternalEnum::toExternal).orElse(null));

另一种选择是只有Mapper

public final class EnumMapper {

private final Map<ExternalEnum, InternalEnum> MAP_EXT_INT = Map.of(
ExternalEnum.EXTERNAL_CAR, InternalEnum.CAR,
ExternalEnum.EXTERNAL_VAN, InternalEnum.VAN,
ExternalEnum.EXTERNAL_BUS, InternalEnum.BUS);

private final Map<InternalEnum, ExternalEnum> MAP_INT_EXT = Map.of(
InternalEnum.CAR, ExternalEnum.EXTERNAL_CAR,
InternalEnum.VAN, ExternalEnum.EXTERNAL_VAN,
InternalEnum.BUS, ExternalEnum.EXTERNAL_BUS);

public static ExternalEnum toExternal(InternalEnum internalEnum) {
return MAP_INT_EXT.get(internalEnum);
}

public InternalEnum toInternal(ExternalEnum externalEnum) {
return MAP_EXT_INT.get(externalEnum);
}

private EnumMapper() {}
}
public enum ExternalEnum {
EXTERNAL_CAR,
EXTERNAL_VAN,
EXTERNAL_BUS
}
public enum InternalEnum {
CAR,
VAN,
BUS;
}

我可以通过使用BiMap和更少的代码来实现这一点。

import com.google.common.collect.EnumBiMap;
public class EnumBiMapMapper
{
private EnumBiMap<InternalEnum, ExternalEnum> enumEnumBiMap = EnumBiMap.create(InternalEnum.class, ExternalEnum.class);
public EnumBiMapMapper()
{
enumEnumBiMap.put(InternalEnum.BUS, ExternalEnum.EXTERNAL_BUS);
enumEnumBiMap.put(InternalEnum.CAR, ExternalEnum.EXTERNAL_CAR);
enumEnumBiMap.put(InternalEnum.VAN, ExternalEnum.EXTERNAL_VAN);
}
public ExternalEnum toExternal(InternalEnum internalEnum)
{
return enumEnumBiMap.get(internalEnum);
}
public InternalEnum toInternal(ExternalEnum externalEnum)
{
return enumEnumBiMap.inverse().get(externalEnum);
}
}

最新更新