/** * Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.util.tuple; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.apache.commons.lang.ObjectUtils; import org.apache.commons.lang.builder.CompareToBuilder; import org.joda.beans.ImmutableBean; import com.opengamma.util.PublicAPI; /** * An immutable pair consisting of two elements. * <p> * This implementation refers to the elements as 'first' and 'second'. * The class also implements the {@code Map.Entry} interface where the key is 'first' * and the value is 'second'. * <p> * Although the implementation is immutable, there is no restriction on the objects * that may be stored. If mutable objects are stored in the pair, then the pair itself * effectively becomes mutable. * * @param <A> the first element type * @param <B> the second element type */ @PublicAPI public abstract class Pair<A, B> implements ImmutableBean, Map.Entry<A, B>, Comparable<Pair<A, B>>, Serializable { // this ImmutableBean is not auto-generated /** Serialization version. */ private static final long serialVersionUID = 1L; /** * Creates a pair of {@code Object}s inferring the types. * * @param <A> the first element type * @param <B> the second element type * @param first the first element, may be null * @param second the second element, may be null * @return a pair formed from the two parameters, not null * @deprecated Use {@link Pairs#of(Object, Object)} or {@link ObjectsPair#of(Object, Object)} */ @Deprecated public static <A, B> ObjectsPair<A, B> of(A first, B second) { return ObjectsPair.of(first, second); } /** * Creates a pair of {@code Double}s. * * @param first the first element, may be null * @param second the second element, may be null * @return a pair formed from the two parameters, not null * @deprecated Use {@link Pairs#of(Double, double)} or {@link ObjectsPair#of(Object, Object)} */ @Deprecated public static ObjectsPair<Double, Double> of(Double first, double second) { return ObjectsPair.of(first, (Double) second); } /** * Creates a pair of {@code Double}s. * * @param first the first element, may be null * @param second the second element, may be null * @return a pair formed from the two parameters, not null * @deprecated Use {@link Pairs#of(double, Double)} or {@link ObjectsPair#of(Object, Object)} */ @Deprecated public static ObjectsPair<Double, Double> of(double first, Double second) { return ObjectsPair.of((Double) first, second); } /** * Creates a pair of {@code double}s. * * @param first the first element, may be null * @param second the second element, may be null * @return a pair formed from the two parameters, not null * @deprecated Use {@link Pairs#of(double, double)} or {@link DoublesPair#of(double, double)} */ @Deprecated public static DoublesPair of(double first, double second) { return DoublesPair.of(first, second); } /** * Creates a pair of {@code int} to {@code double}. * * @param first the first element, may be null * @param second the second element, may be null * @return a pair formed from the two parameters, not null * @deprecated Use {@link Pairs#of(int, double)} or {@link IntDoublePair#of(long, double)} */ @Deprecated public static IntDoublePair of(int first, double second) { return IntDoublePair.of(first, second); } /** * Creates a pair of {@code long} to {@code double}. * * @param first the first element, may be null * @param second the second element, may be null * @return a pair formed from the two parameters, not null * @deprecated Use {@link Pairs#of(long, double)} or {@link LongDoublePair#of(long, double)} */ @Deprecated public static LongDoublePair of(long first, double second) { return LongDoublePair.of(first, second); } /** * Constructs a pair. */ protected Pair() { } //------------------------------------------------------------------------- /** * Gets the first element from this pair. * <p> * When treated as a key-value pair, this is the key. * * @return the first element, may be null */ public abstract A getFirst(); /** * Gets the second element from this pair. * <p> * When treated as a key-value pair, this is the value. * * @return the second element, may be null */ public abstract B getSecond(); /** * Gets the key from this pair. * <p> * This method implements the {@code Map.Entry} interface returning the * first element as the key. * * @return the first element as the key, may be null */ @Override public A getKey() { return getFirst(); } /** * Gets the value from this pair. * <p> * This method implements the {@code Map.Entry} interface returning the * second element as the value. * * @return the second element as the value, may be null */ @Override public B getValue() { return getSecond(); } /** * Throws {@code UnsupportedOperationException} as this class is immutable. * * @param value the new value, may be null * @return never */ @Override public B setValue(B value) { throw new UnsupportedOperationException("Pair is immutable"); } //------------------------------------------------------------------------- /** * Gets the elements from this pair as a list. * <p> * This method supports auto-casting as they is no way in generics to provide * a more specific type. * * @param <T> an auto-cast list type * @return the elements as a list, not null */ @SuppressWarnings("unchecked") public <T> List<T> toList() { ArrayList<Object> list = new ArrayList<Object>(); list.add(getFirst()); list.add(getSecond()); return (List<T>) list; } /** * Clones this pair, returning an independent copy. * <p> * Pair subclasses must be immutable, so {@code this} is returned. * * @return the clone, not null */ @Override public Pair<A, B> clone() { return this; } //------------------------------------------------------------------------- /** * Compares the pair based on the first element followed by the second element. * <p> * A Pair <i>(x<sub>1</sub>, y<sub>1</sub>)</i> is less than another pair * <i>(x<sub>2</sub>, y<sub>2</sub>)</i> if one of these is true:<br /> * <i>x<sub>1</sub> < x<sub>2</sub></i><br> * <i>x<sub>1</sub> = x<sub>2</sub></i> and <i>y<sub>1</sub> < y<sub>2</sub></i> * <p> * The element types must be {@code Comparable}. * * @param other the other pair, not null * @return negative if this is less, zero if equal, positive if greater */ @Override public int compareTo(Pair<A, B> other) { return new CompareToBuilder() .append(getFirst(), other.getFirst()) .append(getSecond(), other.getSecond()) .toComparison(); } @Override public boolean equals(Object obj) { // see Map.Entry API specification if (this == obj) { return true; } if (obj instanceof Map.Entry<?, ?>) { Map.Entry<?, ?> other = (Map.Entry<?, ?>) obj; return ObjectUtils.equals(getKey(), other.getKey()) && ObjectUtils.equals(getValue(), other.getValue()); } return false; } @Override public int hashCode() { // see Map.Entry API specification return (getKey() == null ? 0 : getKey().hashCode()) ^ (getValue() == null ? 0 : getValue().hashCode()); } @Override public String toString() { return new StringBuilder() .append("[") .append(getFirst()) .append(", ") .append(getSecond()) .append("]").toString(); } }