One of the things I've always missed in Java is a simple class to store a couple of objects. Of course, we have HashMap, Properties, arrays and what not but they are just overkill when trying to save just a simple relationship between two objects.
With the advent of Java 5 and generics, building a ValuePair class has become a trivial task...if you can understand generics, that is. In fact, with generics we have the situation where using them is pretty simple but building classes which use them can be a nightmare. The syntax is just complex and the abstraction level they require is high. Sun offers a good tutorial on the topic (and the JDK sources are a good start as well) but may be a simple example can be of better help, and the generic ValuePair class suits the bill perfectly.
The first step is to define the interface:
With the advent of Java 5 and generics, building a ValuePair class has become a trivial task...if you can understand generics, that is. In fact, with generics we have the situation where using them is pretty simple but building classes which use them can be a nightmare. The syntax is just complex and the abstraction level they require is high. Sun offers a good tutorial on the topic (and the JDK sources are a good start as well) but may be a simple example can be of better help, and the generic ValuePair class suits the bill perfectly.
The first step is to define the interface:
public interface Couple<A, B> {
public A getIndex();
public B getValue();
}
public A getIndex();
public B getValue();
}
The code is simple but it has subtle differences if the developer is not used to the Java 5 syntax. The first thing that has to be noticed is the use of <A, B> beside the name of the class or interface. This indicates that the class has two generic types that will need to be defined later. These types although unknown now will be available during compile time (when declaring variables). As you can see from the method declarations these types can be used along the class. Let's see an implementation:
public class ValuePair<A, B> implements Couple<A, B> {
private A a;
private B b;
public ValuePair(A a, B b) {
this.a = a;
this.b = b;
}
public A getIndex() {
return a;
}
public B getValue() {
return b;
}
}
private A a;
private B b;
public ValuePair(A a, B b) {
this.a = a;
this.b = b;
}
public A getIndex() {
return a;
}
public B getValue() {
return b;
}
}
Everything should be expected by now. The class implements a generified interface so it also includes the generic types. A couple of variables use these types as did the methods before. Things just get a little bit more interesting when subclassing our base class:
public class NameValuePair<T> extends ValuePair<String, T> {
public NameValuePair(String a, T b) {
super(a, b);
}
public String getName() {
return getIndex();
}
}
public NameValuePair(String a, T b) {
super(a, b);
}
public String getName() {
return getIndex();
}
}
In the code above some of the useful features of generics are visible. First of all, only one parameter is required! The other is automatically assumed to be String, as is indicated when establishing the inheritance. Notice how the parameter (T) is the same beside the class name and beside the superclass name!
The advantages of using generified classes are shown when using them. Let's see if it has been worth the trouble with some examples:
The advantages of using generified classes are shown when using them. Let's see if it has been worth the trouble with some examples:
List<Couple<Integer, Field>> fields = new ArrayList<Couple<Integer, Field>>();
Set<NameValuePair<Map<String, Date>>> setOfNamedMaps;
ValuePair<Object, Date>> = new ValuePair<Object, Date>>;
Set<NameValuePair<Map<String, Date>>> setOfNamedMaps;
ValuePair<Object, Date>> = new ValuePair<Object, Date>>;
Useful, isn't it?

