Reputation: 485
How can we restrict a HashMap to accept a particular string key.
Restriction here can have one of following meanings-
1. It can throw an error or
2. It can simply ignore that entry which has that specific key.
But the condition is that it should be implemented without overriding put
method of HashMap and without using if
condition while adding an entry to given map.
Suppose I have a HashMap m and I want to restrict a particular string key "myKey". What I want is, whenever we try to add any entry with key "myKey", m should follow point 1 or point 2 as mentioned above.
m.put("otherKey", "value"); // should add to the map<br/>
m.put("myKey","value"); // Either throw an error or ignore this entry and should not add to the map.
I can restrict a type of keys using Genetics but how to do it for a single given string key. It was an interview question.
Thanks in Advance !!
Upvotes: 3
Views: 3031
Reputation: 48864
You could do any number of tricks to avoid explicitly typing if
. The existing answer using switch
works, as would using a while
loop and breaking or returning unconditionally inside of it. If your interviewer really wants to see how you can write unpleasant code that's your answer.
If you're interested in real ways to restrict a HashMap
's keys, you should use Guava's ForwardingMap
and extend its .put*()
and .putAll()
methods, throwing an IllegalArgumentException
"if some property of the specified key or value prevents it from being stored in this map". Even if you don't use Guava, you should prefer the decorator pattern over extending HashMap
directly (Effective Java: Item 16).
Alternatively, you may find it easier to use a dedicated type for your keys, e.g. a RestrictedString
class that does your sanitization. Then you can create a Map<RestrictedString, String>
and trust that only valid keys are in the map. This avoids using a conditional (if
/switch
/etc.) in the Map
code, instead moving it to the RestrictedString
class.
Even if an interviewer is asking a puzzler-style question, responding with real-world solutions (while still acknowledging their stipulations) can only score you points with any legitimate employer.
Upvotes: 2
Reputation: 23246
An EnumMap would allow the keys to be restricted to a static subset but would obviously break the requirement of Map<String, String>
.
With a decorator, the decorator and the decorated class normally share an interface i.e. Map, so implementing a custom put(k, v)
and passing all other methods through to the decorated HashMap may be acceptable as you are not directly overriding the put(k, v)
method of HashMap.
The only other solution I can think of is using an AOP based solution to apply a 'before' advice to the put(k, v) method and which would reject any invalid values.
Upvotes: 0
Reputation: 10717
Use Set to store prohibited keys.
Then map true and false within a map:
Set prohibitedKeys = new HashSet<String>();
prohibitedKeys.add("myKey");
Map<Boolean,Map<String,String>> boolMap = new HashMap<Boolean,Map<String,String>>();
Map<String,String> myMap = new HashMap<String,String>();
boolMap.put(Boolean.FALSE,myMap);
//This will work
Map m = boolMap.get((Boolean)prohibitedKeys.contains("otherKey"))
m.put("otherKey", "value");
//This will throw an null pointer exception
m.put("myKey", "value");
Upvotes: 1
Reputation: 1093
You could use an emun as the key. Such as
public enum AllowedKey {
KEY_ONE,
KEY_TWO; // etc
}
Then use this in your Map:
Map<AllowedKey, String> map = new HashMap<>();
map.put("string", "value"); // compile error!
map.put(AllowedKey.KEY_ONE, "value"); // success!
You could also use an EnumMap if your implementation allows this.
Edit: The definition of the HashMap cannot be changed, so this approach would no longer be applicable.
Upvotes: 5
Reputation: 40510
These are very weird restrictions you have ... but here it is without an if
statement or overriding:
void addToMap(HashMap<String,Sting> map, String key, String value) {
switch (key) {
case "MyKey":
throw new IllegalArgumentException(key);
default: map.put(key, value);
}
}
Upvotes: 3