1

In my Android project I have a method to partially invalidate a cache (HashMap<Integer, Boolean>).

I am currently using a HashMap for compatibility with third party code.

I found a great answer here but it requires switching to a TreeMap. The given solution is:

treeMap.tailMap(key).clear();

The TreeMap solution is much better than my effort on HashMap:

//where hashMap is a copied instance for the method
for (Integer key : hashMap.keySet()) {
    if (key > minPosition) {
        hashMap.remove(key);
    }
}

Is there a better time/complexity solution for doing this in a HashMap, similar to the TreeMap solution?

Community
  • 1
  • 1
Nick Cardoso
  • 20,807
  • 14
  • 73
  • 124
  • Nothing that you could provide in your own implementation would be much better, if at all, than the TreeMap solution. You's just be implementing a binary search to locate the start of the members to remove, and then setting the start node to the next one, which from my understanding is all done in the background with TreeMap anyways. It's a much safer bet so I'd just go with that. – Preston Garno Mar 11 '17 at 01:20
  • Hi, I don't expect it to be better than the TreeMap solution. I want something better than *my* solution. Something closer to the efficiency of the TreeMap. So far TreeMap seems better for me too, but I don't want to commit if there's a chance I can do it well with the HashMap (saving a lot of effort converting to HashMap at all the places this stupid 3rd party stuff doesn't just stick to the Map interface – Nick Cardoso Mar 11 '17 at 01:24
  • You can iterate over the `hashMap.keySet()` so u're not loading the full `Entry` – Jérôme Mar 11 '17 at 01:26
  • Yes true, that makes sense actually, I'll change it in my question in fact. But not a full solution of course – Nick Cardoso Mar 11 '17 at 01:27
  • For a generic map? I don't think there is one- a map has no promise as to any ordering, so there's no tricks you can use. Nothing for a HashMap either (in fact a good hash algorithm would make it impossible to do in better than O(n)). You might be able to get a tiny increase in speed with micro-optimizations, but nothing that would prevent it from being O(n) over the entire mapping. If you need to do this, you need a data structure that optimized for it, which a generic map doesn't. – Gabe Sechan Mar 11 '17 at 01:27
  • That what I feared. I assume there is nothing in the collections class or other utilities either (I'm taking a last-grasp look now) – Nick Cardoso Mar 11 '17 at 01:30
  • @NickCardoso there is a way to make it faster using a LinkedHashMap, but it's a large margin of best-case/worst-case times for the algorithm, like GabeSechan said. One question though, why are you using a Set? Depending on what the Integer keys represent, it might be better to use a List structure. – Preston Garno Mar 11 '17 at 01:36
  • That's just what the Map interface provides – Nick Cardoso Mar 11 '17 at 01:37
  • Thanks everyone for the help/votes/whatever, I thought this was a long shot anyway so thanks for confirming rather than ignoring the question! – Nick Cardoso Mar 11 '17 at 01:49
  • If you care about key order you should be using a `TreeMap`. No two ways about it. – user207421 Mar 11 '17 at 01:54
  • Thanks, It's not that I explicitly care about the order any where - just that ordering makes it more efficient to removed based on a value – Nick Cardoso Mar 11 '17 at 02:40

1 Answers1

3

If you are required to use HashMap, there is no better (more efficient) solution than iterating the entry set, and removing entries one at a time. This is going to be an O(N) operation. You need to visit / test all entries in the map.

As you correctly observed you can bulk remove entries more neatly and more efficiently from a TreeMap. It will be an O(logN) operation. But the downside is that insertions and deletions are O(logN) rather than O(1).

A LinkedHashMap can help in certain use-cases, but not in this one. (It orders the entries based on the sequence of insertion, not on the values of the keys.)

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216