【问题标题】:In java, how can I work with objects which can be either String or List<String>? [duplicate]在 java 中,如何处理可以是 String 或 List<String> 的对象? [复制]
【发布时间】:2012-02-13 11:50:18
【问题描述】:

可能重复:
Maps with multiple types of values in java

我有一个奇怪的问题。也许我的做法是错误的,但让我们看看这个问题的去向:)

我想要一个包含字符串或字符串列表的地图容器。我想在构造这个对象的过程中强制执行这个规则,这样你就不能创建一个值不是其中任何一个的映射。

例如

class Record {
  public Record(String key, Map<String,Object> attrs) {
    // check that attrs only contains Objects which are Strings or List<Strings>
  }
}

我想到的其他解决问题的方法可能是......

1)

class Record {
  public Record(String key, Map<String,String> attrs, Map<String,List<String>> multiAttrs) {
    // ...
  }
}

2)

class Record {
  public Record(String key, Map<String,Value> attrs) {
    // ...
  }
}

class Value {
  // Create some funky class that encapsulates lists.
  // Perhaps returning the only element in the list if the size is 1,
  // but returning the list otherwise
}

我并没有立即对替代方案感到兴奋,但我只是把它作为我已经考虑过的东西放在那里。我真的希望 Strings 和 List 之间的区别对类的用户是透明的。

【问题讨论】:

  • 第三个想法是我能想到的最好的了。我还会按照 epoch 的建议查看来自 Guava 库的多图。

标签: java


【解决方案1】:

你考虑过ListMultimap吗?对于单值情况,列表将只有一个元素。 Multimap 允许将多个元素(值)映射到每个键。所以你的方法是:

public Record(String key, ListMultimap<String, String> attrs)...

此外,由于您的 Record 似乎是另一个映射,请考虑使用允许双键映射的 Table

【讨论】:

  • +1 也考虑到番石榴!
【解决方案2】:

查看来自 Google 的 ArrayListMultimap,这将有助于满足此需求

你可以继续在这个地图上调用put,如果你需要得到简化的地图你可以使用这个方法,或者修改它:)

public static Map<Field, String> toSingularMap(ArrayListMultimap<Field, String> map) {
    Map<Field, String> singular_map = new HashMap<Field, String>();
    if (map != null && !map.isEmpty()) {
        Map<Field, Collection<String>> real_map = map.asMap();
        for (Iterator<Entry<Field, Collection<String>>> it = real_map
                .entrySet().iterator(); it.hasNext();) {
            Entry<Field, Collection<String>> entry = it.next();
            Field field = entry.getKey();
            Collection<String> values = entry.getValue();

            String value = null;
            if (values != null && !values.isEmpty()) {
                ArrayList<String> list = new ArrayList<String>(values);
                value = list.get(0);
            }

            singular_map.put(field, value);
        }
    }

    return singular_map;
}

或者如果你不想使用额外的库,你可以创建一个简单的 Wrapper 类

class Wrap {
    String value;
    String[] values
}

并让您的地图使用Map&lt;String, Wrap&gt; map,然后在循环时您可以通过使用您的类方法或仅测试来确定填充了哪个包装器变量

【讨论】:

  • 我不明白这个方法。 Multimap 旨在允许每个键有多个值。此方法仅提取每个键的第一个值。如果是这样,为什么不使用Map
  • 我知道,我将这种方法用于尚未引入多映射的系统的旧部分,并且 API 需要一个正常的Map&lt;String, String&gt;(); 我只是把它放在这里以证明 OP 可以做同样的事情(使用单个地图或多地图),或者不:)。它只是展示了 Multimap 的基础知识 :)
【解决方案3】:

我只会使用List&lt;String&gt;。您可以添加一些方法来允许添加单个字符串并使用Arrays.asList(...) 包装传递的参数。仅使用单一类型的对象将减少要编写的代码量并避免许多if/else

【讨论】:

    【解决方案4】:

    为什么不创建一个类

    class MyFunkyValue{
    
    private String onlyOneString;
    private List<String> stringValues;
    
    public MyFunkyValue(String s){
    ...
    }
    
    public MyFunkyValue(List<String>ls){
    ...
    }
    }
    

    并像这样使用它:

    Map<KeyClass,MyFunkyValue> m;
    

    【讨论】:

    • 这与OptionalEither 结合使用可能会很好。
    猜你喜欢
    • 1970-01-01
    • 2012-06-22
    • 1970-01-01
    • 2011-03-29
    • 2012-11-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-04
    相关资源
    最近更新 更多