2016-04-05 3 views
2

Я хочу удалить все записи из LinkedHashMap, которые были добавлены после записи с заданным ключом.Как эффективно удалить записи из LinkedHashMap в Java?

Моя первая попытка была:

LinkedHashMap<String, SomeObject> var = new LinkedHashMap<String, SomeObject>(); 

public void removeEntriesAfter(String key) { 
    boolean deleteEntries = false; 
    for (String currentKey : var.keySet()) { 
    if(deleteEntries) { 
     var.remove(currentKey); 
    } else { 
     if(key.equalsIgnoreCase(currentKey)) { 
     // Do not remove the current entry 
     deleteEntries = true; 
     } 
    } 
    } 
} 

Но потом я получил java.util.ConcurrentModificationException.

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

public void removeEntriesAfter(String key) { 
    boolean deleteEntries = false; 
    List<String> listOfEntriesToBeRemoved = new ArrayList<String>(); 

    // Determine entries to be deleted 
    for (String currentKey : var.keySet()) { 
    if(deleteEntries) { 
     listOfEntriesToBeRemoved.add(currentKey); 
    } else { 
     if(key.equalsIgnoreCase(currentKey)) { 
     // Do not remove the current entry 
     deleteEntries = true; 
     } 
    } 
    } 

    // Removed selected entries 
    for (String currentKey : listOfEntriesToBeRemoved) { 
    var.remove(currentKey); 
    } 
} 

Это работает, но я уверен, что есть более элегантный/эффективный способ сделать это.

+4

Получить ключевой итератор через 'm.keySet(). Iterator()'. Вызов 'next()' до тех пор, пока вы не достигнете 'key'. После этого вызывается 'remove()'/'next()' до тех пор, пока 'hasNext()' не возвращает false. – aioobe

ответ

2

Чтобы избежать ConcurrentModificationException, вы можете использовать Iterator.

Iterator<String> it = map.keySet().iterator(); 
while (it.hasNext()) 
    if (it.next().equalsIgnoreCase(currentKey)) 
     break; 
while (it.hasNext()) { 
    it.next(); 
    it.remove(); 
} 

Если вы хотите эффективное решение наиболее, было бы идти прямо к соответствующему входу в первую очередь. Чтобы сделать это, вам нужно было бы когда-либо накладывать на карту нижние регистры (вместо того, чтобы ставить любые старые строки и сравнивать с помощью equalsIgnoreCase). Затем, используя отражение, вы можете получить доступ к объекту Map.Entry, соответствующему currentKey.toLowerCase(), а затем, снова используя отражение, вы можете следовать ссылкам по всей карте. Ничто из этого невозможно без размышлений, поскольку ни одна запись, соответствующая ключу или ссылкам между элементами, не открывается через открытый API. Я не рекомендую отражать, так как ваш код может легко сломаться в будущем, если будет изменен код для LinkedHashMap.

+0

Интересно, я думал, что 'it.remove();' удаляется из 'Iterator', а не из' LinkedHashMap'. Это немного запутанно, но, похоже, работает. – Edward

 Смежные вопросы

  • Нет связанных вопросов^_^