2017-01-09 3 views
3

Извините за титул, я не смог найти лучшего, и я знаю, что это звучит запутанно. Вопрос состоит в следующем:Как сравнить карту со списком

У меня есть HashMap с этим выглядит следующим образом:

Map<String, ClassA> myMap; 

Кроме того, у меня есть список, который выглядит следующим образом:

List<ClassB> myList; 

ClassB выглядит следующим образом:

public class ClassB{ 

    //many things 

    private String someString; 
    //getter 
    //setter 
    } 
} 

SomeString является ключом st кольцо myMap

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

Любой алгоритм? Образец или даже пример?

Спасибо

ответ

5

Вы должны перебирать List<ClassB> myList по крайней мере один раз для того, чтобы сделать это, но вы можете сделать это с одной итерации точно, что делает его идеальным алгоритмического-накрест.

Создайте новую карту и для каждого элемента в списке проверьте, находится ли она в myMap, и если она есть - добавьте ее в новую созданную вами карту. После того, как вы закончите повторение списка, просто назначьте: myMap = newMap;, и все готово.

Примечание: это идеальное решение для минимального количества шагов, но оно является, используя больше памяти, чем алгоритм «на месте».

+0

Привет, я благодарю вас за помощь, это звучит хорошо, за исключением того факта, что мне нужно использовать меньше памяти и меньше процессорного времени. На самом деле я сделал, чтобы перебирать список и делать изменения на карте, не копируя их на другую карту. Я ищу здесь, чтобы улучшить код –

+2

@MarwanJaber, вы должны проверить оба варианта и избежать каких-либо «оптимизаций», если это необходимо.Имейте в виду, что, «копируя» карту, вы на самом деле копируете только указатели на объекты и * не * сами объекты, поэтому, если у вас нет * лота * объектов, такая «оптимизация» не нужна! – alfasin

+1

@MarwanJaber. Трудно (иногда, невозможно) иметь оба: использовать меньше памяти и использовать меньше процессора. Вам нужно выбрать один. –

2

С Java 8 потоков API,

Set<String> keySet = new HashSet<>(myMap.keySet()); 
myList.forEach(entry -> keySet.remove(entry.getSomeString())); 
keySet.forEach(key -> myMap.remove(key)); 

Вот так. Я только что удалил ключи, которые находятся в списке от keySet. Затем я удаляю все оставшиеся ключи. Это будет работать в O(n).

Это будет потреблять меньшую память, чем текущее решение, поскольку вы создаете дополнительный Set вместо Map.

+2

Проверка '! MyList.contains (key)' принимает 'O (n)' шагов и повторяет ее 'n' times делает ее« O (n^2) », что не является идеальным, поскольку OP явно запрашивает что-то эффективное, поскольку это произойдет каждые несколько секунд. – alfasin

+0

Hi Imesha, Чем вы помогаете, он выглядит хорошим, знаете ли вы, лучше ли он перебирать список и каждый раз искать карту? –

+0

Текущее решение неверно и не имеет смысла. – shmosel

2

Похож, вы хотите retainAll. Фокус в том, что вы вызываете это на карте keySet(), которая имеет побочный эффект удаления нежелательных записей с карты.

Далее вы хотите сохранить элементы не в List<ClassB>, а в списке строк, полученных от каждого экземпляра ClassB. Вы можете использовать поток для этого.

myMap.keySet() 
     .retainAll(myList.stream() 
          .map(ClassB::getSomeString) 
          .collect(toList())); 
Смежные вопросы