объединить несколько перечислений? - PullRequest
2 голосов
/ 01 декабря 2011

Мне пришлось подкласс ResourceBundle из-за наших конкретных потребностей.

Однако, чтобы переопределить getKeys(), у меня немного неприятностей. Это getKeys необходимо каким-то образом объединить с картой базовых ResourceBundle s. Как я могу это сделать?

Спасибо

РЕДАКТИРОВАТЬ: При отправке я наткнулся на идею. В основном мы имеем для каждого нашего Module a 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 ]

3 голосов
/ 01 декабря 2011

Самый простой подход - просто перечислить перечисления вручную, сбросить их в коллекцию, а затем вернуть перечисление этой коллекции.

Если это не удастся, вы можете объединить 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);
      }
   })
)); 

Преимущество этого подхода в том, что он эффективен - он выполняет все лениво и не будет повторяться, пока вы его не попросите.Эффективность может не иметь значения в вашем случае, однако, в этом случае просто сделайте это простым способом.

2 голосов
/ 27 января 2014

Вы можете использовать sun.misc.CompoundEnumeration.Он является частью Java без дополнительных библиотек.

0 голосов
/ 17 октября 2018

Вы также можете использовать 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();
}
0 голосов
/ 05 декабря 2011

Это то, что мы наконец придумали. В ней больше кода, но я подумал, что было бы справедливо поделиться основами. Решение следует предложению Скаффмана. Благодаря всем вкладам.

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

}
0 голосов
/ 01 декабря 2011

Вы можете использовать Класс итераторов Guava : преобразовать каждое перечисление с помощью forEnumeration, затем concat итераторы и преобразовать полученный итератор обратно в перечисление с помощью asEnumeration.

Или реализуйте конкатенацию Enumeration самостоятельно, используя код, похожий на метод concat в Guava.

0 голосов
/ 01 декабря 2011

Вы можете создать свою собственную Enumeration реализацию, которая будет иметь метод addAll (Enumeration<E> enumeration).Затем вызовите getKeys() для всех базовых ResourceBundle объектов и добавьте их все в новый собственный экземпляр Enumeration.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...