// This program contains some examples of Java 8 constructs. // // What are the "first-class citizens" of Java (can pass as a parameter)? // numbers // booleans // arrays (a kind of object) // strings (a kind of object) // other objects // // what about // functions? (methods) // // now answer is yes (sort of)...functional programming // functional languages: LISP, Scheme, ML, OCaml, Haskell, Scala // other languages like Python include functional features // // most interesting when you have higher-order functions // functions that take functions as parameters // three biggies: map, filter, reduce import java.util.*; import java.util.stream.*; import java.io.*; import java.nio.file.*; public class Examples { public static void main(String[] args) throws IOException { arraysExample(); rangeExample(); primesExample(); funnyExample(); linesExample(); } public static void arraysExample() { int[] numbers = {18, 9, 7, 42, 3, 8, 15, 32, 208, 315, 8, 12, 8}; // old fashioned way to print the words with array traversal System.out.print("numbers :"); for (int i = 0; i < numbers.length; i++) { System.out.print(" " + numbers[i]); } System.out.println(); // Java 5 introduced the foreach loop System.out.print("numbers :"); for (int n : numbers) { System.out.print(" " + n); } System.out.println(); // Java 8 approach involves working with streams // streams are of the form: source of data -> modifiers -> terminator // functions are specified with a lambda (anonymous function) System.out.print("numbers :"); Arrays.stream(numbers) .forEach(n -> System.out.print(" " + n)); System.out.println(); System.out.print("even numbers :"); Arrays.stream(numbers) .filter(n -> n % 2 == 0) .forEach(n -> System.out.print(" " + n)); System.out.println(); System.out.print("sorted even numbers :"); Arrays.stream(numbers) .filter(n -> n % 2 == 0) .sorted() .forEach(n -> System.out.print(" " + n)); System.out.println(); System.out.print("sorted distinct even numbers :"); Arrays.stream(numbers) .filter(n -> n % 2 == 0) .sorted() .distinct() .forEach(n -> System.out.print(" " + n)); System.out.println(); System.out.print("squares of sorted distinct even numbers :"); Arrays.stream(numbers) .filter(n -> n % 2 == 0) .distinct() .sorted() .map(n -> n * n) .forEach(n -> System.out.print(" " + n)); System.out.println(); // print sum of squares of distinct even numbers int sum = Arrays.stream(numbers) .filter(n -> n % 2 == 0) .distinct() .map(n -> n * n) .reduce(0, (x, y) -> x + y); System.out.println("sum = " + sum); // print sum of squares of distinct even numbers using sum terminator int sum2 = Arrays.stream(numbers) .filter(n -> n % 2 == 0) .distinct() .map(n -> n * n) .sum(); System.out.println("sum = " + sum2); // print all statistics for sum of squares of distinct even numbers System.out.println(Arrays.stream(numbers) .filter(n -> n % 2 == 0) .distinct() .map(n -> n * n) .summaryStatistics()); System.out.println(); } // There is a new range type that can be used for lots of interesting // things that we have normally done with loops public static void rangeExample() { // print 1 to 5 (2nd parameter is exclusive, as with substring) IntStream.range(1, 6) .forEach(System.out::println); System.out.println(); // unusual sequence starting with 4, unusual update, just 5 numbers IntStream.iterate(4, n -> n * n - 7) .limit(5) .forEach(System.out::println); System.out.println(); // print factorials of 0 through 10, factorial itself is written using // a range IntStream.range(1, 11) .map(Examples::factorial) .forEach(System.out::println); System.out.println(); // print primes between 1 and 25, primes itself is written using // a range IntStream.range(1, 26) .filter(Examples::isPrime) .forEach(System.out::println); System.out.println(); } // factorial function written with range and reduce public static int factorial(int n) { return IntStream.range(2, n + 1) .reduce(1, (a, b) -> a * b); } // isPrime function that checks to see that the only factors of n are 1 and // n (exactly 2 factors)...this isn't very efficient (could check just up // to the square root) public static boolean isPrime(int n) { return IntStream.range(1, n + 1) .filter(x -> n % x == 0) .count() == 2; } // example of finding the sum of the primes between 1 and 20,000 with and // without parallel processing public static void primesExample() { // check it 3 times, reporting how long it takes for (int i = 0; i < 3; i++) { printSum(IntStream.range(1, 20001)); } System.out.println(); // do it again, but with a parallel stream for (int i = 0; i < 3; i++) { printSum(IntStream.range(1, 20001).parallel()); } System.out.println(); } // times how long it takes to find the sum of the primes in the stream public static void printSum(IntStream s) { // run the algorithm and time it long start = System.currentTimeMillis(); int n = s.filter(Examples::isPrime).sum(); double elapsed = (System.currentTimeMillis() - start) / 1000.0; System.out.println("n = " + n + ", time = " + elapsed); } // shows how parallelism can go bad public static void funnyExample() { // print 1 through 20 in sequence IntStream.range(1, 21) .forEach(System.out::println); System.out.println(); // allow Java to parallelize it, which scrambles the sequence IntStream.range(1, 21) .parallel() .forEach(System.out::println); System.out.println(); } // Example that shows how an entire file can be read line by line. This // program reads from the text of Moby Dick. public static void linesExample() throws IOException { // Print statistics for line lengths. Notice that "mapToInt" is used // instead of "map" because the stream type changes from a stream of // String objects to a stream of primitive ints. System.out.println(Files.lines(Paths.get("moby.txt")) .mapToInt(String::length) .summaryStatistics()); System.out.println(); // This version filters for lines containing "bulkington" System.out.println(Files.lines(Paths.get("moby.txt")) .filter(s -> s.toLowerCase().contains("bulkington")) .mapToInt(String::length) .summaryStatistics()); System.out.println(); // this version uses the "peek" option to print the lines System.out.println(Files.lines(Paths.get("moby.txt")) .filter(s -> s.toLowerCase().contains("bulkington")) .peek(System.out::println) .mapToInt(String::length) .summaryStatistics()); System.out.println(); } }