【问题标题】:concatenate several enumerations?连接几个枚举?
【发布时间】:2011-11-30 21:57:25
【问题描述】:

由于我们的特殊需要,我不得不继承 ResourceBundle

但是,要覆盖getKeys(),我有点麻烦。这个getKeys 需要以某种方式从底层ResourceBundles 的映射中连接起来。我该怎么做?

谢谢

编辑:提交时我遇到了一个想法。基本上我们每个ModuleResourceBundle 都有,所以到目前为止我的代码如下所示:

public Enumeration<String> getKeys() {
        ArrayList<String> keys = new ArrayList<String>();

        for (Map.Entry<Module, ResourceBundle> entry : internalMap.entrySet()) {
            Enumeration<String> tmp = entry.getValue().getKeys();
            while (tmp.hasMoreElements()) {
                String key = tmp.nextElement();
                keys.add(key);
            }
        }

        return Collections.enumeration(keys);
    }

【问题讨论】:

    标签: java resourcebundle


    【解决方案1】:

    最简单的方法是手动枚举枚举,将它们转储到集合中,然后返回该集合的枚举。

    如果做不到这一点,您可以结合 Google Guava 操作来执行此操作,如下所示:

    // the map of enumerations
    Map<?, Enumeration<String>> map = ...
    
    // a function that turns enumerations into iterators
    Function<Enumeration<String>, Iterator<String>> eumerationToIteratorFunction = new Function<Enumeration<String>, Iterator<String>>() {
       public Iterator<String> apply(Enumeration<String> enumeration) {
          return Iterators.forEnumeration(enumeration);
       }
    };
    
    // transform the enumerations into iterators, using the function
    Collection<Iterator<String>> iterators = Collections2.transform(map.values(), eumerationToIteratorFunction);
    
    // combine the iterators
    Iterator<String> combinedIterator = Iterators.concat(iterators);
    
    // convert the combined iterator back into an enumeration
    Enumeration<String> combinedEnumeration = Iterators.asEnumeration(combinedIterator); 
    

    这很麻烦,但是Enumeration 是旧的,并且在现代 API 中的支持很差。它可以通过明智地使用静态导入来缩小一点。您甚至可以在一个函数式语句中完成所有操作:

    Map<?, Enumeration<String>> map = ...
    
    Enumeration<String> combinedEnumeration = asEnumeration(concat(
       transform(map.values(), new Function<Enumeration<String>, Iterator<String>>() {
          public Iterator<String> apply(Enumeration<String> enumeration) {
             return forEnumeration(enumeration);
          }
       })
    )); 
    

    这种方法的好处是效率高 - 它会懒惰地做所有事情,并且在您要求之前不会迭代。但是,在您的情况下,效率可能并不重要,在这种情况下,只需使用简单的方法即可。

    【讨论】:

    • 是的,枚举是一个非常古老的接口,也许@fablife 应该只发送一个 MethodNotSupportedException。它很可能永远不会被调用。
    • 最后我们按照这些思路做了一些事情,虽然有点不同。我们实现了一个自己的 ResourceBundle,它在单个枚举上保存了一个迭代器集合并实现了 Enumeration。因此,我们可以在需要时生成枚举。感谢所有贡献者。
    【解决方案2】:

    您可以使用 sun.misc.CompoundEnumeration。它是 Java 的一部分,不需要额外的库。

    【讨论】:

      【解决方案3】:

      您可以创建自己的自定义Enumeration 实现,该实现将具有addAll (Enumeration&lt;E&gt; enumeration) 方法。然后在所有底层ResourceBundle 对象上调用getKeys(),并将它们全部添加到您自己的Enumeration 的新实例中。

      【讨论】:

        【解决方案4】:

        您可以使用Guava's Iterators 类:使用forEnumeration 转换每个枚举,然后使用concat 迭代器,然后使用asEnumeration 将生成的迭代器转换回枚举。

        或者使用类似于 Guava 的 concat 方法的代码自己实现一个连接枚举。

        【讨论】:

          【解决方案5】:

          这是我们最终想出的。它有更多代码,但认为分享基础知识是公平的。解决方案遵循了一点 skaffman 的建议。 感谢所有贡献。

          public class ChainedResourceBundle extends ResourceBundle implements Enumeration<String> {
          
              Iterator<Map.Entry<Module, ResourceBundle>> tables;
              private Enumeration<String>                 keys;
          
              private Map<Module, ResourceBundle>         internalMap    = new HashMap<Module, ResourceBundle>();
              private Map<String, String>                 customizedKeys = new HashMap<String, String>();
          
          
              @Override
              public Enumeration<String> getKeys() {
                  tables = internalMap.entrySet().iterator();
                  nextTable();
                  return this;
              }
          
          
              @Override
              public boolean hasMoreElements() {
                  return keys != null;
              }
          
          
              @Override
              public String nextElement() {
                  String key = keys.nextElement();
                  if (!keys.hasMoreElements()) {
                      nextTable();
                  }
                  return key;
              }
          
              private void nextTable() {
                  if (tables.hasNext()) {
                      keys = tables.next().getValue().getKeys();
                  } else {
                      keys = null;
                  }
              }
          
          }
          

          【讨论】:

            【解决方案6】:

            你也可以使用Vectorlike

            public Enumeration<String> getKeys() {
                ResourceBundle parent = this.parent;
                Set<String> keySet = this.handleKeySet();
                List<String> parentKeySet = (parent != null) ? list(parent.getKeys()) : null;
                keySet.addAll(parentKeySet);
                return new Vector<>(keySet).elements();
            }
            

            【讨论】:

              猜你喜欢
              • 2013-07-23
              • 1970-01-01
              • 2015-11-21
              • 2018-02-23
              • 2021-07-22
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多