Is it possible to use the same add method to add various types of data to either a map or set, dependant on what is passed in? for example...
public static <U, T> void add(T _token, U<T> set>
{
...
}
Where possibly a string or double is the _token argument and either a map, map or set or set is the set variable. I understand maps accept two values with the put method, but I'm ignoring this for the moment...
Could anyone show me how to implement this sort of template pleasEe?
Thanks in advance!
Sets and maps have different "add" constraints, so even though you say you want to ignore it, you'd be ignoring an essential difference between them: adding an object to a set can be done with just the object, but adding an object to a map requires an associated key.
You could utilize polymorphism and define two add methods, one for sets and one for maps. However, it seems fairly pointless since those collections already have such behavior defined.
IMHO this smells like a bad design. You should think deeper about your design before deciding to use this kind of method. A map and a set are very different things and usually they're not used for the same thing. It's better to overload the method instead, for example:
public static <T> void add(final T token, final Map<Whatever, T> holder)
public static <T> void add(final T token, final Set<T> holder)
Still one solution using polymorphism and generics could be as follows:
public static <T> void add(final T token, final Object holder) {
if (holder instanceof Map) {
final Map map = (Map) holder;
map.put(KEY, token); // Or whatever you want to do in this case
} else if (holder instanceof Set) {
final Set set = (Set) holder;
set.add(token);
} else {
throw new IllegalArgumentException("Holder is nor a Map neither a Set");
}
}
Note that this is unchecked, that is, the Map could be <String, String> and you're passing an Integer.
I definitely prefer the method overloading solution.
Related
I need a Map<> implementation that allows me to check values before they are stored in Map. The Map<> interface itself defines a lot of ways (methods) to put values in Map<>.
In HashMap<> implementation all those 'ways' go through a single method putVal(...) and that's the perfect place to put my checking code. However, the method is declared as 'final', so I can't subclass from HashMap and override it.
I'm mostly coding in C# and this problem is solved there in 3 mins. I'm actually very shocked right now, that I couldn't find a way to do this in Java.
How is it done? Do I really have to write my own full implementation of Map<>, or copy-paste HashMap<> source code and remove final before putVal?
I suggest you use decorator pattern instead of extending the HashMap:
public class CheckingMap<K, V> implements Map<K, V> {
private final Map<K, V> delegate;
public CheckingMap(Map<K, V> delegate) {
this.delegate = delegate;
}
public boolean put(K key, V value) {
// do the check
return delegate.put(key, value);
}
// etc
}
If implementing all the methods seems like a lot of code, you could use Dynamic proxy that allows you to intercept all calls through one handler - but IMO that's needlessly complicated in this case.
You could achieve this with a custom class e.g.
public class MySpecialHashMap{
private Map<> myActualMap;
public MySpecialHashMap() {
myActualMap = new HashMap<>();
}
public void putItem(Object key, Object value) {
// do your checks and add it to your map or not..
}
}
Besides that you could use generics to define the type.
Although I like Jiri's Decorator pattern idea, if you want support for an implementation, I'm not really sure what java classes you are using but the following works just fine for me.
class DerivedMap<V extends Object> extends HashMap {
#Override
public V put(Object key, Object value) {
// Do yada yada
return super.put(key, value);
}
}
I have a method that gets something from a hashmap, a simplified example (that doesn't make much sense but is good enough for now) is:
private Map<String,String> map = new HashMap<String,String>();
public String get(String key) {
return map.get(key);
}
This method can return a null when an entry doesn't exist for a given key obviously. The thing is, I want to annotate this method with #NonNull (because it is used in a gazillion places and I don't like Intellij spamming me with inspection warnings about producing a NPE and I don't want to turn off that inspection, and I also don't want to check whether the value returned is different than null everywhere I call this method. This is because I always use this method with a bunch of keys that are ALWAYS in the map. So due to the program logic this method is bound to return a #NonNull value.
I am tempted to just annotate it with a #NonNull, but who knows someone may call it with something other than the defined keys somewhere and actually cause a NullPointerException.
What would you do? An assertion sounds tempting to me.. Or would you just change the method to throw a RuntimException ? Or an AssertionError?
Thanks.
Edit:
here's the actual implementation:
/**
* Typesafe heterogeneous container pattern - implementation
*/
public class HandlersMap {
private final Map<Class<? extends TableHandler>, TableHandler> handlers;
public HandlersMap() {
handlers = new HashMap<Class<? extends TableHandler>, TableHandler>();
putHandler(RolesTableHandler.class, new RolesTableHandler());
putHandler(UsersTableHandler.class, new UsersTableHandler());
putHandler(DevicesTableHandler.class, new DevicesTableHandler());
}
private <T extends TableHandler> void putHandler(#NonNull final Class<T> type, #NonNull final T instance) {
handlers.put(type, type.cast(instance));
}
#NonNull
public <T extends TableHandler> T getHandler(#NonNull final Class<T> type) {
assert handlers.get(type) != null;
return type.cast(handlers.get(type));
}
public Collection<TableHandler> values() {
return handlers.values();
}
public int size() {
return handlers.size();
}
public Map<Class<? extends TableHandler>, TableHandler> getMap() {
return this.handlers;
}
}
Annotating with #Nonnull without verifying if the given key exists is definitely the wrong thing to do.
Since you seem to indicate that the given key is expected to exist, this means a missing key is an invalid argument, so checking for this case and throwing an IllegalArgumentException for missing elements would be the proper thing to do.
Alternatively, depending on how your map is initialized, you might want to consider creating an enum for your key values, use an EnumMap instead of a HashMap, and have your get() method take this enum rather than a free-form String. That way, you would have some compile-time checking to ensure proper values are used as well.
Even in that case though, you'd still need to check for existence, just in case the requested enum value is not yet added to the map.
I would like to add a collection of objects to an arrayList ,only if the particular attribute is not null.
I am thinking of extending the ArrayList and implementing the check inside the child class.
One alternate way is to check for the the attribute before putting it in a Arraylist, but that would mean , i will have to scatter the if checks every where if i need to add the objects to the arraylist based on the logic.
I would like to know your thoughts on it ... on a second thought is it a overkill ?
Decorator pattern
I would actually recommend wrapping ArrayList using well-documented Decorator pattern. You simply wrap your ArrayList with another List implementation that delegates most of the methods but adds validation logic:
public class ValidatingListDecorator extends AbstractList<MyBusinessObject>
{
private final List<MyBusinessObject> target;
public ValidatingListDecorator(List<MyBusinessObject> target) {
this.target = target;
}
#Override
public MyBusinessObject set(int index, MyBusinessObject element)
{
validate(element);
return target.set(index, element);
}
#Override
public boolean add(MyBusinessObject o)
{
validate(o);
return target.add(o);
}
//few more to implement
}
Advantages:
You can still access raw list without validation if you want (but you can restrict this)
Easier to stack different validations, turn them on and off selectively.
Promotes composition over inheritance as noted by #helios
Improves testability
Does not tie you to a specific List implementation, you can add validation to LinkedList or Hibernate-backed persistent lists. You can even think about generic Collection decorator to validate any collection.
Implementation notes
Despite the implementation remember there are quite a lot of methods you have to remember about while overriding: add(), addAll(), set(), subList() (?), etc.
Also your object must be immutable, otherwise the user can add/set valid object and modify it afterwards to violate the contract.
Good OO design
Finaly I wrote:
validate(element)
but consider:
element.validate()
which is a better design.
Stacking validations
As noted before if you want to stack validations, validating each proprty/apsect in a single, separate class, consider the following idiom:
public abstract class ValidatingListDecorator extends AbstractList<MyBusinessObject>
{
private final List<MyBusinessObject> target;
public ValidatingListDecorator(List<MyBusinessObject> target) {
this.target = target;
}
#Override
public MyBusinessObject set(int index, MyBusinessObject element)
{
validate(element);
return target.set(index, element);
}
protected abstract void validate(MyBusinessObject element);
}
...and few implementations:
class FooValidatingDecorator extends ValidatingListDecorator {
public FooValidatingDecorator(List<MyBusinessObject> target)
{
super(target);
}
#Override
protected void validate(MyBusinessObject element)
{
//throw if "foo" not met
}
}
class BarValidatingDecorator extends ValidatingListDecorator {
public BarValidatingDecorator(List<MyBusinessObject> target)
{
super(target);
}
#Override
protected void validate(MyBusinessObject element)
{
//throw if "bar" not met
}
}
Want to only validate foo?
List<MyBusinessObject> list = new FooValidatingDecorator(rawArrayList);
Want to validate both foo and bar?
List<MyBusinessObject> list =
new BarValidatingDecorator(new FooValidatingDecorator(rawArrayList));
If you would like to enforce this I don't see why not (although you should check the return value of the add method whenever you do add to make sure that it succeeded).
This is a good way to get rid of that redundant logic which may or may not stick around in later software iterations.
I don't think this is a good practice. Consider instead writing a Util-Method in a Util-Class taking two parameters: The array list and the object you would like to add. There you can check whatever you want and can reuse the logic all over your code.
Only issue would be if you go to reuse this code and you don't remember you've overriden the ArrayList class, make sure to comment thoroughly.
What is the best practice in implementing/providing getters/setters for a class containing a map?
The most common implementation I see is:
public class MyClass {
private Map<String, String> myMap;
public getMyMap() { /* Return an unmodifiable map */ }
public setMyMap(Map<String, String> myMap) { ... }
}
Or would it be better to provide an interface like:
public getMyMap() { /* Return a modifiable map */ }
public addToMap(String key, String value) { myMap.put(key, value); }
And why is such method better?
Both have their uses. The methods exposed by a class should be of a proper level of abstraction. For example if the class is a registry of dogs backed by a Map<String, Dog>, then it could provide methods like:
void addDog(String name, Dog dog);
Dog findByName(String name);
If it's say a rule engine that allows clients to specify the entire rule set in one call, then it could expose methods like:
void setRules(Map<String, Rule> rules);
Map<String, Rule> getRules();
In general I would say try not to return the map at all. Have a method that takes the key and returns the value. Taking a map is ok, as long as you copy it, but a method that takes the key/value and puts it into the map would be my preference.
If you must return the map you should return a read-only version or a copy of it. A set method should also copy the map.
It is a bad idea to allow callers to mutate the data inside of a class without the class knowing, passing or holding onto mutable data is a bad idea.
It totally depends on your requirement. This may suffice in most of the cases.
You may not even have a getter method that returns the map. If you use my plug-in, it may help you creating those methods : http://fast-code.sourceforge.net/documentation.htm#create-list-map as eclipse will not help you create the add method.
I would just provide one. Something like...
public Map<String,String> getMyMap()
{
return myMap;
}
and when you want to use it then
myClass.getMyMap().put(key,value);
DISCLAIMER: I did not compile this and test this answer ;)
I've been reading Effective Java and decided to try to put some of what I've learned into action. I'm trying to effectively create a Multimap<?, Condition<?> > where the wild card will be the same type for both the key and the value, but it will be different, distinct types.
Here is the item from the book I'm looking at: Item 29
I'm not trying to fully replicate it. I realize the big difference is the key does not represent the value directly as per the link. In mine, the key represents the generic type of the value.
So I will do mmap.put(Class<Integer>, ConditionMapping<Integer>)
when I do the get I don't have the generic type of the ConditionMapping, so I get the unchecked cast warning.
I have a get method that I want to have the signature <T> List<Condition <T> >(Class<T> type)
Due to type erasure, is my only option to make sure the condition.value is of type T and building a new list of objects?
I could just ignore the unchecked cast warning, but I'm just trying not to. Any suggestions? Tips? Tricks?
There is no way to express that the two wildcards should capture the same type. See this question for a similar situation and a number of possible solutions.
If you make your interface extend Multimap<Void, Condition<?>> it allows your user to call some of the methods that do not rely on type safety (e.g. containsKey) but not to add entries (bypassing your type-checked proxy methods) unless they use unchecked casts.
interface ConditionMapBase<T> extends Multimap<T, Condition<?>> {
}
interface ConditionMap extends ConditionMapBase<Void> {
<T>boolean putCondition(T key, Condition<T> value);
<T>Collection<Condition<T>> getConditions(T key);
}
class ConditionMapImpl
extends ForwardingMultimap<Void, Condition<?>>
implements ConditionMap {
ConditionMapImpl() {
delegate = HashMultimap.create();
}
#SuppressWarnings("unchecked")
#Override
protected Multimap<Void, Condition<?>> delegate() {
return (Multimap<Void, Condition<?>>) (Multimap<?, ?>) delegate;
}
private final Multimap<Object, Condition<?>> delegate;
#SuppressWarnings("unchecked")
#Override
public <T> Collection<Condition<T>> getConditions(T key) {
return (Collection<Condition<T>>) (Collection<?>) ((ConditionMapBase<T>) this).get(key);
}
#SuppressWarnings("unchecked")
#Override
public <T> boolean putCondition(T key, Condition<T> value) {
return ((ConditionMapBase<T>) this).put(key, value);
}
}
You could make a MyClass and then pass your own type to it, and ecapsulate the Multimap inside that. Template impossibilities in Java can often be solved by adding another layer, so to speak, and templating a class around what you really want, since you can get a "T" type that way, which you can then use for Lists or Maps, and guarantee that it is the same for multiple templates from then on.
This might be a step in the right direction.
<Multimap<Class<?>, Condition<?>>