I’ve came across that kata from @brjavaman and @yanaga to teach lambdas, one of the new features of JDK 8.
There are some unit tests to validate the solution. I’ve found it a good opportunity to exercise the use of lambdas so I decided to solve it. Below is my solution to this kata.
The first method should take the String list and sort all the String elements in ascending (ASCII) order:
1 2 3 4 5 6 7 8 9 10 11 |
/** * This method should take the String List and sort all the String elements in ascending (ASCII) order. * * @return The sorted values in ascending ASCII order. */ public List<String> getSortedStrings() { return values .stream() .sorted() .collect(Collectors.toList()); } |
The other method should take the String list and:
- filter the elements that contains one or more digits
- transform (map) the remaining Strings into Integers
- sort the Integers in ascending order
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
/** * This method should take the String List and: * <ol> * <li>filter the elements that contains one or more digits;</li> * <li>transform (map) the remaining Strings into Integers;</li> * <li>sort the Integers in ascending order.</li> * </ol> * * @return */ public List<Integer> getSortedIntegers() { return values .stream() .filter(s -> s.matches("\\d+")) .map(Integer::valueOf) .sorted() .collect(Collectors.toList()); } |
The last method should take the String list and:
- filter the elements that contains one or more digits
- transform (map) the remaining Strings into Integers
- sort the Integers in descending order
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
/** * This method should take the String List and: * <ol> * <li>filter the elements that contains one or more digits;</li> * <li>transform (map) the remaining Strings into Integers;</li> * <li>sort the Integers in descending order.</li> * </ol> * * @return */ public List<Integer> getSortedDescendingIntegers() { return values .stream() .filter(s -> s.matches("\\d+")) .map(Integer::valueOf) .sorted(Comparator.reverseOrder()) .collect(Collectors.toList()); } |
Note that the steps filter the elements that contains one or more digits
and transform (map) the remaining Strings into Integers
are identical. So I decided to extract the partial Stream into a method with the Extract Method refactoring support on IntelliJ IDEA:
1 2 3 4 5 6 |
private Stream<Integer> integersWithOneOrMoreDigits() { return values .stream() .filter(s -> s.matches("\\d+")) .map(Integer::valueOf); } |
Then I refactored the the solution to use the new extracted method:
1 2 3 4 5 |
public List<Integer> getSortedIntegers() { return integersWithOneOrMoreDigits() .sorted() .collect(Collectors.toList()); } |
1 2 3 4 5 |
public List<Integer> getSortedDescendingIntegers() { return integersWithOneOrMoreDigits() .sorted(Comparator.reverseOrder()) .collect(Collectors.toList()); } |
I re-run the tests and they all passed. What do you think about this solution? Do you suggest other ones?