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.function.BiFunction;
20 import java.util.function.Function;
21
22 import static java.util.Objects.requireNonNull;
23
24 /**
25 * Represents a pair of objects.
26 *
27 * @since 1.0
28 */
29 public final class Pair<A, B> implements Serializable {
30 private static final long serialVersionUID = 3054071035067921893L;
31
32 private static final int HALF_WORD = 16;
33
34 /**
35 * Factory method for static Pair growth.
36 *
37 * @param <A> the left value type
38 * @param <B> the right value type
39 * @param left value, cannot be null
40 * @param right value, cannot be null
41 * @return the Pair containing the passed values
42 */
43 public static <A, B> Pair<A, B> pair(final A left, final B right) {
44 return new Pair<>(left, right);
45 }
46
47 /**
48 * Factory method for a Pair factory function.
49 *
50 * @param <A> the left value type
51 * @param <B> the right value type
52 * @return a function that constructs Pairs
53 */
54 public static <A, B> BiFunction<A, B, Pair<A, B>> pairs() {
55 return Pair::pair;
56 }
57
58 /**
59 * Function for accessing the left value of {@link Pair pairs}.
60 *
61 * @param <A> the left value type
62 * @return a Function that given a {@link io.atlassian.fugue.Pair} returns the
63 * left side value
64 * @since 1.1
65 */
66 public static <A> Function<Pair<A, ?>, A> leftValue() {
67 return Pair::left;
68 }
69
70 /**
71 * Function for accessing the right value of {@link Pair pairs}.
72 *
73 * @param <B> the right value type
74 * @return a Function that given a {@link io.atlassian.fugue.Pair} returns the
75 * right side value
76 * @since 1.1
77 */
78 public static <B> Function<Pair<?, B>, B> rightValue() {
79 return Pair::right;
80 }
81
82 /**
83 * Performs function application within an homogeneous pair (applicative
84 * functor pattern).
85 *
86 * @param aa an homogeneous pair
87 * @param ff The pair of functions to apply.
88 * @return A new pair after applying the given pair of functions through aa.
89 */
90 public static <A, B> Pair<B, B> ap(final Pair<A, A> aa, final Pair<Function<A, B>, Function<A, B>> ff) {
91 return Pair.pair(ff.left().apply(aa.left()), ff.right().apply(aa.right()));
92 }
93
94 /**
95 * Apply a function to both elements of an homogeneous pair.
96 *
97 * @param aa an homogeneous pair
98 * @param f function to apply to both elements of aa
99 * @return A new pair after applying the function to aa elements.
100 */
101 public static <A, B> Pair<B, B> map(final Pair<A, A> aa, final Function<A, B> f) {
102 return Pair.pair(f.apply(aa.left()), f.apply(aa.right()));
103 }
104
105 /**
106 * Zips two iterables into a single iterable that produces {@link Pair pairs}.
107 *
108 * @param <A> LHS type
109 * @param <B> RHS type
110 * @param as left values
111 * @param bs right values
112 * @return an {@link Iterable iterable} of pairs, only as long as the shortest
113 * input iterable.
114 * @since 1.1
115 */
116 public static <A, B> Iterable<Pair<A, B>> zip(final Iterable<A> as, final Iterable<B> bs) {
117 return Iterables.zip(as, bs);
118 }
119
120 //
121 // members
122 //
123
124 private final A left;
125 private final B right;
126
127 /**
128 * Constructor for Pair.
129 *
130 * @param left value, cannot be null
131 * @param right value, cannot be null
132 */
133 public Pair(final A left, final B right) {
134 this.left = requireNonNull(left, "Left parameter must not be null.");
135 this.right = requireNonNull(right, "Right parameter must not be null.");
136 }
137
138 /**
139 * Accessor method for the left value of the pair.
140 *
141 * @return a A object.
142 */
143 public A left() {
144 return left;
145 }
146
147 /**
148 * Accessor method for the right value of the pair.q
149 *
150 * @return a B object.
151 */
152 public B right() {
153 return right;
154 }
155
156 /** {@inheritDoc} */
157 @Override public String toString() {
158 return "Pair(" + left + ", " + right + ")";
159 }
160
161 /** {@inheritDoc} */
162 @Override public boolean equals(final Object o) {
163 if (o == null) {
164 return false;
165 }
166 if (this == o) {
167 return true;
168 }
169
170 if (!(o instanceof Pair<?, ?>)) {
171 return false;
172 }
173 final Pair<?, ?> that = (Pair<?, ?>) o;
174 return left.equals(that.left) && right.equals(that.right);
175 }
176
177 /** {@inheritDoc} */
178 @Override public int hashCode() {
179 final int lh = left.hashCode();
180 final int rh = right.hashCode();
181 return (((lh >> HALF_WORD) ^ lh) << HALF_WORD) | (((rh << HALF_WORD) ^ rh) >> HALF_WORD);
182 }
183 }