Skip to content

Commit dc3347f

Browse files
committed
Added Pair utility class (renamed later to Couple to fix java.naming error)
1 parent 03f0ec4 commit dc3347f

File tree

2 files changed

+352
-0
lines changed

2 files changed

+352
-0
lines changed
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
package java.util;
2+
3+
/**
4+
* The {@code Couple} class represents a mutable, ordered Couple of elements.
5+
* <p>
6+
* This class mimics the behavior of the C++ Standard Library's `std::Couple`, providing two values, referred to as
7+
* the "first" and the "second" elements, of possibly different types.
8+
* <p>
9+
* The {@code Couple} class provides a parameterized constructor to initialize both elements and allows access to them
10+
* through getter and setter methods.
11+
*
12+
* @param <K> the type of the first element
13+
* @param <V> the type of the second element
14+
*
15+
* @author Adarsh Sharma
16+
* @since 1.0
17+
*/
18+
public class Couple<K extends Comparable<? super K>, V extends Comparable<? super V>>
19+
implements Comparable<Couple<K, V>> {
20+
private K first;
21+
private V second;
22+
23+
/**
24+
* Constructs a new Couple with the specified values.
25+
*
26+
* @param first the first element of the Couple
27+
* @param second the second element of the Couple
28+
*/
29+
public Couple(K first, V second) {
30+
this.first = first;
31+
this.second = second;
32+
}
33+
34+
/**
35+
* Returns the first element of the Couple.
36+
*
37+
* @return the first element of the Couple
38+
*/
39+
public K getFirst() {
40+
return first;
41+
}
42+
43+
/**
44+
* Sets the first element of the Couple.
45+
*
46+
* @param first the first element of the Couple
47+
*/
48+
public void setFirst(K first) {
49+
this.first = first;
50+
}
51+
52+
/**
53+
* Returns the second element of the Couple.
54+
*
55+
* @return the second element of the Couple
56+
*/
57+
public V getSecond() {
58+
return second;
59+
}
60+
61+
/**
62+
* Sets the second element of the Couple.
63+
*
64+
* @param second the second element of the Couple
65+
*/
66+
public void setSecond(V second) {
67+
this.second = second;
68+
}
69+
70+
/**
71+
* Compares this Couple with the specified Couple for order.
72+
* <p>
73+
* Comparison is based first on the {@code first} elements, and if they are equal,
74+
* then on the {@code second} elements. Both elements are compared using their natural ordering,
75+
* unless they are {@code null}, in which case {@code null} is considered less than non-null.
76+
* <p>
77+
* This method is {@code null}-safe and consistent with equals when both elements are non-null.
78+
*
79+
* @param other the Couple to be compared
80+
* @return a negative integer, zero, or a positive integer as this Couple
81+
* is less than, equal to, or greater than the specified Couple
82+
* @throws NullPointerException if {@code other} is {@code null}
83+
*/
84+
@Override
85+
public int compareTo(Couple<K, V> other) {
86+
if (other == null) {
87+
throw new NullPointerException("Compared Couple must not be null");
88+
}
89+
90+
int cmp = compareNullable(this.first, other.first);
91+
if (cmp != 0) {
92+
return cmp;
93+
}
94+
95+
return compareNullable(this.second, other.second);
96+
}
97+
98+
/**
99+
* Helper method to compare two Comparable objects, handling nulls.
100+
* {@code null} is considered less than any non-null value.
101+
*
102+
* @param a first value
103+
* @param b second value
104+
* @return comparison result
105+
*/
106+
@SuppressWarnings("unchecked")
107+
private <T extends Comparable<? super T>> int compareNullable(T a, T b) {
108+
if (a == b) return 0;
109+
if (a == null) return -1;
110+
if (b == null) return 1;
111+
return a.compareTo(b);
112+
}
113+
114+
/**
115+
* Returns a string representation of this Couple in the format {@code (first, second)}.
116+
*
117+
* @return a string representation of this Couple
118+
*/
119+
@Override
120+
public String toString() {
121+
return "(" + first + ", " + second + ")";
122+
}
123+
124+
/**
125+
* Checks if this Couple is equal to another object. Two Couples are considered equal if both the first and second
126+
* elements are equal.
127+
*
128+
* @param o the object to compare this Couple with
129+
* @return {@code true} if this Couple is equal to the specified object
130+
*/
131+
@Override
132+
public boolean equals(Object o) {
133+
if (this == o) return true;
134+
if (o == null || getClass() != o.getClass()) return false;
135+
Couple<?, ?> Couple = (Couple<?, ?>) o;
136+
return Objects.equals(first, Couple.first) && Objects.equals(second, Couple.second);
137+
}
138+
139+
/**
140+
* Returns the hash code for this Couple, computed based on the hash codes of the first and second elements.
141+
*
142+
* @return the hash code for this Couple
143+
*/
144+
@Override
145+
public int hashCode() {
146+
return Objects.hash(first, second);
147+
}
148+
149+
/**
150+
* Creates a new {@code Couple} with the given first and second elements.
151+
*
152+
* @param first the first element of the Couple
153+
* @param second the second element of the Couple
154+
* @param <K> the type of the first element, must be Comparable
155+
* @param <V> the type of the second element, must be Comparable
156+
* @return a new {@code Couple} containing the given elements
157+
*/
158+
public static <K extends Comparable<? super K>, V extends Comparable<? super V>>
159+
Couple<K, V> makeCouple(K first, V second) {
160+
return new Couple<>(first, second);
161+
}
162+
}
Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
import org.testng.Assert;
2+
import org.testng.annotations.Test;
3+
4+
import java.util.Objects;
5+
import java.util.Stack;
6+
7+
/**
8+
* Unit tests for the {@link Couple} class.
9+
* <p>
10+
* This class validates all functionalities of the {@code Couple} class including construction, getters/setters,
11+
* equality, comparison, hash code generation, string representation, and utility methods like {@code swap} and
12+
* {@code makeCouple}. It ensures correct behavior across different data types and edge cases (nulls, identity, etc.).
13+
* </p>
14+
*
15+
* @author Adarsh Sharma
16+
* @since 1.0
17+
*/
18+
public class CoupleTest {
19+
20+
/**
21+
* Verifies that the constructor initializes the first and second elements correctly.
22+
*/
23+
@Test
24+
public void testConstructor() {
25+
Couple<Integer, String> Couple = new Couple<>(1, "one");
26+
Assert.assertEquals(Couple.getFirst(), Integer.valueOf(1));
27+
Assert.assertEquals(Couple.getSecond(), "one");
28+
}
29+
30+
/**
31+
* Verifies that the getter and setter methods update and retrieve values as expected.
32+
*/
33+
@Test
34+
public void testGettersAndSetters() {
35+
Couple<Integer, String> Couple = new Couple<>(1, "one");
36+
Couple.setFirst(2);
37+
Couple.setSecond("two");
38+
Assert.assertEquals(Couple.getFirst(), Integer.valueOf(2));
39+
Assert.assertEquals(Couple.getSecond(), "two");
40+
}
41+
42+
/**
43+
* Verifies that the {@code equals} method correctly evaluates object equality.
44+
*/
45+
@Test
46+
public void testEquals() {
47+
Couple<Integer, String> Couple1 = new Couple<>(1, "one");
48+
Couple<Integer, String> Couple2 = new Couple<>(1, "one");
49+
Couple<Integer, String> Couple3 = new Couple<>(2, "two");
50+
51+
Assert.assertTrue(Couple1.equals(Couple2));
52+
Assert.assertFalse(Couple1.equals(Couple3));
53+
Assert.assertFalse(Couple1.equals(null));
54+
Assert.assertFalse(Couple1.equals("not a Couple"));
55+
Assert.assertTrue(Couple1.equals(Couple1)); // Self-comparison
56+
}
57+
58+
/**
59+
* Verifies equality behavior when one or both elements are {@code null}.
60+
*/
61+
@Test
62+
public void testEqualsWithNullElements() {
63+
Couple<String, String> Couple1 = new Couple<>(null, "one");
64+
Couple<String, String> Couple2 = new Couple<>(null, "one");
65+
Assert.assertTrue(Couple1.equals(Couple2));
66+
Couple<String, String> Couple3 = new Couple<>(null, null);
67+
Couple<String, String> Couple4 = new Couple<>(null, null);
68+
Assert.assertTrue(Couple1.equals(Couple2));
69+
Assert.assertTrue(Couple2.equals(Couple1));
70+
}
71+
72+
/**
73+
* Validates that {@code hashCode} is consistent for equal Couples.
74+
*/
75+
@Test
76+
public void testHashCode() {
77+
Couple<Integer, String> Couple1 = new Couple<>(1, "one");
78+
Couple<Integer, String> Couple2 = new Couple<>(1, "one");
79+
Assert.assertEquals(Couple1.hashCode(), Couple2.hashCode());
80+
}
81+
82+
/**
83+
* Ensures {@code hashCode} handles {@code null} elements correctly.
84+
*/
85+
@Test
86+
public void testHashCodeWithNulls() {
87+
Couple<String, String> Couple = new Couple<>(null, null);
88+
Assert.assertEquals(Couple.hashCode(), Objects.hash(null, null));
89+
}
90+
91+
/**
92+
* Validates the static factory method {@code makeCouple} creates an equivalent {@code Couple}.
93+
*/
94+
@Test
95+
public void testMakeCouple() {
96+
Couple<Integer, String> Couple = Couple.makeCouple(1, "one");
97+
Assert.assertEquals(Couple.getFirst(), Integer.valueOf(1));
98+
Assert.assertEquals(Couple.getSecond(), "one");
99+
}
100+
101+
/**
102+
* Tests usage of {@code Couple} with custom objects such as {@code Stack}.
103+
*/
104+
@Test
105+
public void testCustomObjects() {
106+
Couple<Stack<Integer>, String> Couple = new Couple<>(new Stack<>(), "test");
107+
Couple.getFirst().push(1);
108+
Couple.getFirst().push(2);
109+
Assert.assertEquals(Couple.getFirst().size(), 2);
110+
Assert.assertEquals(Couple.getSecond(), "test");
111+
}
112+
113+
/**
114+
* Validates the {@code toString} representation for non-null elements.
115+
*/
116+
@Test
117+
public void testToString() {
118+
Couple<Integer, String> Couple = new Couple<>(1, "one");
119+
Assert.assertEquals(Couple.toString(), "(1, one)");
120+
}
121+
122+
/**
123+
* Validates the {@code toString} representation when both elements are {@code null}.
124+
*/
125+
@Test
126+
public void testToStringWithNulls() {
127+
Couple<String, String> Couple = new Couple<>(null, null);
128+
Assert.assertEquals(Couple.toString(), "(null, null)");
129+
}
130+
131+
/**
132+
* Validates that {@code compareTo} returns zero for equal Couples.
133+
*/
134+
@Test
135+
public void testCompareToEqual() {
136+
Couple<String, String> Couple1 = new Couple<>("a", "b");
137+
Couple<String, String> Couple2 = new Couple<>("a", "b");
138+
Assert.assertEquals(Couple1.compareTo(Couple2), 0);
139+
}
140+
141+
/**
142+
* Validates that {@code compareTo} returns a negative or positive value
143+
* when the first elements differ.
144+
*/
145+
@Test
146+
public void testCompareToFirstDifferent() {
147+
Couple<String, String> Couple1 = new Couple<>("a", "b");
148+
Couple<String, String> Couple2 = new Couple<>("b", "b");
149+
Assert.assertTrue(Couple1.compareTo(Couple2) < 0);
150+
Assert.assertTrue(Couple2.compareTo(Couple1) > 0);
151+
}
152+
153+
/**
154+
* Validates that {@code compareTo} evaluates second elements when first are equal.
155+
*/
156+
@Test
157+
public void testCompareToSecondDifferent() {
158+
Couple<String, String> Couple1 = new Couple<>("a", "b");
159+
Couple<String, String> Couple2 = new Couple<>("a", "c");
160+
Assert.assertTrue(Couple1.compareTo(Couple2) < 0);
161+
}
162+
163+
/**
164+
* Tests {@code compareTo} behavior when one or both elements are {@code null}.
165+
*/
166+
@Test
167+
public void testCompareToWithNulls() {
168+
Couple<String, String> Couple1 = new Couple<>(null, "b");
169+
Couple<String, String> Couple2 = new Couple<>("a", "b");
170+
Assert.assertTrue(Couple1.compareTo(Couple2) < 0);
171+
172+
Couple<String, String> Couple3 = new Couple<>("a", null);
173+
Couple<String, String> Couple4 = new Couple<>("a", "b");
174+
Assert.assertTrue(Couple3.compareTo(Couple4) < 0);
175+
176+
Couple<String, String> Couple5 = new Couple<>(null, null);
177+
Couple<String, String> Couple6 = new Couple<>(null, null);
178+
Assert.assertEquals(Couple5.compareTo(Couple6), 0);
179+
// null is considered less than non-null for comparison
180+
}
181+
182+
/**
183+
* Verifies that passing {@code null} to {@code compareTo} throws {@code NullPointerException}.
184+
*/
185+
@Test(expectedExceptions = NullPointerException.class)
186+
public void testCompareToNull() {
187+
Couple<String, String> Couple = new Couple<>("a", "b");
188+
Couple.compareTo(null);
189+
}
190+
}

0 commit comments

Comments
 (0)