You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by sc...@apache.org on 2011/04/11 19:48:14 UTC

svn commit: r1091146 - in /commons/proper/lang/trunk/src: main/java/org/apache/commons/lang3/ test/java/org/apache/commons/lang3/

Author: scolebourne
Date: Mon Apr 11 17:48:14 2011
New Revision: 1091146

URL: http://svn.apache.org/viewvc?rev=1091146&view=rev
Log:
Enhance pair classes; Shorten toString form; Javadoc

Modified:
    commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/ImmutablePair.java
    commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/MutablePair.java
    commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/Pair.java
    commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/ImmutablePairTest.java
    commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/MutablePairTest.java
    commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/PairTest.java

Modified: commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/ImmutablePair.java
URL: http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/ImmutablePair.java?rev=1091146&r1=1091145&r2=1091146&view=diff
==============================================================================
--- commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/ImmutablePair.java (original)
+++ commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/ImmutablePair.java Mon Apr 11 17:48:14 2011
@@ -17,16 +17,23 @@
 package org.apache.commons.lang3;
 
 /**
- * Immutable concrete manifestation of the {@link Pair} type.
- *
+ * <p>An immutable pair consisting of two {@code Object} elements.</p>
+ * 
+ * <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. The class is also not {@code final}, so a subclass
+ * could add undesirable behaviour.</p>
+ * 
  * <p>#ThreadSafe# if the objects are threadsafe</p>
+ *
+ * @param <L> the first element type
+ * @param <R> the second element type
+ *
  * @since Lang 3.0
  * @version $Id$
- *
- * @param <L> left generic type
- * @param <R> right generic type
  */
 public class ImmutablePair<L, R> extends Pair<L, R> {
+
     /** Serialization version */
     private static final long serialVersionUID = 4954918890077093841L;
 
@@ -36,10 +43,26 @@ public class ImmutablePair<L, R> extends
     public final R right;
 
     /**
-     * Create a new ImmutablePair instance.
+     * <p>Obtains an immutable pair of from two objects inferring the generic types.</p>
+     * 
+     * <p>This factory allows the pair to be created using inference to
+     * obtain the generic types.</p>
+     * 
+     * @param <L> the left element type
+     * @param <R> the right element type
+     * @param left  the left element, may be null
+     * @param right  the right element, may be null
+     * @return a pair formed from the two parameters, not null
+     */
+    public static <L, R> ImmutablePair<L, R> of(L left, R right) {
+        return new ImmutablePair<L, R>(left, right);
+    }
+
+    /**
+     * Create a new pair instance.
      *
-     * @param left the left value
-     * @param right the right value
+     * @param left  the left value, may be null
+     * @param right  the right value, may be null
      */
     public ImmutablePair(L left, R right) {
         super();
@@ -47,6 +70,7 @@ public class ImmutablePair<L, R> extends
         this.right = right;
     }
 
+    //-----------------------------------------------------------------------
     /**
      * {@inheritDoc}
      */
@@ -64,29 +88,16 @@ public class ImmutablePair<L, R> extends
     }
 
     /**
-     * {@link java.util.Map.Entry#setValue(Object)} implementation. Because this
-     * class is immutable the {@code setValue()} operation is not supported.
-     * Therefore always an exception is thrown.
+     * <p>Throws {@code UnsupportedOperationException}.</p>
+     * 
+     * <p>This pair is immutable, so this operation is not supported.</p>
      *
-     * @param value the value to set
-     * @return the old right value
+     * @param value  the value to set
+     * @return never
      * @throws UnsupportedOperationException as this operation is not supported
      */
     public R setValue(R value) {
         throw new UnsupportedOperationException();
     }
 
-    /**
-     * Static fluent creation method for an {@link ImmutablePair}<L, R>:
-     * <code>ImmutablePair.of(left, right)</code>
-     *
-     * @param <L> the left generic type
-     * @param <R> the right generic type
-     * @param left the let value
-     * @param right the right value
-     * @return ImmutablePair<L, R>(left, right)
-     */
-    public static <L, R> ImmutablePair<L, R> of(L left, R right) {
-        return new ImmutablePair<L, R>(left, right);
-    }
 }

