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