连接几个枚举?

时间:2011-11-30 21:57:25

标签: java resourcebundle

由于我们的特殊需要,我必须继承ResourceBundle

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

由于

编辑:提交时我遇到了一个想法。基本上我们为Module ResourceBundle中的每一个都有,所以到目前为止我的代码看起来像这样:

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);
    }

6 个答案:

答案 0 :(得分:3)

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

如果做不到这一点,您可以将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);
      }
   })
)); 

这种方法具有高效的好处 - 它可以懒惰地完成所有操作,并且在您提出要求之前不会进行迭代。在你的情况下,效率可能无关紧要,在这种情况下,只需简单的方法就可以了。

答案 1 :(得分:2)

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

答案 2 :(得分:0)

您可以使用Enumeration方法创建自己的自定义addAll (Enumeration<E> enumeration)实施。然后在所有基础getKeys()对象上调用ResourceBundle,并将它们全部添加到您自己Enumeration的新实例中。

答案 3 :(得分:0)

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

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

答案 4 :(得分:0)

这是我们最终提出的。它有更多的代码,但认为分享基础知识是公平的。该解决方案遵循了一些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;
        }
    }

}

答案 5 :(得分:0)

您也可以像

一样使用Vector
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();
}