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 ;)
Related
I would like to know if there is a more efficient way of storing values (like fields) for an instance of an interface (if implementing it is not guaranteed) than a static hashmap in an other non-visible class.
Example:
public interface myInterface {
public default Object getMyVariable() {
return Storage.data.get(this);
}
}
final class Storage {
static HashMap<myInterface, Object> data = new HashMap<myInterface, Object>();
}
Firs of all this is bad bracrice - you abstraction knows about implementations. The point of interface is to introduce abstraction - and get rig of rigit design.
You can define interface like that:
public interface MyInterface {
default Object getMyVariable() {
return getDefaultObject();
}
Object getDefaultObject()
}
As you can see i added required method getDefaultObject() - that all implementations have to implement. However this will not work if you already have implementation classes - and you have no control over them.
I have a class which basically just contains a HashMap.
The class also has a simple getter method which allows other parts of my application to send the "key" and get back the value from the map.
That much works, however, I don't want to keep instantiating that class every time I need to access it, because this particular data doesn't really change, and I only want it in the map for the sake of querying it quickly for the value I need.
I would like my main application class to create an instance of this, and then have it be available to all of my other classes automatically.
I have been reading about this a lot this morning, but am kind of confused about how it could be achieved, am I trying to do some sort of singleton? Or am I trying to use a service?
Anyway, if anyone has a snippet I can learn from - that would really help me out. I am currently using Annotations for most stuff in spring, and would LIKE to keep it that way.
I think you may not even need a separate class to hold your map. Directly create a bean of the Map which you may want and then Autowire the map where ever you need them.
#Configuration
public class MapConfiguration {
#Bean
public Map<String, Object> dataMap() {
// Create and return your Map here
}
}
Whereever you want your map, just use autowiring.
#Autowired
#Qualifier("dataMap")
private Map<String, Object> dataMap;
If you want to continue to use Spring, you can use the #Component to create a simple component. By default all components are singletons. You can use the #PostConstruct to initialize the data. Below is an example. I'm using a String as the map key, but you can modify it to match your application.
#Component
public class MyMap {
private Map<String, Object> theMap = new HashMap<>();
// PostConstruct runs after the application context instantiates the bean
#PostConstruct
public void init() {
// initialize the data in theMap
}
public Object get(String key) {
return theMap.get(key);
}
}
You can then use the #Autowired annotation or your application context to retrieve the bean:
public class AnotherClass {
#Autowired
MyMap myMap;
// ...
}
If you would like to avoid Spring, another option is to create a simple Java singleton. Here's an example
public class MyMap {
private final static Map<String, Object> theMap = new HashMap<>();
// Use a static block to initialize the map with data
static {
// populate theMap with data
}
public Object get(String key) {
return theMap.get(key);
}
}
One thing to note is that if your map ever does actually get updated, then you will need to handle concurrent reads and updates.
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.
How to create a class that add some stuff to a map and display it.
I was wondering about the best interface considering that all the code usually need to be covered with unit tests and it's a problem to test a method that display data.
This was my first thought:
class MyFirstProgram {
private Map<String, String> map = new HashMap<String,String>();
public int insertData(...) {...}
public void displayData(...) {...}
}
...but it's not possible to test anything about the retrieval and there is this display method... so I thougt this:
class MyFirstProgram {
private Map<String, String> map = new HashMap<String,String>();
public int insertData(...) {...}
private Map<String, String> retrieveData(...) {...}
public int displayData(...) {...call ; return status}
}
In this it's possible to test the private method with reflection but there is still this display method...
Any idea about the design?
The pragmatic way is to allow access to the Map (via a default/package access method with a comment // for unit tests, and access that. Actually, even better, name the method forUnitTestGetMap() to make it extra clear and avoid confusion with the standard getXXX naming convention. I'm usually fine with just calling toString() on the Map and comparing to what it should be, YMMV. If your insertData() is just calling standard methods on HashMap (e.g. put()) there isn't that much you can and should test, as most of the code is Java library code.
Alternatively, in the displayData() method, does it create an alternative representation of the Data? Such as XML, JSON, maybe a JPanel? If so, look at that to see that the contents of the Data are correct. Obviously XML is much easier than a JPanel for that, but you can still do something like checking that the JPanel has 3 children and the first is a Button named "OK"...
You can try creating getter and setter for the Map variable.
class MyFirstProgram {
private Map<String, String> map = new HashMap<String,String>();
public setMap(Map data) {...}
public Map getMap(...) {...}
}
And then wherever you want to print the map value use getMap method.
If you don't want to use the setters and getters we can have any method which takes a Map as input and print it.
public void PrintMap(Map data){print(data)}
I am computing statistics grouped by an attribute. For each category of this attribute (given as Strings) I get values which I want to aggregate.
For this, I need a map from category to DescriptiveStatistics (provided by org.apache.commons.math.stat.descriptive). In this map, I'd have to check if, for a given category, the corresponding DescriptiveStatistics have been created yet. This check, and the creation of the new DescriptiveStatistics, should be done by the map.
I tested Apache's LazyMap, but the non-genericity led me to Guava's LoadingCache. Something along these lines works for me:
LoadingCache<String, DescriptiveStatistics> groupedStats =
CacheBuilder.newBuilder()
.build(new CacheLoader<String, DescriptiveStatistics>() {
#Override
public DescriptiveStatistics load(String key) {
return new DescriptiveStatistics();
}
});
Is there a less "wordy" solution? One that wouldn't require me to throw in an anonymous class just for instantiating objects?
Your original code is exactly the code the Guava team would like you to write.
We tend to avoid reflection (except, naturally, in com.google.common.reflect). It tends to be fragile and lose the benefits of compile-time checking -- if a particular class doesn't have a public no-arg constructor, and you used clazz.newInstance(), you wouldn't find that out until runtime. Writing the direct implementation might cost you a line or two, but we consider the benefits worth it.
I you want to have less wordy solution create a class that you will used for your cache.
As someone design API can not always make happy every one. Guava cache is very flexiple and adaptable. And the additional few code of line should not be a problem.
This is my idea of reducing wordiness in user code: A class Creator<T> that does just what it says.
LoadingCache<String, SummaryStatistics> groupedStats =
CacheBuilder.newBuilder().build(
CacheLoader.from(Creators.of(SummaryStatistics.class)));
I was wondering if such a beast exists; I couldn't find it in the classes implementing Supplier<T>. Here's a possible implementation, all classes in the same package:
import com.google.common.base.Supplier;
public class Creator<T> implements Supplier<T> {
private Class<T> class1;
Creator(Class<T> class1) {
this.class1 = class1;
}
#Override
public T get() {
try {
return class1.newInstance();
} catch (Exception e) {
throw new RuntimeException(
"Cannot instantiate object of type "
+ class1.getCanonicalName(),
e);
}
}
}
public class Creators {
public static <T> Creator<T> of(Class<T> class1) {
return new Creator<T>(class1);
}
}
Of course this could be generalized to using constructors with arguments.