如何使用相同的键将枚举映射到枚举

时间:2020-04-27 11:00:13

标签: java enums mapping

如何使用Java中相同的键将枚举映射到枚举。 例如。

public enum FirstEnum {
 A, B
} 

public enum ScndEnum {
 A, B, C
} 

我找不到好的解决方法

2 个答案:

答案 0 :(得分:3)

您不能直接从一种枚举类型映射到另一种枚举类型,但是可以使用name()的值并使用valueOf()进行映射。这两种方法都随所有枚举类一起提供:

ScndEnum aToA = ScndEnum.valueOf(FirstEnum.A.name());

如果要使它通用:

private static <E extends Enum<E>, F extends Enum<F>> 
    F mapEnum(E enum1, Class<F> enum2Class) {

    return Enum.valueOf(enum2Class, enum1.name());
}

您可以使用类似的方式拨打电话

ScndEnum b = mapEnum(FirstEnum.B, ScndEnum.class)

答案 1 :(得分:2)

tl; dr

考虑到Java中的枚举定义,在枚举之间共享对象实际上没有任何意义。

也许为您提供的解决方案是一系列枚举,例如Mapkey-value pairs),其中键类型是一个枚举类,而值类型是另一个枚举类。

Map< Animal , Food > feeding = 
    Map.of
    (
        DOG , MEAT ,
        CAT , MEAT ,
        BIRD , SEED ,
        BAT , FRUIT
    )
;

枚举是数据类型

Java中的枚举是一个类,其实例在编译时命名,在运行时自动实例化,并且无法重新分配。参见tutorial by Oracle

示例:

enum Animal { DOG , CAT , BIRD , BAT ; }

enum Flavor { VANILLA , CHOCOLATE , LAVENDER , LEMON ; }

枚举中的每个名称都将分配一个对象,该对象是该枚举类的一个实例。在上面的示例中,DOG常量保存一个Animal对象,而LEMON常量保存一个Flavor对象。

当您拥有在编译时已知但在运行时未更改的特定实例实例时,在Java中使用枚举是有意义的。这意味着您不能在上面的示例中调用new Animal()。首次加载该类时,会自动实例化四个新的Animal对象并将其分配给每个变量名称。枚举类加载后,无法再实例化或丢弃Animal对象。

枚举之间没有共享

因此,鉴于枚举的定义,您的问题实际上没有任何意义。一个枚举的对象不与另一个枚举共享。

收藏

也许您正在寻找的是枚举对象的集合

Set

例如,在这里我们使用Set的实现,该实现针对保存枚举对象EnumSet进行了高度优化。

Set< Animal > furryPets = EnumSet.of( DOG , CAT ) ;
Set< Animal > flyingAnimals = EnumSet.of( BIRD , BAT ) ;
Set< Animal > featheredFlyingAnimals = flyingAnimals.clone().remove( BAT ) ;

Map

您提到要双向映射。因此,也许您想要的是Map来跟踪一个枚举作为键,而另一个枚举作为值。当您的键是枚举时,EnumMap类得到了高度优化。

作为示例,让我们添加另一个枚举。

enum Food { MEAT , SEED , FRUIT ; }

根据动物的食物类型对其进行映射。

Map< Animal , Food > feeding = new EnumMap<>( Animal.class ) ;
feeding.put( DOG , MEAT ) ;
feeding.put( CAT , MEAT ) ;
feeding.put( BIRD , SEED ) ;
feeding.put( BAT , FRUIT ) ;

获取要喂给蝙蝠的食物类型。

Food foodForBats = feeding.get( BAT ) ;

成员变量

Java中的枚举是一种特殊的类,但仍然是一个类。因此,枚举可以像常规Java类一样具有成员字段,构造函数和访问器方法。

因此,我们可以通过使用成员字段,构造函数和访问器方法将Animal与其Food关联起来。

enum Animal 
{
    DOG( Food.MEAT ) , 
    CAT( Food.MEAT ) , 
    BIRD( Food.SEED ) , 
    BAT( Food.FRUIT ) ;

    // Member fields.
    private Food food ;

    // Constructor.
    private Animal( Food foodArg ) 
    {
        this.food = foodArg ;
    }

    // Accessor "getter" method.
    public Food getFood() { return this.food ; }

}

如上所述,当Animal类加载时,其构造函数被调用四次,每个命名常量一次。指定的Food对象会自动代表您传递给该构造函数。您可以认为该行DOG( Food.MEAT ) ,public static final Animal DOG = new Animal( Food.MEAT) ;的缩写。

用法。

Food foodForBats = Animal.BAT.getFood() ;