Triple.java

  1. /*
  2.  * Licensed to the Apache Software Foundation (ASF) under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * The ASF licenses this file to You under the Apache License, Version 2.0
  6.  * (the "License"); you may not use this file except in compliance with
  7.  * the License.  You may obtain a copy of the License at
  8.  *
  9.  *      http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */
  17. package org.apache.commons.lang3.tuple;

  18. import java.io.Serializable;
  19. import java.util.Objects;

  20. import org.apache.commons.lang3.builder.CompareToBuilder;

  21. /**
  22.  * A triple consisting of three elements.
  23.  *
  24.  * <p>This class is an abstract implementation defining the basic API.
  25.  * It refers to the elements as 'left', 'middle' and 'right'.</p>
  26.  *
  27.  * <p>Subclass implementations may be mutable or immutable.
  28.  * However, there is no restriction on the type of the stored objects that may be stored.
  29.  * If mutable objects are stored in the triple, then the triple itself effectively becomes mutable.</p>
  30.  *
  31.  * @param <L> the left element type
  32.  * @param <M> the middle element type
  33.  * @param <R> the right element type
  34.  *
  35.  * @since 3.2
  36.  */
  37. public abstract class Triple<L, M, R> implements Comparable<Triple<L, M, R>>, Serializable {

  38.     /** Serialization version */
  39.     private static final long serialVersionUID = 1L;

  40.     /**
  41.      * An empty array.
  42.      * <p>
  43.      * Consider using {@link #emptyArray()} to avoid generics warnings.
  44.      * </p>
  45.      *
  46.      * @since 3.10.
  47.      */
  48.     public static final Triple<?, ?, ?>[] EMPTY_ARRAY = {};

  49.     /**
  50.      * Returns the empty array singleton that can be assigned without compiler warning.
  51.      *
  52.      * @param <L> the left element type
  53.      * @param <M> the middle element type
  54.      * @param <R> the right element type
  55.      * @return the empty array singleton that can be assigned without compiler warning.
  56.      *
  57.      * @since 3.10.
  58.      */
  59.     @SuppressWarnings("unchecked")
  60.     public static <L, M, R> Triple<L, M, R>[] emptyArray() {
  61.         return (Triple<L, M, R>[]) EMPTY_ARRAY;
  62.     }

  63.     /**
  64.      * Obtains an immutable triple of three objects inferring the generic types.
  65.      *
  66.      * <p>This factory allows the triple to be created using inference to
  67.      * obtain the generic types.</p>
  68.      *
  69.      * @param <L> the left element type
  70.      * @param <M> the middle element type
  71.      * @param <R> the right element type
  72.      * @param left  the left element, may be null
  73.      * @param middle the middle element, may be null
  74.      * @param right  the right element, may be null
  75.      * @return a triple formed from the three parameters, not null
  76.      */
  77.     public static <L, M, R> Triple<L, M, R> of(final L left, final M middle, final R right) {
  78.         return ImmutableTriple.of(left, middle, right);
  79.     }

  80.     /**
  81.      * Obtains an immutable triple of three non-null objects inferring the generic types.
  82.      *
  83.      * <p>This factory allows the triple to be created using inference to
  84.      * obtain the generic types.</p>
  85.      *
  86.      * @param <L> the left element type
  87.      * @param <M> the middle element type
  88.      * @param <R> the right element type
  89.      * @param left  the left element, may not be null
  90.      * @param middle  the middle element, may not be null
  91.      * @param right  the right element, may not be null
  92.      * @return a triple formed from the three parameters, not null
  93.      * @throws NullPointerException if any input is null
  94.      * @since 3.13.0
  95.      */
  96.     public static <L, M, R> Triple<L, M, R> ofNonNull(final L left, final M middle, final R right) {
  97.         return ImmutableTriple.ofNonNull(left, middle, right);
  98.     }

  99.     /**
  100.      * Constructs a new instance.
  101.      */
  102.     public Triple() {
  103.         // empty
  104.     }

  105.     /**
  106.      * Compares the triple based on the left element, followed by the middle element,
  107.      * finally the right element.
  108.      * The types must be {@link Comparable}.
  109.      *
  110.      * @param other  the other triple, not null
  111.      * @return negative if this is less, zero if equal, positive if greater
  112.      */
  113.     @Override
  114.     public int compareTo(final Triple<L, M, R> other) {
  115.       return new CompareToBuilder().append(getLeft(), other.getLeft())
  116.           .append(getMiddle(), other.getMiddle())
  117.           .append(getRight(), other.getRight()).toComparison();
  118.     }

  119.     /**
  120.      * Compares this triple to another based on the three elements.
  121.      *
  122.      * @param obj  the object to compare to, null returns false
  123.      * @return true if the elements of the triple are equal
  124.      */
  125.     @Override
  126.     public boolean equals(final Object obj) {
  127.         if (obj == this) {
  128.             return true;
  129.         }
  130.         if (obj instanceof Triple<?, ?, ?>) {
  131.             final Triple<?, ?, ?> other = (Triple<?, ?, ?>) obj;
  132.             return Objects.equals(getLeft(), other.getLeft())
  133.                 && Objects.equals(getMiddle(), other.getMiddle())
  134.                 && Objects.equals(getRight(), other.getRight());
  135.         }
  136.         return false;
  137.     }

  138.     /**
  139.      * Gets the left element from this triple.
  140.      *
  141.      * @return the left element, may be null
  142.      */
  143.     public abstract L getLeft();

  144.     /**
  145.      * Gets the middle element from this triple.
  146.      *
  147.      * @return the middle element, may be null
  148.      */
  149.     public abstract M getMiddle();

  150.     /**
  151.      * Gets the right element from this triple.
  152.      *
  153.      * @return the right element, may be null
  154.      */
  155.     public abstract R getRight();

  156.     /**
  157.      * Returns a suitable hash code.
  158.      *
  159.      * @return the hash code
  160.      */
  161.     @Override
  162.     public int hashCode() {
  163.         return Objects.hashCode(getLeft()) ^ Objects.hashCode(getMiddle()) ^ Objects.hashCode(getRight());
  164.     }

  165.     /**
  166.      * Returns a String representation of this triple using the format {@code ($left,$middle,$right)}.
  167.      *
  168.      * @return a string describing this object, not null
  169.      */
  170.     @Override
  171.     public String toString() {
  172.         return "(" + getLeft() + "," + getMiddle() + "," + getRight() + ")";
  173.     }

  174.     /**
  175.      * Formats the receiver using the given format.
  176.      *
  177.      * <p>This uses {@link java.util.Formattable} to perform the formatting. Three variables may
  178.      * be used to embed the left and right elements. Use {@code %1$s} for the left
  179.      * element, {@code %2$s} for the middle and {@code %3$s} for the right element.
  180.      * The default format used by {@code toString()} is {@code (%1$s,%2$s,%3$s)}.</p>
  181.      *
  182.      * @param format  the format string, optionally containing {@code %1$s}, {@code %2$s} and {@code %3$s}, not null
  183.      * @return the formatted string, not null
  184.      */
  185.     public String toString(final String format) {
  186.         return String.format(format, getLeft(), getMiddle(), getRight());
  187.     }

  188. }