Skip to content
Snippets Groups Projects
Commit 1748514d authored by Stuart Marks's avatar Stuart Marks
Browse files

more exercises from Jose, especially comparators

parent 3d95e1c2
No related branches found
No related tags found
No related merge requests found
......@@ -136,6 +136,28 @@ public class A_LambdasAndMethodReferences {
assertEquals("ABC", func.apply("abc"));
}
/**
* Given two Functions, one that converts a null reference to an
* empty string, and another that gets the length of a string,
* create a single function converts nulls and then gets the
* string's length.
*/
@Test @Ignore
public void b_function4() {
Function<String, String> unNullify = s -> s == null ? "" : s;
Function<String, Integer> length = String::length;
Function<String, Integer> lengthBis = null; // TODO
assertEquals((Integer)14, lengthBis.apply("Hello JavaOne!"));
assertEquals((Integer)0, lengthBis.apply(""));
assertEquals((Integer)0, lengthBis.apply(null));
}
// Hint:
// <editor-fold defaultstate="collapsed">
// See java.util.Function.compose() or java.util.Function.andThen()
// </editor-fold>
/**
* Write a lambda expression that appends the
* string "abc" to the given StringBuilder.
......
package exercises;
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 {
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 @Ignore
public void comparator1() {
Comparator<Person> comparebyLastName = null; // TODO
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 @Ignore
public void comparator2() {
Comparator<Person> comparebyLastNameThenFirstName = null; // TODO
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 @Ignore
public void comparator3() {
Comparator<Person> comparebyLastNameThenFirstNameReversed = null; // TODO
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 @Ignore
public void comparator4() {
Comparator<Person> comparebyLastNameThenFirstNameWithNull = null; // TODO
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 @Ignore
public void comparator5() {
Comparator<Person> comparebyAge = null; // TODO
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 @Ignore
public void comparator6() {
IntBinaryOperator intCompare = null; // TODO
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 @Ignore
public void comparator7() {
IntBinaryOperator intCompare = null; // TODO
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 @Ignore
public void comparator8() {
DoubleToIntBiFunction doubleCompare = null; // TODO
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>
}
package model;
public class Person {
private String lastName;
private String firstName;
private int age;
public Person(String firstName, String lastName, int age) {
this.lastName = lastName;
this.firstName = firstName;
this.age = age;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
......@@ -160,6 +160,33 @@ public class A_LambdasAndMethodReferences {
assertEquals("ABC", func.apply("abc"));
}
/**
* Given two Functions, one that converts a null reference to an
* empty string, and another that gets the length of a string,
* create a single function converts nulls and then gets the
* string's length.
*/
@Test
public void b_function4() {
Function<String, String> unNullify = s -> s == null ? "" : s;
Function<String, Integer> length = String::length;
//TODO//Function<String, Integer> lengthBis = null;
//BEGINREMOVE
Function<String, Integer> lengthBis = unNullify.andThen(length);
// Alternatively:
// Function<String, Integer> lengthBis = length.compose(unNullify);
//ENDREMOVE
assertEquals((Integer)14, lengthBis.apply("Hello JavaOne!"));
assertEquals((Integer)0, lengthBis.apply(""));
assertEquals((Integer)0, lengthBis.apply(null));
}
// Hint:
// <editor-fold defaultstate="collapsed">
// See java.util.Function.compose() or java.util.Function.andThen()
// </editor-fold>
/**
* Write a lambda expression that appends the
* string "abc" to the given StringBuilder.
......
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 {
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>
}
......@@ -6,6 +6,7 @@ import org.junit.runners.Suite;
@RunWith(Suite.class)
@Suite.SuiteClasses(value={
exercises.A_LambdasAndMethodReferences.class,
exercises.B_Comparators.class,
exercises.Exercises.class
})
public class JUnit4TestSuite {
......
* Jose's comparator tests
* Balloon stuff -- a bit complicated, but useful to show constructor references
* Maurice's forEach example List<StringBuilder>
* reorganize files
Java 8 Lambdas Hands-on Lab Materials
(version for late 2016 conferences)
Open LambdaLab in your favorite IDE. (Currently NetBeans is
supported.) Then open Test Packages / exercises / Exercises.java.
supported.) Then open the files in
Test Packages > exercises
The exercises are in the form of JUnit tests. Each exercise is a
single test method. Each test method is initially marked with @Ignore
so that it will be not be run by JUnit. Each test method has some
setup code and some assertions at the bottom.
To work on an exercise, uncomment @Ignore and add code at or near the
TODO comment that will make the assertions pass.
To work on an exercise, uncomment @Ignore and then look for a "TODO"
comment somewhere in the body of the test method. Add code here that
makes the assertions pass. You shouldn't have to modify any of the
setup code at the top of the test method or the assertions at the
bottom of the test method.
There is sometimes a hint or two after a test method. If you're having
trouble with an exercise, look for hints. The hint text is inside
a editor fold that is closed by default, so click on the plus-sign
to read it.
The intent of the exercises is to solve them using the new Java 8
lambda feature, the new Java 8 Streams API, and other APIs added in
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment