【问题标题】:How to put string items in a map of enums of enums of enums of String?如何将字符串项放在字符串枚举的枚举映射中?
【发布时间】:2011-05-30 00:39:06
【问题描述】:

我想创建一个字符串数组(枚举)的数组(枚举)数组(枚举)。我认为在 Java 中不可能实现这一点,但我听说过 EnumMap。

public class Tricky {

    public enum enumA { A1, A2, A3 };
    public enum enumB { B1, B2, B3 };
    public enum enumC { C1, C2, C3 };

    HashMap<EnumMap<enumA, EnumMap<enumB, enumC>>,String> item
        = new HashMap<EnumMap<enumA, EnumMap<enumB, enumC>>,String>();

    public Tricky() {

        // How do I put and get strings in my hash map?


    }
}

上面的代码可以编译,但是如何在我的地图中放置和获取字符串项?

【问题讨论】:

  • 你有什么可能的理由想要这样做?当 Enums 是键而其他东西是值时,EnumMap 只是一个非常快速、高效的 Map 实现。
  • 您是否尝试将三组值(enumAenumBenumC 各一个)映射到字符串?
  • @Ted Hopp 是的,我的想法是我想通过提供 enumA、enumB 和 enumC 来检索我的字符串。

标签: java enums map enum-map


【解决方案1】:

不应该是EnumMap&lt;EnumA, EnumMap&lt;EnumB, EnumMap&lt;EnumC, String&gt;&gt;&gt; 吗?在这种情况下,你会做

EnumMap<...> enumMapC = new EnumMap<...>();
enumMapC.put(EnumC.VALUE, "SomeString");
EnumMap<...> enumMapB = new EnumMap<...>();
enumMapB.put(EnumB.VALUE, enumMapC);
EnumMap<...> enumMapA = new EnumMap<...>();
enumMapA.put(EnumA.VALUE, enumMapB);

虽然我建议您使用好的 IDE 来编写代码。您可能需要考虑创建一些类而不是直接使用 EnumMap 以使其更易于管理。

如果您使用数组中的所有位置,您可能希望使用枚举的序数值作为普通数组的索引。

