【问题标题】:Mapping specific strings to constant integers?将特定字符串映射到常量整数?
【发布时间】:2010-11-09 21:05:12
【问题描述】:

给定一组特定的字符串,将它们映射到相应的整数组的最佳方法是什么?假设我有一个包含一些我在内部使用的整数常量的类,但需要获取传入的外部字符串并确定它们映射到的正确对应的整数常量。

这是一个简化的例子:

public class Example {
    public static final int ITEM_APPLE = 0;
    public static final int ITEM_BANANA = 1;
    public static final int ITEM_GRAPE = 3;

    public void incomingData(String value) {
        // Possible values would be "apple", "banana", and "grape" in this case.
    }
}

从那个值到对应的整数常量最合适的方法是什么?哈希表?或者有什么方法可以在静态成员中定义这些映射?另一个想法?

【问题讨论】:

    标签: java string integer constants


    【解决方案1】:

    我会使用HashMap,因为它最接近您想要实现的目标,因此是可维护的解决方案。你可以定义一个静态的HashMap:

    Class Example {
        public static final int ITEM_APPLE = 0;
        public static final int ITEM_BANANA = 1;
        public static final int ITEM_GRAPE = 3;
    
        private static final Map<String, Integer> fruitCodes = new HashMap<String, Integer>();
    
        static {
            fruitCodes.put("apple", ITEM_APPLE);
            fruitCodes.put("banana", ITEM_BANANA);
            // ...
        }
    
    
        public void incomingData(String value) {
            // Possible values would be "apple", "banana", and "grape" in this case.
            Integer code = fruitCodes(value);
    
            if (null == code) {
                throw new IllegalArgumentException("Forbidden fruit: " + value);
            }
        }
    }
    

    【讨论】:

    • 我接受这个答案,因为它为我的特殊情况提供了最佳解决方案。所有其他有效答案至少会得到我的支持。
    【解决方案2】:

    是的,使用enum。您可以为每个枚举分配一个整数值,或者只使用ordinal()

    public enum ExampleEnum {
        ITEM_APPLE(0), ITEM_BANANA(1), ITEM_GRAPE(3);
    
        private final int intValue;
    
        private ExampleEnum (int intValue) {
          this.intValue = intValue;
        }
    
        public int intValue() {
          return intValue;
        }
    }
    

    然后使用例如ExampleEnum.valueOf("ITEM_APPLE").intValue() 将 String 解析为 int。

    如果 int 值是连续的并且从零开始,您可以完全去掉 intValue 字段:

    public enum ExampleEnum {
        ITEM_APPLE, ITEM_BANANA, ITEM_GRAPE;
    }
    

    只需使用ExampleEnum.valueOf("ITEM_APPLE").ordinal()

    【讨论】:

    • 但是给出我的例子,如果给定字符串“apple”,我怎么能得到 Example.ITEM_APPLE?
    • 或者为了更好地说明,如果我有“4pple”作为值并且知道它对应于ITEM_APPLE怎么办?我该如何翻译?
    • @Wilco:最简单的选择是为枚举常量赋予与您要使用的字符串相同的名称。或者,将"apple" 字符串作为另一个构造函数参数传递,并将其保存在字符串值到枚举值的静态Map。不过,这开始变得很麻烦。
    【解决方案3】:

    你“可以”使用反射,例如:

    Example.class.getField("ITEM_" + input.toUpperCase()).getInt(null);
    

    但是,您应该考虑使用枚举,或者如果没有太多可能性,只需使用一组 else if 语句...

    【讨论】:

    • 有道理,但您对“可能”部分是正确的。此外,在我的情况下,传入的字符串不能总是直接映射常量的结尾部分(即“ITEM_”+字符串)(更多地认为这是巧合)
    • 那么您将不得不编写一些自定义映射逻辑。您可以建立可能性的哈希值,或者测试名称范围以了解它们与输入的匹配程度等......很多选择,没有一个是 100% 正确的。
    【解决方案4】:

    我还建议使用 Enum 方法,尽管 ExampleEnum.valueOf("ITEM_APPLE").ordinal() 必须进行字符串比较才能得到答案,而 HashMap 会给您带来 O(1) 复杂度。

    可能是一个危险的想法,但只是为了好玩(怎么样):

    class Example {
        public static final int ITEM_APPLE = "apple".hashCode();
        public static final int ITEM_BANANA = "banana".hashCode();
        public static final int ITEM_GRAPE = "grape".hashCode();
    
        public int incomingData(String value) {
            return value.hashCode();
        }
    
        public static void main(String[] args) {
            Example x = new Example();
            if (ITEM_APPLE == x.incomingData("apple"))
                System.out.println("ITEM_APPLE");
        }
        }
    }
    

    您只需要确保字符串值的哈希码不会冲突 ;-)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-08-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多