Как создать пользовательский итератор для реализации Map? - PullRequest
4 голосов
/ 04 июля 2011

Я реализовал уникальную карту.Это хэш-карта, которая является двунаправленной, где не только ключи уникальны, но и значения.

public interface UniqueMap<K,V>{

    V uniquePut(K key, V value);

    UniqueMap<V,K> inverse(); 
}

Это возможная реализация:

public class SimpleUniqueMap<K,V> implements UniqueMap<K,V>, Iterable<K>{

    public HashMap<K,V> uniqueMap = new HashMap<K,V>();

    class EnumSimpleUniqueMap implements Iterator<K>{

        int count = uniqueMap.size();

        public boolean hasNext(){
            return count > 0;
        }

        public K next(){
            if(count == 0){
                throw new NoSuchElementException();     
            }else{
                count--;
                //...
            }
        }

        public void remove(){
            throw new UnsupportedOperationException();
        }
    }

    public Iterator<V> iterator(){
        return new EnumSimpleUniqueMap();
    }

    public V uniquePut(K key, V value){ 
        return null;
    }

    public UniqueMap<V,K> inverse(){
        return null;
    }
}

Как вы можете видеть, я уже пытался реализовать итератор для моей уникальной карты.Но из значений hashmap можно получить доступ не по позиции, а по ключу.Поэтому обычно я беру счетчик и получаю доступ к значениям, но в этом случае это невозможно.

На самом деле, этого будет достаточно, чтобы перебрать ключи и получить их один за другим.Как я могу это сделать?Есть ли способ получить какой-либо объект ввода, содержащий и ключ, и значение?

Я знаю, что могу извлечь итератор из объекта карты, но это не вариант для меня.

Ответы [ 3 ]

3 голосов
/ 04 июля 2011

ОБНОВЛЕНИЕ : Самое простое из всех, используйте

org.apache.commons.collections.BidiMap

Но если вы действительно хотите бросить свой собственный, то подумайте:

Обычно, Maps не реализовывать Iterable.В вашем случае вы можете получить Iterator бесплатно, вызвав любой из этих

map.keys().iterator(); // is the same as
map.inverse().values().iterator();

map.values().iterator(); // is the same as
map.inverse().keys().iterator();

map.entrySet().iterator(); // almost the same as
map.inverse().entrySet().iterator();

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

public interface UniqueMap<K,V> extends Map<K, V> {
    // no need for uniquePut(), you already have Map.put()
    UniqueMap<V,K> inverse(); 
}

Также неплохо бы расширить вашу реализацию

java.util.AbstractMap<K, V>

, которая уже имеет много базовых функций для карт.

2 голосов
/ 04 июля 2011

Вы могли бы реализовать свой метод iterator(), просто делегировав итератору набора ключей вашего резервного хеш-карты:

public Iterator<K> iterator(){
    return uniqueMap.keySet().iterator();
}

Конечно, как сказал Лукас, карта, как правило, не будет итеративной, но предоставит виды коллекций, которые сами по себе итеративны.

Кроме того, для вашей уникальной реализации карты может быть полезно иметь HashMaps в обоих направлениях.

Кроме того, подумайте (и укажите это в интерфейсе): что должно произойти, если пользователь вставит новый ключ с уже существующим значением - это не удастся, игнорируется, удалит существующее сопоставление или как?

1 голос
/ 04 июля 2011

Вам следует заглянуть в библиотеку Guava (Google Collection). У них есть реализация BiMap , которая, кажется, является именно тем, что вы пытаетесь реализовать ...

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