Modified: commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/MutablePair.java
URL: http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/MutablePair.java?rev=1091146&r1=1091145&r2=1091146&view=diff
==============================================================================
--- commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/MutablePair.java (original)
+++ commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/MutablePair.java Mon Apr 11 17:48:14 2011
@@ -17,55 +17,77 @@
 package org.apache.commons.lang3;
 
 /**
- * Mutable concrete manifestation of the {@link Pair} type.
+ * <p>A mutable pair consisting of two {@code Object} elements.</p>
+ * 
+ * <p>Not #ThreadSafe#</p>
+ *
+ * @param <L> the first element type
+ * @param <R> the second element type
  *
- * <p>#ThreadSafe# if the objects are threadsafe</p>
  * @since Lang 3.0
  * @version $Id$
- *
- * @param <L> left generic type
- * @param <R> right generic type
  */
 public class MutablePair<L, R> extends Pair<L, R> {
+
     /** Serialization version */
     private static final long serialVersionUID = 4954918890077093841L;
 
-    private L leftElement;
-    private R rightElement;
+    /** Left object */
+    public L left;
+    /** Right object */
+    public R right;
+
+    /**
+     * <p>Obtains an immutable pair of from two objects inferring the generic types.</p>
+     * 
+     * <p>This factory allows the pair to be created using inference to
+     * obtain the generic types.</p>
+     * 
+     * @param <L> the left element type
+     * @param <R> the right element type
+     * @param left  the left element, may be null
+     * @param right  the right element, may be null
+     * @return a pair formed from the two parameters, not null
+     */
+    public static <L, R> MutablePair<L, R> of(L left, R right) {
+        return new MutablePair<L, R>(left, right);
+    }
 
     /**
-     * Create a new MutablePair instance.
+     * Create a new pair instance of two nulls.
      */
     public MutablePair() {
         super();
     }
 
     /**
-     * Create a new MutablePair instance.
+     * Create a new pair instance.
      *
-     * @param leftElement the left value
-     * @param rightElement the right value
+     * @param left  the left value, may be null
+     * @param right  the right value, may be null
      */
-    public MutablePair(L leftElement, R rightElement) {
+    public MutablePair(L left, R right) {
         super();
-        this.leftElement = leftElement;
-        this.rightElement = rightElement;
+        this.left = left;
+        this.right = right;
     }
 
+    //-----------------------------------------------------------------------
     /**
      * {@inheritDoc}
      */
     @Override
     public L getLeftElement() {
-        return leftElement;
+        return left;
     }
 
     /**
      * Set the left element of the pair.
-     * @param leftElement the value of the left element
+     * 
+     * @param left  the new value of the left element, may be null
      */
-    public void setLeftElement(L leftElement) {
-        this.leftElement = leftElement;
+    public void setLeftElement(L left) {
+        this.left = left;
     }
 
     /**
@@ -73,20 +95,23 @@ public class MutablePair<L, R> extends P
      */
     @Override
     public R getRightElement() {
-        return rightElement;
+        return right;
     }
 
     /**
      * Set the right element of the pair.
-     * @param rightElement the value of the right element
+     * 
+     * @param right  the value of the right element
      */
-    public void setRightElement(R rightElement) {
-        this.rightElement = rightElement;
+    public void setRightElement(R right) {
+        this.right = right;
     }
 
     /**
-     * Implement {@link java.util.Map.Entry#setValue(Object)}.
-     * @param value value (<code>rightElement</code>) to set
+     * Sets the {@code Map.Entry} value.
+     * This sets the right element of the pair.
+     * 
+     * @param value  the right value to set, not null
      * @return the old value for the right element
      */
     public R setValue(R value) {
@@ -95,16 +120,4 @@ public class MutablePair<L, R> extends P
         return result;
     }
 
-    /**
-     * Static fluent creation method for a {@link MutablePair}<L, R>:
-     * <code>MutablePair.of(left, right)</code>
-     * @param <L> the left generic type
-     * @param <R> the right generic type
-     * @param left the left value
-     * @param right the right value
-     * @return MutablePair<L, R>(left, right)
-     */
-    public static <L, R> MutablePair<L, R> of(L left, R right) {
-        return new MutablePair<L, R>(left, right);
-    }
 }

Modified: commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/Pair.java
URL: http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/Pair.java?rev=1091146&r1=1091145&r2=1091146&view=diff
==============================================================================
--- commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/Pair.java (original)
+++ commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/Pair.java Mon Apr 11 17:48:14 2011
@@ -19,79 +19,142 @@ package org.apache.commons.lang3;
 import java.io.Serializable;
 import java.util.Map;
 
-import org.apache.commons.lang3.builder.HashCodeBuilder;
+import org.apache.commons.lang3.builder.CompareToBuilder;
 
 /**
- * Abstract Pair (or 2-element Tuple).
+ * <p>A pair consisting of two elements.</p>
+ * 
+ * <p>This class is an abstract implementation defining the basic API.
+ * It refers to the elements as 'left' and 'right'. It also implements the
+ * {@code Map.Entry} interface where the key is 'left' and the value is 'right'.</p>
+ * 
+ * <p>Subclass implementations may be mutable or immutable.
+ * However, there is no restriction on the type of the stored objects that may be stored.
+ * If mutable objects are stored in the pair, then the pair itself effectively becomes mutable.</p>
+ *
+ * @param <L> the first element type
+ * @param <R> the second element type
  *
  * @since Lang 3.0
  * @version $Id$
  */
-public abstract class Pair<L, R> implements Serializable, Map.Entry<L, R> {
+public abstract class Pair<L, R> implements Map.Entry<L, R>, Comparable<Pair<L, R>>, Serializable {
+
     /** Serialization version */
     private static final long serialVersionUID = 4954918890077093841L;
 
     /**
-     * Get the "left" element of the pair.
-     * @return L
+     * <p>Obtains an immutable pair of from two objects inferring the generic types.</p>
+     * 
+     * <p>This factory allows the pair to be created using inference to
+     * obtain the generic types.</p>
+     * 
+     * @param <L> the left element type
+     * @param <R> the right element type
+     * @param left  the left element, may be null
+     * @param right  the right element, may be null
+     * @return a pair formed from the two parameters, not null
+     */
+    public static <L, R> Pair<L, R> of(L left, R right) {
+        return new ImmutablePair<L, R>(left, right);
+    }
+
+    //-----------------------------------------------------------------------
+    /**
+     * <p>Gets the left element from this pair.</p>
+     * 
+     * <p>When treated as a key-value pair, this is the key.</p>
+     * 
+     * @return the left element, may be null
      */
     public abstract L getLeftElement();
 
     /**
-     * Get the "right" element of the pair.
-     * @return R
+     * <p>Gets the right element from this pair.</p>
+     * 
+     * <p>When treated as a key-value pair, this is the value.</p>
+     * 
+     * @return the right element, may be null
      */
     public abstract R getRightElement();
 
     /**
-     * Return {@link #getLeftElement()} as a {@link java.util.Map.Entry}'s key.
-     * @return L
+     * <p>Gets the key from this pair.</p>
+     * 
+     * <p>This method implements the {@code Map.Entry} interface returning the
+     * left element as the key.</p>
+     * 
+     * @return the left element as the key, may be null
      */
     public final L getKey() {
         return getLeftElement();
     }
 
     /**
-     * Return {@link #getRightElement()} as a {@link java.util.Map.Entry}'s value.
-     * @return R
+     * <p>Gets the value from this pair.</p>
+     * 
+     * <p>This method implements the {@code Map.Entry} interface returning the
+     * right element as the value.</p>
+     * 
+     * @return the right element as the value, may be null
      */
     public R getValue() {
         return getRightElement();
     }
 
+    //-----------------------------------------------------------------------
     /**
-     * {@inheritDoc}
+     * <p>Compares the pair based on the first element followed by the second element.
+     * The types must be {@code Comparable}.</p>
+     * 
+     * @param other  the other pair, not null
+     * @return negative if this is less, zero if equal, positive if greater
+     */
+    public int compareTo(Pair<L, R> other) {
+      return new CompareToBuilder().append(getLeftElement(), other.getLeftElement())
+              .append(getRightElement(), other.getRightElement()).toComparison();
+    }
+
+    /**
+     * <p>Compares this pair to another based on the two elements.</p>
+     * 
+     * @param obj  the object to compare to, null returns false
+     * @return true if the elements of the pair are equal
      */
     @Override
     public boolean equals(Object obj) {
         if (obj == this) {
             return true;
         }
-        if (obj instanceof Pair<?, ?> == false) {
-            return false;
+        if (obj instanceof Map.Entry<?, ?>) {
+            Map.Entry<?, ?> other = (Map.Entry<?, ?>) obj;
+            return ObjectUtils.equals(getKey(), other.getKey())
+                    && ObjectUtils.equals(getValue(), other.getValue());
         }
-        Pair<?, ?> other = (Pair<?, ?>) obj;
-        return ObjectUtils.equals(getLeftElement(), other.getLeftElement())
-                && ObjectUtils.equals(getRightElement(), other.getRightElement());
+        return false;
     }
 
     /**
-     * {@inheritDoc}
+     * <p>Returns a suitable hash code.
+     * The hash code follows the definition in {@code Map.Entry}.</p>
+     * 
+     * @return the hash code
      */
     @Override
     public int hashCode() {
-        // TODO should the hashCodeBuilder be seeded per concrete type?
-        return new HashCodeBuilder().append(getLeftElement()).append(getRightElement())
-                .toHashCode();
+        // see Map.Entry API specification
+        return (getKey() == null ? 0 : getKey().hashCode()) ^
+                (getValue() == null ? 0 : getValue().hashCode());
     }
 
     /**
-     * Returns a String representation of the Pair in the form: (L,R)
+     * <p>Returns a String representation of the Pair in the form: (L,R).</p>
+     * 
      * @return a string for this object
      */
     @Override
     public String toString() {
-        StringBuilder builder = new StringBuilder(this.getClass().getSimpleName());
+        StringBuilder builder = new StringBuilder();
         builder.append("(");
         builder.append(getLeftElement());
         builder.append(",");
@@ -100,16 +163,4 @@ public abstract class Pair<L, R> impleme
         return builder.toString();
     }
 
-    /**
-     * Static fluent creation method for a {@link Pair}<L, R>:
-     * <code>Pair.of(left, right)</code>
-     * @param <L> the left generic type
-     * @param <R> the right generic type
-     * @param left the left value
-     * @param right the right value
-     * @return ImmutablePair<L, R>(left, right)
-     */
-    public static <L, R> Pair<L, R> of(L left, R right) {
-        return new ImmutablePair<L, R>(left, right);
-    }
 }

Modified: commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/ImmutablePairTest.java
URL: http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/ImmutablePairTest.java?rev=1091146&r1=1091145&r2=1091146&view=diff
==============================================================================
--- commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/ImmutablePairTest.java (original)
+++ commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/ImmutablePairTest.java Mon Apr 11 17:48:14 2011
@@ -80,10 +80,10 @@ public class ImmutablePairTest {
 
     @Test
     public void testToString() throws Exception {
-        assertEquals("ImmutablePair(null,null)", ImmutablePair.of(null, null).toString());
-        assertEquals("ImmutablePair(null,two)", ImmutablePair.of(null, "two").toString());
-        assertEquals("ImmutablePair(one,null)", ImmutablePair.of("one", null).toString());
-        assertEquals("ImmutablePair(one,two)", ImmutablePair.of("one", "two").toString());
+        assertEquals("(null,null)", ImmutablePair.of(null, null).toString());
+        assertEquals("(null,two)", ImmutablePair.of(null, "two").toString());
+        assertEquals("(one,null)", ImmutablePair.of("one", null).toString());
+        assertEquals("(one,two)", ImmutablePair.of("one", "two").toString());
     }
 
     @Test

Modified: commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/MutablePairTest.java
URL: http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/MutablePairTest.java?rev=1091146&r1=1091145&r2=1091146&view=diff
==============================================================================
--- commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/MutablePairTest.java (original)
+++ commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/MutablePairTest.java Mon Apr 11 17:48:14 2011
@@ -88,10 +88,10 @@ public class MutablePairTest {
 
     @Test
     public void testToString() throws Exception {
-        assertEquals("MutablePair(null,null)", MutablePair.of(null, null).toString());
-        assertEquals("MutablePair(null,two)", MutablePair.of(null, "two").toString());
-        assertEquals("MutablePair(one,null)", MutablePair.of("one", null).toString());
-        assertEquals("MutablePair(one,two)", MutablePair.of("one", "two").toString());
+        assertEquals("(null,null)", MutablePair.of(null, null).toString());
+        assertEquals("(null,two)", MutablePair.of(null, "two").toString());
+        assertEquals("(one,null)", MutablePair.of("one", null).toString());
+        assertEquals("(one,two)", MutablePair.of("one", "two").toString());
     }
 
     @Test

Modified: commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/PairTest.java
URL: http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/PairTest.java?rev=1091146&r1=1091145&r2=1091146&view=diff
==============================================================================
--- commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/PairTest.java (original)
+++ commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/PairTest.java Mon Apr 11 17:48:14 2011
@@ -21,7 +21,9 @@ import static org.junit.Assert.assertFal
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
+import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Map.Entry;
 
 import org.junit.Test;
 
@@ -44,7 +46,7 @@ public class PairTest {
     }
 
     @Test
-    public void testCompatibility() throws Exception {
+    public void testCompatibilityBetweenPairs() throws Exception {
         Pair<Integer, String> pair = ImmutablePair.of(0, "foo");
         Pair<Integer, String> pair2 = MutablePair.of(0, "foo");
         assertEquals(pair, pair2);
@@ -59,8 +61,39 @@ public class PairTest {
     }
 
     @Test
+    public void testMapEntry() throws Exception {
+        Pair<Integer, String> pair = ImmutablePair.of(0, "foo");
+        HashMap<Integer, String> map = new HashMap<Integer, String>();
+        map.put(0, "foo");
+        Entry<Integer, String> entry = map.entrySet().iterator().next();
+        assertEquals(pair, entry);
+        assertEquals(pair.hashCode(), entry.hashCode());
+    }
+
+    @Test
+    public void testComparable1() throws Exception {
+        Pair<String, String> pair1 = Pair.of("A", "D");
+        Pair<String, String> pair2 = Pair.of("B", "C");
+        assertEquals(true, pair1.compareTo(pair1) == 0);
+        assertEquals(true, pair1.compareTo(pair2) < 0);
+        assertEquals(true, pair2.compareTo(pair2) == 0);
+        assertEquals(true, pair2.compareTo(pair1) > 0);
+    }
+
+    @Test
+    public void testComparable2() throws Exception {
+        Pair<String, String> pair1 = Pair.of("A", "C");
+        Pair<String, String> pair2 = Pair.of("A", "D");
+        assertEquals(true, pair1.compareTo(pair1) == 0);
+        assertEquals(true, pair1.compareTo(pair2) < 0);
+        assertEquals(true, pair2.compareTo(pair2) == 0);
+        assertEquals(true, pair2.compareTo(pair1) > 0);
+    }
+
+    @Test
     public void testToString() throws Exception {
         Pair<String, String> pair = Pair.of("Key", "Value");
-        assertEquals("ImmutablePair(Key,Value)", pair.toString());
+        assertEquals("(Key,Value)", pair.toString());
     }
+
 }