【问题标题】:How to best convert Map<String,Foo> to Map<MyEnum,Foo> in a wrapper如何在包装器中最好地将 Map<String,Foo> 转换为 Map<MyEnum,Foo>
【发布时间】:2013-12-19 11:21:07
【问题描述】:

更新,添加来自 cmets 的问题:

将 Map 放入 Map where 的最佳方法是什么 Foo 是一个枚举。从概念上讲,它似乎非常复杂, 不是一个复杂的想法。

此代码起作用,它是简单MUD client 的一部分。基本思想是Monitor 保存数据(生命值等),这些数据将在游戏过程中显示给用户,可能在第二个JPanel 中;类似的东西。此报告的可能值在Attribs 中作为Enum

在走得太远之前,当我查看 Monitor 类以及创建单个实例所需的内容时,似乎有点冗长。

如果我将convertToEnumEntry 移出Monitor,那么课程将无法工作。所以,班级不能变小,我不认为。有没有我可以使用(或使用更好)的模式?

此类中的所有内容都基于这样的假设:如果convertToEnumEntry 返回一个对Map.Entry 的空引用,然后获取不适合Attribs 的特定String

enemy = stringEntry.getKey();

与其他键不同,敌人可以是任何String。其他键仅限于Attribs(属性)的Enum 值。

public class Monitor {

    private static Logger log = Logger.getLogger(Monitor.class.getName());
    private Map<Attribs, Ratio> mapOfAttributes = new HashMap<>();
    private String enemy = null;

    private Monitor() {
    }

    public Monitor(Map<String, Ratio> mapStringToRatio) {
        init(mapStringToRatio);
    }

    private void init(Map<String, Ratio> mapStringToRatio) {
        SimpleEntry<Attribs, Ratio> attribsEntry = null;
        for (Entry<String, Ratio> stringEntry : mapStringToRatio.entrySet()) {
            attribsEntry = null;
            attribsEntry = convertToEnumEntry(stringEntry);
            if (attribsEntry != null) {
                mapOfAttributes.put(attribsEntry.getKey(), attribsEntry.getValue());
            } else {
                enemy = stringEntry.getKey();     //assumes key is enemy value
                mapOfAttributes.put(Attribs.ENEMY, stringEntry.getValue());
            }
        }
    }

    private SimpleEntry<Attribs, Ratio> convertToEnumEntry(Entry<String, Ratio> stringEntry) {
        Ratio ratio = stringEntry.getValue();
        SimpleEntry<Attribs, Ratio> attribEntry = null;
        for (Attribs attribute : Attribs.values()) {
            if (stringEntry.getKey().equalsIgnoreCase(attribute.name())) {
                attribEntry = new HashMap.SimpleEntry<>(attribute, ratio);
            }
        }
        return attribEntry;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("\nfighting\t\t" + enemy + "\n");
        for (Map.Entry<Attribs, Ratio> e : mapOfAttributes.entrySet()) {
            sb.append("\n");
            sb.append(e.getKey().name());
            sb.append("\t");
            sb.append(e.getValue().toString());
        }
        sb.append("\n");
        return sb.toString();
    }
}

将所有内容都塞进任一类以解析和构建Map,或者将所有内容都放入Monitor 是很诱人的。目前,RegexMapBuilder 是一种中间立场,因为它完成了大部分艰苦的工作,但并不能完全独立地构建完整的 Monitor

public class RegexMapBuilder {

    public static Map<String, Ratio> stringToRatiosMap(String input) {
        Map<String, Ratio> mapOfStringsToRatios = new HashMap<>();
        Map<String, String> strings = stringMap(input);
        Pattern fraction = Pattern.compile("(\\d+)/(\\d+)");
        Pattern wholeNumber = Pattern.compile("(\\d+)");
        Pattern percent = Pattern.compile("(\\d+)%");
        Matcher matcher;
        int numerator, denominator;
        Ratio ratio = null;             //need numerator and denominator values
        for (Entry<String, String> e : strings.entrySet()) {
            matcher = wholeNumber.matcher(e.getValue());
            while (matcher.find()) {
                numerator = Integer.parseInt(matcher.group(1));
                denominator = 1;
                ratio = new Ratio(numerator, denominator);
            }
            matcher = fraction.matcher(e.getValue());
            while (matcher.find()) {
                numerator = Integer.parseInt(matcher.group(1));
                denominator = Integer.parseInt(matcher.group(2));
                ratio = new Ratio(numerator, denominator);
            }
            matcher = percent.matcher(e.getValue());
            while (matcher.find()) {
                numerator = Integer.parseInt(matcher.group(1));
                denominator = 100;
                ratio = new Ratio(numerator, denominator);
            }
            mapOfStringsToRatios.put(e.getKey(), ratio);
        }
        return mapOfStringsToRatios;
    }

    private static Map<String, String> stringMap(String input) {
        Map<String, String> strings = new HashMap<>();
        Pattern pattern = Pattern.compile("(\\w+): +(\\S+)");
        Matcher matcher = pattern.matcher(input);
        while (matcher.find()) {
            strings.put(matcher.group(1), matcher.group(2));
        }
        return strings;
    }
}

为简洁起见,我省略了Enum,但Attribs 只是此报告打印的一些属性的列表。唯一棘手的部分是有一个值不是真正的 Enum 类型。

【问题讨论】:

  • 你的问题是什么?
  • 将 Map 放入 Map 的最佳方法是什么,其中 Foo 是一个枚举。从概念上讲,这似乎不是一个复杂的想法。
  • 为什么不将Attribs attr = Attribs.valueOf(stringValue.toUpperCase()); 用于String -&gt; Attribs 算法?
  • stringValue 可能Attrib,但不一定。大约有五个Attrib 值,然后是第六个,它只是一个String,这个变量可以是任何东西。所以它几乎是,但不是,一个“枚举”。

标签: java design-patterns enums hashmap code-organization


【解决方案1】:

我认为java.util.EnumMap 可能是您正在寻找的。您可以使用Enum#valueOf 从给定的字符串中查找枚举值,就像 Sam Yonnou 提到的那样。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-30
    • 2013-11-08
    • 1970-01-01
    • 2021-11-27
    相关资源
    最近更新 更多