Перебор HashMap из HashMaps в Java (или Scala) - PullRequest
6 голосов
/ 15 июля 2010

Я создал класс Foo, который имеет метод toArray(), который возвращает Array<Int>.

Теперь у меня есть HashMap, отображающий Strings в HashMaps, который отображает Object в Foo.То есть:

HashMap<String,HashMap<Object,Foo>>

И я хочу создать новый объект типа:

HashMap<String,HashMap<Object,Array<Int>>>

, который получается путем вызова функции toArray () для каждого элемента Foo в исходном HashMAp.

Для этого я обычно делал бы что-то вроде:

    public static HashMap<String,HashMap<Object,Array<Int>>> changeMap(Map mpOld) {
        Object key2;
        String key1;
        Iterator it2;
        HashMap<String,HashMap<Object,Array<Int>>> mpNew= 
            new HashMap<String,HashMap<Object,Array<Int>>>()
        Iterator it1 = mpOld.keySet().iterator();
        while (it1.hasNext()) {
            key1=it1.next();
            it2= mpOld.get(key1).keySet().iterator();
            mpNew.put(key1,new HashMap<Object,Array<Int>>())
            while (it2.hasNext()) {
                key2=it2.next();
                mpNew.get(key1).put(key2,mpOld.get(key1).get(key2).toArray());
                //TODO clear entry mpOld.get(key1).get(key2)
            }
            //TODO clear entry mpOld.get(key1)
        }
        return mpNew;
    }

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

Интересно, есть ли лучший способ перебрать карты и скопировать информацию.

Кроме того, я работаю в проекте Scala, но здесь я должен использовать типы Java для некоторых проблем совместимости.Хотя Java.util.HashMap не является итератором, может быть, в Scala есть какая-то скрытая функция, чтобы справиться с этим?

Спасибо,

Ответы [ 4 ]

8 голосов
/ 15 июля 2010

Итераторы предлагают remove(..) методы, которые безопасно удаляют ранее доступный элемент.Переберите записи «Ключ / Значение» на карте, конвертируйте их и добавляйте на новую карту, удаляя старые по мере продвижения.

/**
 * Transfers and converts all entries from <code>map1</code> to 
 * <code>map2</code>.  Specifically, the {@link Foo} objects of the 
 * inner maps will be converted to integer arrays via {@link Foo#toArray}.
 * 
 * @param map1 Map to be emptied.
 * @param map2 Receptacle for the converted entries.
 */
private static void transfer(Map<String, Map<Object, Foo>> map1
        , Map<String, Map<Object, int[]>> map2) {

    final Iterator<Entry<String, Map<Object, Foo>>> mapIt
        = map1.entrySet().iterator();
    while (mapIt.hasNext()) {
        final Entry<String, Map<Object, Foo>> mapEntry = mapIt.next();
        mapIt.remove();
        final Map<Object, int[]> submap = new HashMap<Object,int[]>();
        map2.put(mapEntry.getKey(), submap);
        final Iterator<Entry<Object,Foo>> fooIt 
            = mapEntry.getValue().entrySet().iterator();
        while (fooIt.hasNext()) {
            final Entry<Object,Foo> fooEntry = fooIt.next();
            fooIt.remove();
            submap.put(fooEntry.getKey(), fooEntry.getValue().toArray());
        }
    }
}
5 голосов
/ 15 июля 2010

У меня не было времени, чтобы проверить это, но я думаю, что-то вроде этого должно работать на Scala Maps (при условии, что вы используете Scala 2.8, который, наконец, здесь):

mpO.mapValues(_.mapValues(_.toArray))

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

Если вы также выполните

import scala.collection.JavaConversions._

тогда java-карты можно использовать так же, как карты scala: JavaConversions содержат набор неявных методов, которые могут конвертировать между коллекциями scala и java.

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

Отредактируйте, отражая ваш комментарий

import scala.collection.JavaConversions._
import java.util.Collections._

object MapValues {
  def main(args: Array[String]) {
    val jMap = singletonMap("a",singletonMap("b", 1))
    println(jMap)
    println(jMap.mapValues(_.mapValues(_+1)))
  }
}

отпечатков:

{a = {b = 1}}
Карта (a -> Карта (b -> 2))

Показывает, что импликации применяются как к внешней, так и к внутренней карте довольно красиво.В этом и заключается цель объекта JavaConversions: даже если у вас есть коллекция java, вы можете использовать ее как аналогичный класс scala (с расширенными функциями).
Вам больше ничего не нужно делать, просто импортируйте JavaConversions._

4 голосов
/ 05 мая 2015

Например, учитывая строковые ключи; Давайте позвоним на вход data : Map<String, Map<String, Object>> data

for (Entry<String, Map<String, Tuple>> entry : data.entrySet()) {
  String itemKey = entry.getKey();
  for (Entry<String, Object> innerEntry : entry.getValue().entrySet()) {
    String innerKey = innerEntry.getKey();
    Object o = innerEntry.getValue();
    // whatever, here you have itemKey, innerKey and o
  }
}
4 голосов
/ 15 июля 2010

Набор поддерживается картой, поэтому изменения в карте отражаются в наборе и наоборот.Если карта изменяется во время выполнения итерации по набору (кроме как через собственную операцию удаления итератора), результаты итерации не определены.Набор поддерживает удаление элементов, которое удаляет соответствующее отображение с карты с помощью операций Iterator.remove, Set.remove, removeAll, retainAll и clear.

Почему бы вам не вызвать *Метод 1005 * на итераторе или set.remove (iterator.next ()), где iterator.next () возвращает ключ, набор - это набор ключей, а итератор - итератор.

PS: также попытайтесь реорганизовать структуру данных, возможно, некоторые промежуточные классы, которые обрабатываютпоиск данных?Карта на карте с массивами в качестве значений ничего не говорит и ее трудно отслеживать.

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