简体   繁体   English

如何有效地从Java中的LinkedHashMap中删除条目?

[英]How to efficiently remove entries from a LinkedHashMap in Java?

I want to remove all entries from a LinkedHashMap that were added after an entry with a given key. 我想从LinkedHashMap中删除在具有给定键的项之后添加的所有项。

My first try was: 我的第一次尝试是:

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;
      }
    }
  }
}

But then I received a java.util.ConcurrentModificationException . 但是后来我收到了java.util.ConcurrentModificationException

My second idea was to first determine the keys, an remove them afterwards. 我的第二个想法是先确定键,然后再删除它们。

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);
  }
}

That works, but I'm sure there is a more elegant/efficient way of doing this. 那行得通,但是我敢肯定有一种更优雅/更有效的方法。

To avoid a ConcurrentModificationException you can use an Iterator . 为了避免ConcurrentModificationException ,可以使用Iterator

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

If you wanted the most efficient solution, it would be to go straight to the appropriate entry in the first place. 如果您想要有效的解决方案,那将是直接直接进入相应的条目。 To do this you would have to only ever put lower case keys into the map (rather than putting any old strings and comparing using equalsIgnoreCase ). 为此,您只需将小写键放入映射中(而不是放入任何旧字符串并使用equalsIgnoreCase进行比较)。 Then, using reflection, you could access the Map.Entry object corresponding to currentKey.toLowerCase() and then, using reflection again, you could follow the links all the way through the map. 然后,使用反射,您可以访问与currentKey.toLowerCase()对应的Map.Entry对象,然后再次使用反射,您可以一直浏览整个地图中的链接。 None of this is possible without reflection because neither the entry corresponding to a key nor the links between entries are exposed through public API. 没有反射就不可能做到这一点,因为与键对应的条目或条目之间的链接都不会通过公共API公开。 I do not recommend reflection as your code could easily break in the future if the code for LinkedHashMap is changed. 我不建议您使用反射,因为如果更改LinkedHashMap的代码,将来您的代码很容易中断。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM