On Fri, Mar 4, 2011 at 5:41 AM, Stephen Colebourne <scolebou...@joda.org> wrote: > I now have authoristion from OpenGamma to discuss adding a Pair class > to [lang] based on our internal classes. If necessary a CCLA can be > signed, although since we are not necessarily importing the OpenGamma > classes as is and I'd be writing code in [lang3] with my Apache hat > on, the CCLA might not be needed. I can also code it in work time :-) > > The main goal would be either an abstract class or an interface for > Pair. We chose an abstract class so that it could have factory > methods: > > Pair<String, Number> p = Pair.of("Foo", 6); > > It also allowed more control over the immutability of Pair (although > because its abstract and holds references to any object, immutability > cannot be guaranteed). > > We then have other concrete classes: > - ObjectsPair - two generified objects > - DoublePair - two double > - IntDoublePair - int and double > - LongDoublePair - long and double > - IntObjectPair - int and generified object > - LongObjectPair - long and generified object > > Clearly there are many more possible combinations, but some make less > sense than others. (Booleans don't waste space, as they are a > singleton reference, short/float are rarely used) > > Beyond this, there are some standard comparators. > > Design wise, we implement Map.Entry (makes sense). The primitive > classes implement primitive map entry interfaces from another library, > but that wouldn't make sense here. They are comparable and > serializable (again, one reason for an abstract class). > > We name our elements "first" and "second". > > The elements are available by methods (for generics) or as public > final variables from the concrete classes (not the abstract one). The > methods are getFirst(), getSecond() plus getKey() and getValue() for > Map compatibility. > > The pairs are implemented as immutable. I saw someone mention the > possibility of a mutable pair, so perhaps we consider that. > > I don't want this to be a long process of design or implementation! If > there isn't rapid consensus, I'd suggest either shipping [lang3] with > or without the existing class. > > Opinions?
I agree that it would be nice to do whatever we're going to do quickly, and ship with *something*. On the other hand, I don't want to ship the existing class without consensus on design, only to give ourselves (and users) headaches trying to replace it in a subsequent release. I also had the thought that the abstract class would be necessary for the factory methods. It doesn't seem important, but I'd really like to be able to say Pair.of(X, Y). Semantically it'd also be nice to be able to use fields on the immutable variety of Pair (it's perhaps debatable in light of JIT whether the final field access yields better performance, so I won't address it--but it *looks* faster :P ), while still requiring the client to know as little as possible about the RT type of the Pair. Is it possible to accomplish all these things? abstract class Pair<L, R> implements Map.Entry<L, R> { abstract L getLeft(); abstract R getRight(); final L getKey() { return getLeft(); } final R getValue() { return getRight(); } static <L, R> ImmutablePair<L, R> of(L, R) {} } class ImmutablePair<L, R> extends Pair<L, R> { final L left; final R right; ImmutablePair(L left, R right) { this.left = left; this.right = right; } L getLeft() { return left; } R getRight() { return right; } static <L, R> ImmutablePair<L, R> of(L, R) {} } class MutablePair<L, R> extends Pair<L, R> { private L left; private R right; MutablePair(L left, R right) { setLeft(left); setRight(right); } L getLeft() { return left; } setLeft(L left) { this.left = left; } R getRight() { return right; } setRight(R right) { this.right = right; } static <L, R> MutablePair<L, R> of(L, R) {} } In the examples above I continue to use the left/right idiom for reasons of inertia; in the end, I don't *really* care. It seems examples abound of the various proposed paired names in other programming contexts, so this becomes a simple matter of taste and/or majority rules. Personally I prefer left/right as there is less connotation of priority given either member of the pair as (IMO) in the case of first/second. If we want to extend ImmutablePair for the wrapper types (it wouldn't seem to make sense to provide access to the primitive equivalent values in the MutablePair variety), where does it end? If we provide any such pair types, IMO we should use some predictable rule to define, for a given wrapper type, what combinations are available, e.g.: * X Double * X Boolean * X Object * X self * X * ? I'm sure I don't have to tell any of my fellow Commons committers that our components may well have to provide more implementations, or none at all, compared to equivalent proprietary code, for reasons of perceived "completeness." If anything this is even more so in the case of [lang] than perhaps some other Commons components. Matt > > Stephen > > --------------------------------------------------------------------- > To unsubscribe, e-mail: dev-unsubscr...@commons.apache.org > For additional commands, e-mail: dev-h...@commons.apache.org > > --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@commons.apache.org For additional commands, e-mail: dev-h...@commons.apache.org