View Javadoc
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    *      https://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  
19  import java.io.Serializable;
20  import java.util.Objects;
21  
22  import org.apache.commons.lang3.builder.CompareToBuilder;
23  
24  /**
25   * A triple consisting of three elements.
26   *
27   * <p>
28   * This class is an abstract implementation defining the basic API.
29   * It refers to the elements as 'left', 'middle' and 'right'.
30   * </p>
31   *
32   * <p>
33   * Subclass implementations may be mutable or immutable.
34   * However, there is no restriction on the type of the stored objects that may be stored.
35   * If mutable objects are stored in the triple, then the triple itself effectively becomes mutable.
36   * </p>
37   *
38   * @param <L> The left element type.
39   * @param <M> The middle element type.
40   * @param <R> The right element type.
41   * @since 3.2
42   */
43  public abstract class Triple<L, M, R> implements Comparable<Triple<L, M, R>>, Serializable {
44  
45      /** Serialization version */
46      private static final long serialVersionUID = 1L;
47  
48      /**
49       * An empty array.
50       * <p>
51       * Consider using {@link #emptyArray()} to avoid generics warnings.
52       * </p>
53       *
54       * @since 3.10
55       */
56      public static final Triple<?, ?, ?>[] EMPTY_ARRAY = {};
57  
58      /**
59       * Returns the empty array singleton that can be assigned without compiler warning.
60       *
61       * @param <L> The left element type.
62       * @param <M> The middle element type.
63       * @param <R> The right element type.
64       * @return The empty array singleton that can be assigned without compiler warning.
65       * @since 3.10
66       */
67      @SuppressWarnings("unchecked")
68      public static <L, M, R> Triple<L, M, R>[] emptyArray() {
69          return (Triple<L, M, R>[]) EMPTY_ARRAY;
70      }
71  
72      /**
73       * Obtains an immutable triple of three objects inferring the generic types.
74       *
75       * @param <L> The left element type.
76       * @param <M> The middle element type.
77       * @param <R> The right element type.
78       * @param left  The left element, may be null.
79       * @param middle The middle element, may be null.
80       * @param right  The right element, may be null.
81       * @return An immutable triple formed from the three parameters, not null.
82       */
83      public static <L, M, R> Triple<L, M, R> of(final L left, final M middle, final R right) {
84          return ImmutableTriple.of(left, middle, right);
85      }
86  
87      /**
88       * Obtains an immutable triple of three non-null objects inferring the generic types.
89       *
90       * @param <L> The left element type.
91       * @param <M> The middle element type.
92       * @param <R> The right element type.
93       * @param left  The left element, may not be null.
94       * @param middle  The middle element, may not be null.
95       * @param right  The right element, may not be null.
96       * @return An immutable triple formed from the three parameters, not null.
97       * @throws NullPointerException Thrown if any input is null.
98       * @since 3.13.0
99       */
100     public static <L, M, R> Triple<L, M, R> ofNonNull(final L left, final M middle, final R right) {
101         return ImmutableTriple.ofNonNull(left, middle, right);
102     }
103 
104     /**
105      * Constructs a new instance.
106      */
107     public Triple() {
108         // empty
109     }
110 
111     /**
112      * Compares the triple based on the left element, followed by the middle element,
113      * finally the right element.
114      * The types must be {@link Comparable}.
115      *
116      * @param other  The other triple, not null.
117      * @return negative if this is less, zero if equal, positive if greater.
118      */
119     @Override
120     public int compareTo(final Triple<L, M, R> other) {
121       return new CompareToBuilder().append(getLeft(), other.getLeft())
122           .append(getMiddle(), other.getMiddle())
123           .append(getRight(), other.getRight()).toComparison();
124     }
125 
126     /**
127      * Compares this triple to another based on the three elements.
128      *
129      * @param obj  The object to compare to, null returns false.
130      * @return true if the elements of the triple are equal.
131      */
132     @Override
133     public boolean equals(final Object obj) {
134         if (obj == this) {
135             return true;
136         }
137         if (obj instanceof Triple<?, ?, ?>) {
138             final Triple<?, ?, ?> other = (Triple<?, ?, ?>) obj;
139             return Objects.equals(getLeft(), other.getLeft())
140                 && Objects.equals(getMiddle(), other.getMiddle())
141                 && Objects.equals(getRight(), other.getRight());
142         }
143         return false;
144     }
145 
146     /**
147      * Gets the left element from this triple.
148      *
149      * @return The left element, may be null.
150      */
151     public abstract L getLeft();
152 
153     /**
154      * Gets the middle element from this triple.
155      *
156      * @return The middle element, may be null.
157      */
158     public abstract M getMiddle();
159 
160     /**
161      * Gets the right element from this triple.
162      *
163      * @return The right element, may be null.
164      */
165     public abstract R getRight();
166 
167     /**
168      * Returns a suitable hash code.
169      * <p>
170      * The hash code is adapted from the definition in {@code Map.Entry}.
171      * </p>
172      *
173      * @return The hash code.
174      */
175     @Override
176     public int hashCode() {
177         // See Map.Entry API specification
178         return Objects.hashCode(getLeft()) ^ Objects.hashCode(getMiddle()) ^ Objects.hashCode(getRight());
179     }
180 
181     /**
182      * Returns a String representation of this triple using the format {@code (left,middle,right)}.
183      *
184      * @return A string describing this object, not null.
185      */
186     @Override
187     public String toString() {
188         return "(" + getLeft() + "," + getMiddle() + "," + getRight() + ")";
189     }
190 
191     /**
192      * Formats the receiver using the given format.
193      *
194      * <p>
195      * This uses {@link java.util.Formattable} to perform the formatting. Three variables may
196      * be used to embed the left and right elements. Use {@code %1$s} for the left
197      * element, {@code %2$s} for the middle and {@code %3$s} for the right element.
198      * The default format used by {@code toString()} is {@code (%1$s,%2$s,%3$s)}.
199      * </p>
200      *
201      * @param format  The format string, optionally containing {@code %1$s}, {@code %2$s} and {@code %3$s}, not null.
202      * @return The formatted string, not null.
203      */
204     public String toString(final String format) {
205         return String.format(format, getLeft(), getMiddle(), getRight());
206     }
207 
208 }
209