As a simple example:
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class FilterExample { | |
private Map<String, String> data = new HashMap<String, String>(); | |
public FilterExample() { | |
data.put("A", "one"); | |
data.put("B", "two"); | |
data.put("C", "three"); | |
data.put("D", "four"); | |
data.put("E", "five"); | |
} | |
public Map<String, String> getNewMapWithVowelKeys() { | |
Map<String, String> result = new HashMap<String, String>(); | |
for (String keyVal: data.keySet()) { | |
if (keyVal.matches("^[aeiouAEIOU].*")) { | |
result.put(keyVal, data.get(keyVal)); | |
} | |
} | |
return result; | |
} | |
public Map<String, String> getNewMapWithVowelValues() { | |
Map<String, String> result = new HashMap<String, String>(); | |
for (Map.Entry<String, String> entry: data.entrySet()) { | |
if (entry.getValue().matches("^[aeiouAEIOU].*")) { | |
result.put(entry.getKey(), entry.getValue()); | |
} | |
} | |
return result; | |
} | |
public Map<String, String> getNewMapWithConsonantKeys() { | |
Map<String, String> result = new HashMap<String, String>(); | |
for (String keyVal: data.keySet()) { | |
if (keyVal.matches("^[^aeiouAEIOU].*")) { | |
result.put(keyVal, data.get(keyVal)); | |
} | |
} | |
return result; | |
} | |
public Map<String, String> getNewMapWithConsonantValues() { | |
Map<String, String> result = new HashMap<String, String>(); | |
for (Map.Entry<String, String> entry: data.entrySet()) { | |
if (entry.getValue().matches("^[^aeiouAEIOU].*")) { | |
result.put(entry.getKey(), entry.getValue()); | |
} | |
} | |
return result; | |
} | |
} |
We're looking at two different criteria (string starts with a vowel or a consonant) and two different targets -- the map key or the value.
The looping is duplicated and the determination of whether the values should be in the new map screams for a predicate.
In Google collections this is usually just a filter taking in the collection and the predicate. But 'filter' wasn't available on a Map -- it works on a collection.
Well, first I needed a predicate:
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class EntryKeyIsVowel implements Predicate<Map.Entry<String,String>> { | |
public boolean apply(Map.Entry<String, String> input) { | |
return input.getKey().matches("^[aeiouAEIOU].*"); | |
} | |
public boolean equals(Object obj) { | |
return this.getClass() == obj.getClass(); | |
} | |
} |
That was easy enough.
My first try was to filter the entry set of the map and then add the filtered elements to the result:
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public Map<String, String> getMapFor(Predicate<Map.Entry<String,String>> mapPredicate) { | |
Map<String, String> result = newHashMap(); | |
Collection<Map.Entry<String, String>> newEntries = filter(data.entrySet(), mapPredicate); | |
for (Map.Entry<String, String> entry: newEntries) { | |
result.put(entry.getKey(), entry.getValue()); | |
} | |
return result; | |
} |
Not too happy that I'm looping over something twice in the worst case.
Well, I can just use the predicate without using anything else from Google collections:
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public Map<String, String> anotherMapFor(Predicate<Map.Entry<String,String>> mapPredicate) { | |
Map<String, String> result = newHashMap(); | |
for (Map.Entry<String, String> entry: data.entrySet()) { | |
if (mapPredicate.apply(entry)) { | |
result.put(entry.getKey(), entry.getValue()); | |
} | |
} | |
return result; | |
} |
But, I just felt there should be a better way. Asked a couple of people while I was trying different searches. Finally I found that Maps has a tranform, but it also has different filter methods! Just what I needed.
The one-liner:
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public Map<String, String> transformMapFor(Predicate<Map.Entry<String,String>> mapPredicate) { | |
return Maps.filterEntries(data, mapPredicate); | |
} |
That will wrap it up for now.
No comments:
Post a Comment