【问题标题】:Mapping a set of strings to a specific key value将一组字符串映射到特定的键值
【发布时间】:2017-03-11 05:19:55
【问题描述】:

假设我有 3 组字符串值:

水果:苹果、浆果、香蕉

颜色:红、蓝、橙

交通工具:汽车、飞机、卡车

我正在寻找使用 Java 检索每个集合的父值的最有效方法,例如:

getParentValue("banana") ---> 水果

解决方案 1:

创建一堆 if/else 语句或 switch case:

if (fruitSet.contains(elem)) {
   return "fruit";
}
else if (colorSet.contains(elem)) {
   return "color";
} ...

这会产生 O(n) 查找,n 是集合的数量。

解决方案 2:

创建一个将每个子项存储到父项值的哈希图,

Key/Value:

apple/fruit
berry/fruit
banana/fruit
red/color
blue/color
orange/color
...

这会产生 O(1) 的查找时间,但会在存储每个键时生成一个大的哈希映射 - 出于某种原因,这种解决方案感觉很难看。

我正在寻找一些可能更优雅的意见或其他方法。

【问题讨论】:

  • 哈希图中的键数将等于所有集合中的元素数组合(来自解决方案 1)

标签: java algorithm


【解决方案1】:

最好的方法绝对是您的解决方案#2:如果您希望能够查找给定成员的类别,那么最有效的方法是从成员到类别的Map。这正是Map 的用途。

(请注意,无论您采用何种方法,您都必须存储所有成员。将它们作为键存储并不比以某种效率较低的方式存储它们更难看。)

【讨论】:

    【解决方案2】:

    这是一些在 Map 中只有 3 个条目的代码。

    public static void main(String[] args) {
        Map<String, List<String>> myMap = new HashMap<>();
        myMap.put("fruit", new ArrayList<String>(Arrays.asList("apple","berry","banana")));
        myMap.put("color", new ArrayList<String>(Arrays.asList("red","blue","orange")));
        myMap.put("vehicle", new ArrayList<String>(Arrays.asList("car","plane","truck")));
        System.out.println(getKey(myMap, "blue"));
    }
    
    public static String getKey(Map<String, List<String>> map, String value) {
        for (String key : (Set<String>)map.keySet()) {
            List<String> list = map.get(key);
            if (list.contains(value)) {
                return key;
            }
        }
        return null;
    }
    

    【讨论】:

      【解决方案3】:

      Hashmap 的想法很好,但是如果你想进一步改进,你可以将每个对象设置为一个整数并将其存储在一个数组中。如果您有一些名称很长的类别,那就太好了。

      例如,

      something1/very very long string
      something2/very very long string
      

      转换后:

      apple/0
      berry/0
      banana/0
      red/1
      blue/1
      orange/1
      ...
      something1/i
      something2/i
      

      你的数组将是:

      arr = {"fruit", "color", ....., "very very long string", ....};
      

      除非您的列表中有这么多条目(数千万或数百万)具有非常长的字符串类别,否则不值得。

      例如,您的平均字符串大小是 16 个字符,而您有一百万个不同的行,这意味着只有 16 MB,这对于现代计算机来说不算什么,而您只节省了 12MB,因为整数是 4B。

      【讨论】:

      • 这不是一个好主意。字符串是 Java 中的一种引用类型,因此如果您想避免存储许多 "very very long string" 的副本,您可以通过存储对同一个 String 实例的许多引用来轻松解决这个问题。没有理由求助于您自己的参考表。除了不必要地使代码复杂化之外,它实际上增加了所需的内存量。
      • @ruakh,你会怎么做?就像哈希图中的String s1 = "very very long string"something1 / s1
      • 这取决于您如何构建地图。例如,如果值都是硬编码的,那么string interning 将自动发生。但无论您如何构建地图,如果重要的话,重用字符串实例从来都不是难事。在任何情况下,存储数组索引都更容易。
      猜你喜欢
      • 1970-01-01
      • 2017-10-27
      • 1970-01-01
      • 2012-01-23
      • 2012-08-21
      • 2011-01-18
      • 2019-11-10
      • 2021-11-15
      • 1970-01-01
      相关资源
      最近更新 更多