Итератор для всех элементов в хеш-картах, хранящихся в массиве - PullRequest
1 голос
/ 18 марта 2009

У меня есть пользовательский класс под названием Graph, в котором я использую списки смежности. Чтобы быть более конкретным, у меня есть массив хеш-карт, где каждая хеш-карта содержит всех соседей этого узла в виде ребер. Ключ - это конечный узел, а значение - объект Edge.

Теперь я хочу, чтобы этот класс Graph реализовал Iterable. Есть ли способ объединить все эти хэш-карты и вернуть общий итератор для всех их элементов?

Очень важно, чтобы используемый метод был эффективным.

Ответы [ 5 ]

6 голосов
/ 18 марта 2009

Вы можете использовать ChainedIterator из коллекций Apache Commons:

Iterator current = IteratorUtils.emptyIterator();
for(map: arrayOfHashmaps) {
   current = IteratorUtils.chainedIterator(current, map.keySet().iterator);
}

Если вы хотите избежать сбора общих ресурсов, вы можете просто собрать наборы ключей в списке и повторить его:

List allKeys = new LinkedList();
for(map: arrayOfHashmaps) {
   allKeys.addAll(map.KeySet());
}
return allKey.iterator();

Второе решение будет использовать немного больше памяти и будет немного медленнее. Однако я сомневаюсь, что это будет иметь значение.

1 голос
/ 18 марта 2009

В соответствии с API HashMap имеет функцию entrySet (), которая возвращает представление набора для отображения в Hash. Набор является повторяемым объектом. Чтобы создать итератор, просто выполните итерацию по массиву, превратив каждый хеш в набор, а затем скомпонуйте отдельные итераторы в один итератор ...

Не существует встроенного способа создания итераторов в java, однако написание собственной функции compose должно быть тривиальным.

0 голосов
/ 18 марта 2009

В качестве альтернативы вы можете попытаться сохранить все записи для графа в одной HashMap, в которой ключ является объектом, содержащим как номер узла, так и номер соседнего узла. Я предполагаю, что номер узла обычно будет индексом в массиве HashMaps, а соседний узел - ключом к текущему HashMap. Это позволит вам выполнять те же операции поиска, что и сейчас, и выполнять итерацию по всем записям без необходимости писать какой-либо специальный код.

Не забывайте, что вам нужно написать equals () и хорошую хеш-функцию для объекта, используемого в качестве ключа (этот объект в противном случае может быть очень простым). Если у вас очень большие графики, это, конечно, может не подходить.

0 голосов
/ 18 марта 2009

Почему бы просто не прокрутить свою собственную, последовательно повторяющуюся по различным картам?

public class MapCollection<K,V> implements Iterable<V> {
  Map [] maps;

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


   private class MapCollectionIterator<T>{
        public boolean hasNext() {
        public T next(){... (code omitted due to lazyness..)
  }

}

0 голосов
/ 18 марта 2009

Я бы сделал так, чтобы создать внутренний класс, который реализует Iterator. Внутренне он отслеживает 1) текущий индекс в массиве карт и 2) итератор в текущей карте. Его методы hasNext() и next() просто делегируют текущему итератору, или, если итератор завершен, просто увеличивают индекс и изменяют итератор.

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