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