Newer
Older
package solutions;
import java.util.Comparator;
import java.util.function.IntBinaryOperator;
import static org.junit.Assert.assertEquals;
import org.junit.Ignore;
import org.junit.Test;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import model.Person;
/**
* Exercises to create comparators using lambda expressions
* and using the Comparator combinators. Some of the exercises
* use a Person class, which is a simple POJO containing a last
* name, first name, and age, with the obvious constructors and
* getters.
*/
public class B_Comparators {
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
final Person michael = new Person("Michael", "Jackson", 51);
final Person rod = new Person("Rod", "Stewart", 71);
final Person paul = new Person("Paul", "McCartney", 74);
final Person mick = new Person("Mick", "Jagger", 73);
final Person jermaine = new Person("Jermaine", "Jackson", 61);
/**
* Write a Comparator that compares instances of Person using their lastName.
*/
@Test
public void comparator1() {
//TODO//Comparator<Person> comparebyLastName = null;
//BEGINREMOVE
Comparator<Person> comparebyLastName = Comparator.comparing(Person::getLastName);
//ENDREMOVE
assertTrue(comparebyLastName.compare(michael, rod) < 0);
assertTrue(comparebyLastName.compare(paul, paul) == 0);
assertTrue(comparebyLastName.compare(michael, jermaine) == 0);
}
// Hint:
// <editor-fold defaultstate="collapsed">
// Check the static factory methods of the Comparator interface. Remember
// how you implemented functions in the previous exercises. Write it using
// a method reference.
// </editor-fold>
/**
* Write a Comparator that compares instances of Person using their
* lastName, and if their last name is the same, uses their first name.
*/
@Test
public void comparator2() {
//TODO//Comparator<Person> comparebyLastNameThenFirstName = null;
//BEGINREMOVE
Comparator<Person> comparebyLastNameThenFirstName =
Comparator.comparing(Person::getLastName)
.thenComparing(Person::getFirstName);
//ENDREMOVE
assertTrue(comparebyLastNameThenFirstName.compare(michael, rod) < 0);
assertTrue(comparebyLastNameThenFirstName.compare(paul, paul) == 0);
assertTrue(comparebyLastNameThenFirstName.compare(michael, jermaine) > 0);
}
// Hint:
// <editor-fold defaultstate="collapsed">
// Use the previous comparator and check the default methods of the Comparator interface.
// </editor-fold>
/**
* Write a Comparator that compares the people in the reversed order than
* the one you wrote in the comparator2() exercise.
*/
@Test
public void comparator3() {
//TODO//Comparator<Person> comparebyLastNameThenFirstNameReversed = null;
//BEGINREMOVE
Comparator<Person> comparebyLastNameThenFirstNameReversed =
Comparator.comparing(Person::getLastName)
.thenComparing(Person::getFirstName)
.reversed();
//ENDREMOVE
assertFalse(comparebyLastNameThenFirstNameReversed.compare(michael, rod) < 0);
assertTrue(comparebyLastNameThenFirstNameReversed.compare(paul, paul) == 0);
assertFalse(comparebyLastNameThenFirstNameReversed.compare(michael, jermaine) > 0);
}
// Hint:
// <editor-fold defaultstate="collapsed">
// Use the previous comparator and check the default methods of the Comparator interface.
// </editor-fold>
/**
* Write a Comparator that compares the people in the same order than the
* one you wrote in comparator2(), but that supports null values. The null
* values should be considered greater than any non-null values.
*/
@Test
public void comparator4() {
//TODO//Comparator<Person> comparebyLastNameThenFirstNameWithNull = null;
//BEGINREMOVE
Comparator<Person> comparebyLastNameThenFirstNameWithNull =
Comparator.nullsLast(
Comparator.comparing(Person::getLastName)
.thenComparing(Person::getFirstName));
//ENDREMOVE
assertTrue(comparebyLastNameThenFirstNameWithNull.compare(michael, rod) < 0);
assertTrue(comparebyLastNameThenFirstNameWithNull.compare(paul, paul) == 0);
assertTrue(comparebyLastNameThenFirstNameWithNull.compare(michael, jermaine) > 0);
assertTrue(comparebyLastNameThenFirstNameWithNull.compare(mick, null) < 0);
assertTrue(comparebyLastNameThenFirstNameWithNull.compare(null, mick) > 0);
}
// Hint:
// <editor-fold defaultstate="collapsed">
// Use the previous comparator and check the static methods of the Comparator interface.
// </editor-fold>
/**
* Write a Comparator that compares two people by age.
* Try to write the comparator so as to avoid boxing of primitives.
*/
@Test
public void comparator5() {
//TODO//Comparator<Person> comparebyAge = null;
//BEGINREMOVE
Comparator<Person> comparebyAge = Comparator.comparingInt(Person::getAge);
//ENDREMOVE
assertTrue(comparebyAge.compare(michael, rod) < 0);
assertTrue(comparebyAge.compare(paul, paul) == 0);
assertTrue(comparebyAge.compare(mick, jermaine) > 0);
}
// Hint:
// <editor-fold defaultstate="collapsed">
// Look for static methods on the Comparator interface that
// have primitive specializations.
// </editor-fold>
/**
* Write a lambda expression that compares two int values and returns an
* int result that is less than, equal to, or greater than zero, like
* a comparator. Watch out for overflow. The Comparator interface takes
* two objects, but in this case we are comparing int primitives, so the
* functional interface we use is IntBinaryOperator.
*/
@Test
public void comparator6() {
//TODO//IntBinaryOperator intCompare = null;
//BEGINREMOVE
IntBinaryOperator intCompare = (a, b) -> (a < b) ? -1 : (a > b) ? 1 : 0;
// Avoid the following as it is susceptible to overflow:
// IntBinaryOperator intCompare = (a, b) -> a - b;
//ENDREMOVE
assertTrue(intCompare.applyAsInt(0, 1) < 0);
assertTrue(intCompare.applyAsInt(1, 1) == 0);
assertTrue(intCompare.applyAsInt(2, 1) > 0);
assertTrue(intCompare.applyAsInt(Integer.MIN_VALUE, Integer.MAX_VALUE) < 0);
assertTrue(intCompare.applyAsInt(Integer.MAX_VALUE, Integer.MIN_VALUE) > 0);
}
// Hint:
// <editor-fold defaultstate="collapsed">
// Use a ternary operator (cond ? result1 : result2) instead of subtraction.
// </editor-fold>
/**
* Write a method reference that compares two int values and returns an
* int result that is less than, equal to, or greater than zero, like
* a comparator.
*/
@Test
public void comparator7() {
//TODO//IntBinaryOperator intCompare = null;
//BEGINREMOVE
IntBinaryOperator intCompare = Integer::compare;
//ENDREMOVE
assertTrue(intCompare.applyAsInt(0, 1) < 0);
assertTrue(intCompare.applyAsInt(1, 1) == 0);
assertTrue(intCompare.applyAsInt(2, 1) > 0);
assertTrue(intCompare.applyAsInt(Integer.MIN_VALUE, Integer.MAX_VALUE) < 0);
assertTrue(intCompare.applyAsInt(Integer.MAX_VALUE, Integer.MIN_VALUE) > 0);
}
// Hint:
// <editor-fold defaultstate="collapsed">
// Use a method reference to a static method on the Integer class.
// </editor-fold>
interface DoubleToIntBiFunction {
int applyAsInt(double a, double b);
}
/**
* Write a method reference that compares two double values and returns an
* int result that is less than, equal to, or greater than zero, like
* a comparator. There functional interface that takes two doubles and returns
* an int, so we define one here. Comparing double values introduces
* special cases such NaN. Consider all NaN values to be equal to each other
* and greater than any non-NaN value.
*/
@Test
public void comparator8() {
//TODO//DoubleToIntBiFunction doubleCompare = null;
//BEGINREMOVE
DoubleToIntBiFunction doubleCompare = Double::compare;
//ENDREMOVE
assertTrue(doubleCompare.applyAsInt(0.0, 1.0) < 0);
assertTrue(doubleCompare.applyAsInt(1.0, 1.0) == 0);
assertTrue(doubleCompare.applyAsInt(2.0, 1.0) > 0);
assertTrue(doubleCompare.applyAsInt(Double.NaN, Double.NaN) == 0);
assertTrue(doubleCompare.applyAsInt(Double.NaN, 0.0) > 0);
assertTrue(doubleCompare.applyAsInt(0.0, Double.NaN) < 0);
}
// Hint:
// <editor-fold defaultstate="collapsed">
// Use a method reference to a static method on the Double class.
// </editor-fold>
}