1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
package com.read.file; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.stream.Stream; public class MyFileReader { public static void main(String[] args) { Path file = Paths.get("C:\\Users\\akumaras\\workspace\\test\\src\\com\\read\\file\\readme.txt"); try { //Java 8: Stream class Stream<String> lines = Files.lines( file, StandardCharsets.UTF_8 ); for( String line : (Iterable<String>) lines::iterator ) { System.out.println("read=" + line); } } catch (Exception e){ e.printStackTrace(); } } } |
Output:
1 2 |
read=A big brown fox read=jumped over the fence |
#1 double colon notation ::
The new double colon (::) operator that Java 8 has to convert a normal method into lambda expression. So,
Instead of:
1 |
list.forEach(n -> System.out.println(n)); |
You can do:
1 |
list.forEach(System.out::println); |
#2 Why is stream::iterator used?
“lines::iterator” where iterator() is an instance method on “BaseStream<T,Stream<T>>” from which java.util.Stream<T> extends. The “iterator()” returns an “Iterator<T>”. The for each loop works on Iterable<T>.
1 |
for (element : iterable); |
So, given a Stream s, the following results in an Iterable:
1 |
s::iterator |
If you want to use this directly in an enhanced-for loop, you have to apply a cast in order to establish a target type for the method reference.
1 |
for( String line : (Iterable<String>) lines::iterator ) |
#3 Iterator Vs Iterable difference?
An Iterable<T> is a simple representation of a series of elements that can be iterated over, and it does not have any iteration state such as a “current element”. Instead, it has a “iterator()” method that produces an Iterator. Implementing this interface allows an object to be the target of the “for-each loop” statement.
An Iterator<T> is the object with iteration state to let you check if it has more elements using hasNext() and move to the next() element.
Read from the classpath
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
package com.read.file; import java.net.URL; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.stream.Stream; public class MyFileReader { public static void main(String[] args) { Path file = null; try { //read from the classpath URL url = MyFileReader.class.getResource("readme.txt"); file = Paths.get(url.toURI()); //Java 8: Stream class Stream<String> lines = Files.lines( file, StandardCharsets.UTF_8 ); for( String line : (Iterable<String>) lines::iterator) { System.out.println("read=" + line); } } catch (Exception e){ e.printStackTrace(); } } } |
Output:
1 2 |
read=A big brown fox read=jumped over the fence |
Filter the line that has “fox”
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
package com.read.file; import java.net.URL; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Optional; import java.util.stream.Stream; public class MyFileReader { public static void main(String[] args) { Path file = null; try { //read from the classpath URL url = MyFileReader.class.getResource("readme.txt"); file = Paths.get(url.toURI()); //Java 8: Stream class Stream<String> lines = Files.lines( file, StandardCharsets.UTF_8 ); //Java 8 Optional class with Lambda expression s -> s.contains("fox") Optional<String> lineThatHasFox = lines.filter(s -> s.contains("fox")).findFirst(); if(lineThatHasFox.isPresent()){ System.out.println(lineThatHasFox.get()); } } catch (Exception e){ e.printStackTrace(); } } } |
Output:
1 |
A big brown fox |
Note: filter() is an intermediate operation, returning a Stream, and findFirst() is a terminal operation.
Count lines
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
package com.read.file; import java.net.URL; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; public class MyFileReader { public static void main(String[] args) { Path file = null; try { //read from the classpath URL url = MyFileReader.class.getResource("readme.txt"); file = Paths.get(url.toURI()); long count = Files.lines( file, StandardCharsets.UTF_8 ).count(); System.out.println("count lines=" + count); } catch (Exception e){ e.printStackTrace(); } } } |
Output:
1 |
count lines=2 |
Note: count() is a terminal operation as it does not return a stream.
Can you workout the output of the following code?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
package com.read.file; import static java.util.stream.Collectors.toList; import java.net.URL; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.List; import java.util.Arrays; public class MyFileReader { public static void main(String[] args) { Path file = null; try { //read from the classpath URL url = MyFileReader.class.getResource("readme.txt"); file = Paths.get(url.toURI()); List<String> output = Files.lines( file, StandardCharsets.UTF_8 ) .filter(s -> s.contains("fox")) .map(line -> line.split("\\s+")) .flatMap(Arrays::stream) .limit(2) .collect(toList()); System.out.println(output); } catch (Exception e){ e.printStackTrace(); } } } |
Output:
An array of size two containing …..
1 |
[A, big] |