11

In Mysql we can query a table having clause " WHERE name LIKE '%someName%' ", can we have the same functionality with HashMap in java,if so how can we achieve this more efficiently in a less time by not iterating over each element?

achuth
  • 1,212
  • 2
  • 16
  • 29
  • 3
    just loop with some regex, or create your own map impl – epoch Apr 17 '14 at 09:32
  • Is "name" the key or the value in your map? Would you like to return a list of keys or values? – Joffrey Apr 17 '14 at 09:34
  • "name" is a key in a map – achuth Apr 17 '14 at 09:36
  • 1
    How efficient do you want it to be? You can do a brute force search of HashMap, or you can use a NavigableMap efficiently, but the code is far more complicated. i.e. if a brute force search isn't obvious to you, don't attempt using a NavigableMap. – Peter Lawrey Apr 17 '14 at 09:37
  • I need to search for key in a large number of keys more frequently – achuth Apr 17 '14 at 09:43

5 Answers5

8

If you're using Java SE 8 and the new Streams API: there is a filter method which basically is what you are looking for, I think.

e.g. something like (untested!):

myMap.entrySet().stream().filter(entry -> entry.getKey().contains("someName")).map(entry -> entry.getValue()).collect(Collectors.toList());
Puce
  • 37,247
  • 13
  • 80
  • 152
  • Thank you @Puce! I just needed the key part, so `myMap.entrySet().stream().filter(entry -> entry.getKey().contains("someName")).collect(Collectors.toList());` was enough – hestellezg Apr 17 '19 at 21:27
4

You can iterate on all your keys and check if they match a regexp. This might not be the most efficient way of doing it, but it's the first thing I thought of. Here is what it would look like:

Pattern p = Pattern.compile("*someName*"); // the regexp you want to match

List<String> matchingKeys = new ArrayList<>();
for (String key : map.keySet()) {
    if(p.matcher(key).matches()) {
        matchingKeys.add(key);
    }
}

// matchingKeys now contains the keys that match the regexp

Note: map is supposed to be declared earlier like this:

HashMap<String, SomeValueClass> map = new HashMap<>();
Joffrey
  • 32,348
  • 6
  • 68
  • 100
  • This will upto my need functionality wise, but i am thinking about large set of key values which has to be iterated large number of times – achuth Apr 17 '14 at 09:59
  • @achuth Then why not use a real database? How much memory your program will need anyway if the number of keys is that large? – Joffrey Apr 17 '14 at 09:59
  • Actually i get all keys from a column in a table from database, of size 62Kb – achuth Apr 17 '14 at 10:03
  • @achuth Then why don't you use the `LIKE` SQL keyword when you get the info? I think it will be more efficient than loading everything in memory and iterate on everything many times in a row. – Joffrey Apr 17 '14 at 10:05
  • All the key are stored in JSON format in a single row of a single coumn – achuth Apr 17 '14 at 10:07
  • Hash map is faster in getting a value than iterating over a list or array by comparing each element, if there is no way in doing this i would directly use a array rather than a HashMap – achuth Apr 17 '14 at 10:29
  • @achuth Storing JSON in a database does not seem a good idea to me, why would you do such a thing? You might want to re-design your DB tables to fit the JSON fields. Then, you can load your stuff in a HashMap (if it fits in your memory) for indivual value accesses, and do SQL queries for large regexp accesses. – Joffrey Apr 17 '14 at 11:04
  • @achuth Here is some wise advice on whether to store JSON or not in the DB: http://stackoverflow.com/a/15367769/1540818 – Joffrey Apr 17 '14 at 11:14
2

Remove all values which doesn't contain key part:

yourMap.keySet().removeIf(key -> !key.contains(keyPart));

Or regex:

yourMap.keySet().removeIf(key -> !key.matches(".*keyPart.*"));
Justinas Jakavonis
  • 8,220
  • 10
  • 69
  • 114
0

There may be a way to achieve this functionality in Java, but HashMap will not do it.

merlin2011
  • 71,677
  • 44
  • 195
  • 329
0

If you want to get all the values in a map that are associated to a given key you are doing a reverse lookup.

You would need to iterate over every key / value pair in the map, searching for the given value and storing it into a collection. Something like this:

List<KeyType> keys = new ArrayList<>();
for (Map.Entry<KeyType, ValueType> e : myMap)
    if(e.getValue().equals(valueWeAreSearchingFor)) keys.add(e.getKey());
robertoia
  • 2,301
  • 23
  • 29
  • What happens when searching a map having some 1000's of key's frequently? – achuth Apr 17 '14 at 09:39
  • This might not meet the OP's needs, because he wanted to match a pattern, not an exact value. – Joffrey Apr 17 '14 at 09:47
  • @achuth Well, you have to iterate over the entire map, so it's going to be *slow*. Consider using something like a [BidiMap](http://commons.apache.org/proper/commons-collections/apidocs/org/apache/commons/collections4/BidiMap.html) – robertoia Apr 17 '14 at 09:48
  • @Joffrey True, I didn't get that part of the question. Your answer is better then, upvoting. – robertoia Apr 17 '14 at 09:49