1 /*
2 Copyright 2011 Atlassian
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15 */
16 package io.atlassian.fugue;
17
18 import java.io.Serializable;
19 import java.util.Optional;
20 import java.util.function.BiFunction;
21 import java.util.function.Function;
22
23 import static java.util.Objects.requireNonNull;
24
25 /**
26 * Represents a pair of objects.
27 *
28 * @since 1.0
29 */
30 public final class Pair<A, B> implements Serializable {
31 private static final long serialVersionUID = 3054071035067921893L;
32
33 private static final int HALF_WORD = 16;
34
35 /**
36 * Factory method for static Pair growth.
37 *
38 * @param <A> the left value type
39 * @param <B> the right value type
40 * @param left value, cannot be null
41 * @param right value, cannot be null
42 * @return the Pair containing the passed values
43 */
44 public static <A, B> Pair<A, B> pair(final A left, final B right) {
45 return new Pair<>(left, right);
46 }
47
48 /**
49 * Factory method for a Pair factory function.
50 *
51 * @param <A> the left value type
52 * @param <B> the right value type
53 * @return a function that constructs Pairs
54 */
55 public static <A, B> BiFunction<A, B, Pair<A, B>> pairs() {
56 return Pair::pair;
57 }
58
59 /**
60 * Function for accessing the left value of {@link Pair pairs}.
61 *
62 * @param <A> the left value type
63 * @return a Function that given a {@link io.atlassian.fugue.Pair} returns the
64 * left side value
65 * @since 1.1
66 */
67 public static <A> Function<Pair<A, ?>, A> leftValue() {
68 return Pair::left;
69 }
70
71 /**
72 * Function for accessing the right value of {@link Pair pairs}.
73 *
74 * @param <B> the right value type
75 * @return a Function that given a {@link io.atlassian.fugue.Pair} returns the
76 * right side value
77 * @since 1.1
78 */
79 public static <B> Function<Pair<?, B>, B> rightValue() {
80 return Pair::right;
81 }
82
83 /**
84 * Performs function application within an homogeneous pair (applicative
85 * functor pattern).
86 *
87 * @param aa an homogeneous pair
88 * @param ff The pair of functions to apply.
89 * @return A new pair after applying the given pair of functions through aa.
90 */
91 public static <A, B> Pair<B, B> ap(final Pair<A, A> aa, final Pair<Function<A, B>, Function<A, B>> ff) {
92 return Pair.pair(ff.left().apply(aa.left()), ff.right().apply(aa.right()));
93 }
94
95 /**
96 * Apply a function to both elements of an homogeneous pair.
97 *
98 * @param aa an homogeneous pair
99 * @param f function to apply to both elements of aa
100 * @return A new pair after applying the function to aa elements.
101 */
102 public static <A, B> Pair<B, B> map(final Pair<A, A> aa, final Function<A, B> f) {
103 return Pair.pair(f.apply(aa.left()), f.apply(aa.right()));
104 }
105
106 /**
107 * Zips two iterables into a single iterable that produces {@link Pair pairs}.
108 *
109 * @param <A> LHS type
110 * @param <B> RHS type
111 * @param as left values
112 * @param bs right values
113 * @return an {@link Iterable iterable} of pairs, only as long as the shortest
114 * input iterable.
115 * @since 1.1
116 */
117 public static <A, B> Iterable<Pair<A, B>> zip(final Iterable<A> as, final Iterable<B> bs) {
118 return Iterables.zip(as, bs);
119 }
120
121 /**
122 * Zips the two given optionals into an optional of a pair.
123 *
124 * @param oA the first optional
125 * @param oB the second optional
126 * @param <A> the first type
127 * @param <B> the second type
128 * @return empty if either or both optionals are empty
129 * @since 4.6.0
130 */
131 @SuppressWarnings("OptionalUsedAsFieldOrParameterType") public static <A, B> Optional<Pair<A, B>> zip(final Optional<A> oA, final Optional<B> oB) {
132 if (oA.isPresent() && oB.isPresent()) {
133 return Optional.of(pair(oA.get(), oB.get()));
134 }
135 return Optional.empty();
136 }
137
138 //
139 // members
140 //
141
142 private final A left;
143 private final B right;
144
145 /**
146 * Constructor for Pair.
147 *
148 * @param left value, cannot be null
149 * @param right value, cannot be null
150 */
151 public Pair(final A left, final B right) {
152 this.left = requireNonNull(left, "Left parameter must not be null.");
153 this.right = requireNonNull(right, "Right parameter must not be null.");
154 }
155
156 /**
157 * Accessor method for the left value of the pair.
158 *
159 * @return a A object.
160 */
161 public A left() {
162 return left;
163 }
164
165 /**
166 * Accessor method for the right value of the pair.q
167 *
168 * @return a B object.
169 */
170 public B right() {
171 return right;
172 }
173
174 /** {@inheritDoc} */
175 @Override public String toString() {
176 return "Pair(" + left + ", " + right + ")";
177 }
178
179 /** {@inheritDoc} */
180 @Override public boolean equals(final Object o) {
181 if (o == null) {
182 return false;
183 }
184 if (this == o) {
185 return true;
186 }
187
188 if (!(o instanceof Pair<?, ?>)) {
189 return false;
190 }
191 final Pair<?, ?> that = (Pair<?, ?>) o;
192 return left.equals(that.left) && right.equals(that.right);
193 }
194
195 /** {@inheritDoc} */
196 @Override public int hashCode() {
197 final int lh = left.hashCode();
198 final int rh = right.hashCode();
199 return (((lh >> HALF_WORD) ^ lh) << HALF_WORD) | (((rh << HALF_WORD) ^ rh) >> HALF_WORD);
200 }
201 }