【讨论】:

    【解决方案2】:

    您可能会发现这很有用:

    package p;
    enum enumA {
        A1,A2,A3;
    }
    enum enumB {
        B1,B2,B3;
    }
    enum enumC {
        C1,C2,C3;
    }
    class MyArray{
        MyArray(Class<? extends Enum> e1,Class<? extends Enum> e2,Class<? extends Enum> e3) {
            strings=new String[e1.getEnumConstants().length][e1.getEnumConstants().length][e2.getEnumConstants().length];
            e3.getEnumConstants();
        }
        void set(enumA a,enumB b,enumC c,String string) {
            strings[a.ordinal()][b.ordinal()][c.ordinal()]=string;
        }
        String get(enumA a,enumB b,enumC c) {
            return strings[a.ordinal()][b.ordinal()][c.ordinal()];
        }
        public String toString() {
            StringBuffer sb=new StringBuffer();
            for(enumA a:enumA.values())
                for(enumB b:enumB.values()) {
                    for(enumC c:enumC.values()) {
                        sb.append(get(a,b,c));
                        sb.append('\n');
                    }
                    sb.append('\n');
                }
            return sb.toString();
        }
        public static void main(String[] arguments) {
            MyArray myArray=new MyArray(enumA.class,enumB.class,enumC.class);
            for(enumA a:enumA.values())
                for(enumB b:enumB.values())
                    for(enumC c:enumC.values())
                        myArray.set(a,b,c,""+a+b+c);
            System.out.println(myArray);
        }
        final String[][][] strings;
    }
    

    【讨论】:

    • 这个有一个bug,修复是:strings=new String[e1.getEnumConstants().length][e2.getEnumConstants().length][e3.getEnumConstants().length];跨度>
    【解决方案3】:

    公共类 Tricky {

    public enum enumA { A1, A2, A3 };
    public enum enumB { B1, B2, B3 };
    public enum enumC { C1, C2, C3 };
    
    HashMap<Object[],String> item = new HashMap<Object[],String>();
    
    public Tricky() {
        item.put(new Object[] {enumA.A1, enumB.B2, enumC.C3}, "A1_B2_C3 string");
        String oops = item.get(new Object[] {enumA.A2, enumB.B3, enumC.C1});
    }
    

    }

    那是相当丑陋的代码。为了清理它(并提供一些类型安全),您可以定义自己的类来保存三个枚举,每个枚举类型一个,并定义其hashcodeequals 方法。您可能还会发现方法Arrays.hashcode(Object[]) 很有用。

    【讨论】:

    • 这确实是个好主意...谢谢!
    【解决方案4】:

    好的,这是基于@owlstead 提出的建议的解决方案。它有效:

    public class Tricky {
    
        public enum enumA { A1, A2, A3 };
        public enum enumB { B1, B2, B3 };
        public enum enumC { C1, C2, C3 };
    
        static EnumMap<enumA,EnumMap<enumB,EnumMap<enumC,String>>> items;
    
        public static void main(String[] args) {
    
            // Creating my array (enum) of array (enum) of array (enum) of strings
            items = new EnumMap<enumA,
                            EnumMap<enumB,
                                EnumMap<enumC,String>>>(
                                    enumA.class);
    
            // We need to add entries
            for (enumA itemA : enumA.values() ) {
    
                EnumMap<enumB,
                    EnumMap<enumC,String>> itemsB =
                        new EnumMap<enumB,
                            EnumMap<enumC,String>>(enumB.class);
    
                // And sub-entries...
                for (enumB itemB : enumB.values())
                    itemsB.put(itemB, new EnumMap<enumC,String>(enumC.class));
    
                items.put(itemA, itemsB);
    
            }
    
            // Putting a value
            items.get(enumA.A2).get(enumB.B3).put(enumC.C1, "MyValue");
    
            // Retrieving a value
            String retr = items.get(enumA.A2).get(enumB.B3).get(enumC.C1);
            String retr2 = items.get(enumA.A3).get(enumB.B3).get(enumC.C2);
    
            System.out.println(retr);
            System.out.println(retr2);
    
        }
    
    }
    

    【讨论】:

    • 我醒来时正在考虑这个问题,我想你可能想创建一个不可变的类来保存一个字段中所有三个枚举的值,写一个好的 equals() 和 hash()方法,然后将该类用作 HashMap 中的键。但这只是一个提示,不能直接回答您的问题。
    • @owlstead 你的建议确实是一个解决方案,但它会引入一个额外的类。我终于实现了类似于雷的提议的东西。它是相同功能的更简单的代码。谢谢。
    【解决方案5】:

    我认为您还没有理解 Java 中的枚举概念;它就像任何其他类型一样。如果必须,可以将其视为一个类,因为 Java 中的所有枚举都扩展 java.lang.Enum。因此,您可以组成枚举数组(或至少它们的值/常量,如果您是这个意思)。看看下面的例子:

    package com.example;
    
    public class Enumerations {
    
        public enum enumA { A1, A2, A3 };
        public enum enumB { B1, B2, B3 };
        public enum enumC { C1, C2, C3 };
    
        private void test() {
            Enumerations.enumA[] enumerations = new Enumerations.enumA[3];
            enumerations[0] = enumA.A1;
            enumerations[1] = enumA.A2;
            enumerations[2] = enumA.A3;
        }
    }
    

    如果您的意思是这样,您不能将枚举与数组中的其他类型混合。换句话说,您不能创建具有不同类型的多维数组:数组的类型与声明中指定的类型相同;这样,声明为包含枚举的数组不能包含字符串,即使它是多维的。因此,下面的 sn-p 是非法的:

    package com.example;
    
    public class Enumerations {
    
        public enum enumA { A1, A2, A3 };
        public enum enumB { B1, B2, B3 };
        public enum enumC { C1, C2, C3 };
    
        private void test() {
            Enumerations.enumA[][] enumerations = new Enumerations.enumA[3][];
            enumerations[0][1] = enumA.A1; //legal
            enumerations[0][2] = enumB.B1; //illegal since enumB is a different type
        }
    

    就您最初的问题而言,使用键为枚举的 EnumMap 按以下方式完成:

    private void createAndStoreEnum() {
            EnumMap<Enumerations.enumA, String> aMap = new EnumMap<Enumerations.enumA, String>(enumA.class);
            aMap.put(enumA.A1, "Example");
    }
    

    使用的 EnumMap 构造函数需要将类型(用作键的枚举)作为参数传入。然后可以像使用任何其他地图一样使用标准的 put 和 get 语义。

    【讨论】:

    • 我想要实现的是一种数组或数组等...的枚举来访问一个字符串。这不是 1 级枚举。它是一个多级枚举。可能这是不可能的......
    • @JVerstry,我想我在一定程度上理解了你的问题。我已经编辑了我的答案,以说明为什么数组在这里没有帮助。我认为您需要使用枚举映射。希望 sn-p 可以帮助您入门。
    • @JVerstry,我在问题中查看了您的代码。您如何尝试将多级枚举映射到字符串?我认为使用包含 EnumMaps 的 HashMap 将是朝着错误方向迈出的一步。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-11-09
    • 2019-01-29
    • 1970-01-01
    • 2017-12-06
    • 2012-01-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多