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       * @param <L> the left element type.
72       * @param <M> the middle element type.
73       * @param <R> the right element type.
74       * @param left  the left element, may be null.
75       * @param middle the middle element, may be null.
76       * @param right  the right element, may be null.
77       * @return an immutable triple formed from the three parameters, not null.
78       */
79      public static <L, M, R> Triple<L, M, R> of(final L left, final M middle, final R right) {
80          return ImmutableTriple.of(left, middle, right);
81      }
82  
83      /**
84       * Obtains an immutable triple of three non-null objects inferring the generic types.
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 an immutable 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     /**
101      * Constructs a new instance.
102      */
103     public Triple() {
104         // empty
105     }
106 
107     /**
108      * Compares the triple based on the left element, followed by the middle element,
109      * finally the right element.
110      * The types must be {@link Comparable}.
111      *
112      * @param other  the other triple, not null.
113      * @return negative if this is less, zero if equal, positive if greater.
114      */
115     @Override
116     public int compareTo(final Triple<L, M, R> other) {
117       return new CompareToBuilder().append(getLeft(), other.getLeft())
118           .append(getMiddle(), other.getMiddle())
119           .append(getRight(), other.getRight()).toComparison();
120     }
121 
122     /**
123      * Compares this triple to another based on the three elements.
124      *
125      * @param obj  the object to compare to, null returns false.
126      * @return true if the elements of the triple are equal.
127      */
128     @Override
129     public boolean equals(final Object obj) {
130         if (obj == this) {
131             return true;
132         }
133         if (obj instanceof Triple<?, ?, ?>) {
134             final Triple<?, ?, ?> other = (Triple<?, ?, ?>) obj;
135             return Objects.equals(getLeft(), other.getLeft())
136                 && Objects.equals(getMiddle(), other.getMiddle())
137                 && Objects.equals(getRight(), other.getRight());
138         }
139         return false;
140     }
141 
142     /**
143      * Gets the left element from this triple.
144      *
145      * @return the left element, may be null.
146      */
147     public abstract L getLeft();
148 
149     /**
150      * Gets the middle element from this triple.
151      *
152      * @return the middle element, may be null.
153      */
154     public abstract M getMiddle();
155 
156     /**
157      * Gets the right element from this triple.
158      *
159      * @return the right element, may be null.
160      */
161     public abstract R getRight();
162 
163     /**
164      * Returns a suitable hash code.
165      * <p>
166      * The hash code is adapted from the definition in {@code Map.Entry}.
167      * </p>
168      *
169      * @return the hash code.
170      */
171     @Override
172     public int hashCode() {
173         // See Map.Entry API specification
174         return Objects.hashCode(getLeft()) ^ Objects.hashCode(getMiddle()) ^ Objects.hashCode(getRight());
175     }
176 
177     /**
178      * Returns a String representation of this triple using the format {@code (left,middle,right)}.
179      *
180      * @return a string describing this object, not null.
181      */
182     @Override
183     public String toString() {
184         return "(" + getLeft() + "," + getMiddle() + "," + getRight() + ")";
185     }
186 
187     /**
188      * Formats the receiver using the given format.
189      *
190      * <p>This uses {@link java.util.Formattable} to perform the formatting. Three variables may
191      * be used to embed the left and right elements. Use {@code %1$s} for the left
192      * element, {@code %2$s} for the middle and {@code %3$s} for the right element.
193      * The default format used by {@code toString()} is {@code (%1$s,%2$s,%3$s)}.</p>
194      *
195      * @param format  the format string, optionally containing {@code %1$s}, {@code %2$s} and {@code %3$s}, not null.
196      * @return the formatted string, not null.
197      */
198     public String toString(final String format) {
199         return String.format(format, getLeft(), getMiddle(), getRight());
200     }
201 
202 }
203