Spaces:
Running
Running
TurkuBasicOOPinJava / Week 7: Enum, Generic Type, Streams, write to file, class diagram /09A. sum-average-min-max(), OptionalInt+++
| A typical example of an operation applied to a collection is calculating the SUM of all elements. | |
| If we have a list containing numbers as strings, we can easily calculate the sum of its elements by forming a stream from the list: | |
| ArrayList<String> numbers = new ArrayList<>(); | |
| numbers.add("23"); | |
| numbers.add("9"); | |
| numbers.add("7"); | |
| numbers.add("3"); | |
| int sum = numbers.stream().mapToInt(number -> Integer.valueOf(number)).sum(); | |
| System.out.println("The sum of the numbers: " + sum); | |
| The program prints: | |
| 42 | |
| In this stream, we need the operation 'mapToInt', which converts the pieces into int type. | |
| Here again, we use a lambda expression and give the operation as Integer's valueOf. | |
| ========================================================== | |
| Somewhat confusingly, the operation is also needed when the list is already of integer type. | |
| This is because certain terminal operations only work when the elements are of type 'int' ('Integer' is not acceptable): | |
| ArrayList<Integer> numbers = new ArrayList<>(); | |
| for (int i=1; i<20; i+=2) { | |
| numbers.add(i); | |
| } | |
| System.out.println(numbers); | |
| // The confusing-looking "change" number -> number converts | |
| // an Integer stream into an int stream | |
| System.out.println("The sum of the numbers: " + numbers.stream().mapToInt(number -> number).sum()); | |
| The program prints: | |
| [1, 3, 5, 7, 9, 11, 13, 15, 17, 19] | |
| The sum of the numbers: 100 | |
| ========================================================== | |
| Other handy operations include average, min, and max, | |
| which return the average, minimum, and maximum of a list of numbers: | |
| ArrayList<Integer> numbers = new ArrayList<>(); | |
| for (int i=1; i<10; i++) { | |
| numbers.add(i); | |
| } | |
| System.out.println(numbers); | |
| System.out.println("Maximum:"); | |
| System.out.println(numbers.stream().mapToInt(number -> number).max().getAsInt()); | |
| System.out.println("Minimum:"); | |
| System.out.println(numbers.stream().mapToInt(number -> number).min().getAsInt()); | |
| System.out.println("Average:"); | |
| System.out.println(numbers.stream().mapToInt(number -> number).average().getAsDouble()); | |
| The program prints: | |
| [1, 2, 3, 4, 5, 6, 7, 8, 9] | |
| Maximum: | |
| 9 | |
| Minimum: | |
| 1 | |
| Average: | |
| 5.0 | |
| Now, a terminal operation is needed to convert the result into a number, for example, getAsInt(). | |
| This is because the output of the preceding max operation is not an integer but a value of type 'OptionalInt'. | |
| An 'extended type' from a normal integer (such as 'OptionalInt') is needed because the list might not contain any values | |
| - in which case the maximum value of the list cannot be presented as an integer. | |
| If the stream is empty when it comes to the max operation, the getAsInt() operation will throw an exception: | |
| ArrayList<Integer> numbers = new ArrayList<>(); | |
| // In an empty stream, there is no maximum... | |
| int max = numbers.stream().mapToInt(number -> number).max().getAsInt(); | |
| The programs throws an exception: | |
| Exception in thread "main" java.util.NoSuchElementException: No value present | |
| The problem can be circumvented either by | |
| 1- CHECKING that the LIST is NOT EMPTY or | |
| 2- by performing the 'getAsInt' operation only AFTER it has been confirmed that the VALUE EXISTS: | |
| OptionalInt max = numbers.stream().mapToInt(number -> number).max(); | |
| if (!max.isEmpty()) { | |
| System.out.println("Maximum: " + max.getAsInt()); | |