Re: Encapsulating HashMap bulding
On Tue, 11 May 2010, Robert Klemme wrote:
On 11.05.2010 00:20, Roedy Green wrote:
Can anyone think of a way to write a method that takes an array of X,
and produces a HashMap<Key,X>
How would you specify the name of the key field/method?
Maybe you could do it by making X implement an interface that defines
the key.
Perhaps you could do it with reflection.
I'd rather provide an interface that is responsible for the conversion from X
to Key - this is more modular.
That's what i'd do too. Many winters ago, i faced the same problem, and
ended up doing it the interface way - i required my elements to implement:
public interface Keyed {
public Object getKey(); // this was before generics!
}
And then wrote code to build a map using the keys derived from supplied
values. Having had years to digest that design, i now think a separate
key-derivation function is a better idea.
Incidentally, you could use Robert's approach to wrap the reflective
approach easily:
public class KeyExtractor<A, B> implements Transformer<A, B> {
private Method getter;
private KeyExtractor(Class<A> a, String methodName, Class<B> b) {
Method method = a.getMethod(methodName);
if (!b.isAssignableFrom(method.getReturnType())) throw new IllegalArgumentException("bad return type from getter");
this.getter = method;
}
@SuppressWarnings("unchecked")
public B transform (A obj) {
return (B)method.invoke(obj);
}
}
Now you can say:
Customer[] customers;
MapUtil.createHash(customers, new KeyExtractor(Customers.class, "getSalesman", Salesman.class));
Which is amazingly wordy, so maybe you wouldn't bother.
I initially thought Roedy wanted a method to create maps from explicit
lists of keys and values, and wrote this:
public static <K, V> Map<K, V> mapWith(K[] keys, V[] values) {
if (keys.length != values.length) throw new IllegalArgumentException("different number of keys and values");
Map<K, V> map = new LinkedHashMap<K, V>(keys.length);
for (int i = 0; i < keys.length; ++i) {
map.put(keys[i], values[i]);
}
return map;
}
public static <K> K[] keys(K... keys) {
return keys;
}
public static <V> V[] values(V... values) {
return values;
}
example after suitable static imports: mapWith(keys(1, 2, 3), values("one", "two", "three"))
But that's not what he wanted.
tom
--
But in the week its like Urbino under the wise rule of Count Federico,
only with a better football team and the nations most pleb-infested
Waitrose. And shops selling size 12 stilettos. -- Jelb, on Holloway