www.xsolve.plAgile Software House
Advantages of functional
programming in Java 8
www.xsolve.plAgile Software House
www.xsolve.plAgile Software House
● 10:00 - 10:25 Welcome!
● 10:30 - 10:40 Functional Programming
● 10:40 - 11:55 Lambdas
● 12:10 - 13:25 Streams
● 13:55 - 15:00 File IO
Agenda
Functional Programming
www.xsolve.plAgile Software House
● Concise
● Little “Boilerplate”
Functional Programming in JVM
www.xsolve.plAgile Software House
● Groovy: Closures
● Java 6:
● Java8 - Lambdas!
www.xsolve.plAgile Software House
Lambdas
// Java 7
button.addActionListener( new ActionListener () {
@Override
public void actionPerformed(ActionEvent e){
doSomethingWith(e) ;
}
});
Motivation
www.xsolve.plAgile Software House
// Java 8
button.addActionListener(
e -> doSomethingWith(e)) ;
vs
// Java 7
Collections. sort(list, new Comparator<Integer>() {
@Overide
public int compare(final Integer o1,
final Integer o2) {
return o2.compareTo(o1) ;
}
});
Motivation
www.xsolve.plAgile Software House
// Java 8
Collections. sort(
list, (o1, o2) -> o2.compareTo(o1)) ;
vs
Lambda syntax
www.xsolve.plAgile Software House
new Comparator<String>() {
@Override
public int compare(final String s1, final String s2) {
return s1.length() - s2.length();
}
}
(s1, s2) -> {
return s1.length() - s2.length();
}
(s1, s2) -> s1.length() - s2.length()
(final String s1, final String s2) -> {
return s1.length() - s2.length();
}
(final String s1, final String s2) -> {
return s1.length() - s2.length();
}
(final String s1, final String s2) -> {
return s1.length() - s2.length();
}
new Comparator<String>() {
@Override
public int compare(final String s1, final String s2) {
return s1.length() - s2.length();
}
}
(s1, s2) -> {
return s1.length() - s2.length();
}
Sorting Strings by Length
www.xsolve.plAgile Software House
// Java 7 example
Collections .sort(list,
new Comparator<String>() {
@Override
public int compare(final String s1, final String s2) {
return s1.length() - s2.length() ;
}
}
);
// Java 8 alternative
Collections .sort(list, (s1, s2) -> s1.length() - s2.length()) ;
Lambda syntax (one argument)
www.xsolve.plAgile Software House
(s) -> s.toUpperCase()
() -> doSomething()
s -> s.toUpperCase()
Method references
www.xsolve.plAgile Software House
(args) -> ClassName.staticMethodName( args)
ClassName::staticMethodName
// Examples
Math::cos
Arrays::sort
String::valueOf
String::length
Integer::compareTo
Method references
www.xsolve.plAgile Software House
Method Ref Type Example Equivalent Lambda
SomeClass::staticMethod Math::cos x -> Math.cos(x)
someObject::instanceMethod someString::toUpperCase () -> someString.toUpperCase()
SomeClass::instanceMethod String::toUpperCase s -> s.toUpperCase()
SomeClass::new Employee::new () -> new Employee()
Lambdas with big body
www.xsolve.plAgile Software House
addActionListener(e -> {
prepareFuel();
/*
…
*/
launch(e);
});
addActionListener(this::fireNuclearRocket);
void fireNuclearRocket(ActionEvent e) {
prepareFuel();
/*
…
*/
launch(e);
}
Functional interface
www.xsolve.plAgile Software House
@FunctionalInterface
interface MyOperation {
String apply(String s);
}
String transform(String s, MyOperation mo) {
String result = mo.apply(s) ;
log(s + " : " + result);
return result;
} // Java 7
transform("Java8", new MyOperation() {
@Override
public String apply(String s) {
return s.toUpperCase() ;
}
});
// Java 8
transform("Java8", s -> s.toUpperCase()) ;
Simplification 1
www.xsolve.plAgile Software House
transform("Java8", s -> s.toUpperCase()) ; transform("Java8", String::toLowerCase );
transform("Java8", String::toUpperCase) ;
transform("Java8", String::trim);
Simplification 2 (java.util.function)
www.xsolve.plAgile Software House
// before
@FunctionalInterface
interface MyOperation {
String apply(String s);
}
String transform(String s, MyOperation mo) {
String result = mo.apply(s) ;
log(s + " : " + result);
return result;
}
// after
String transform(String s, UnaryOperator <String> uo) {
String result = uo.apply(s) ;
log(s + "<->" + result);
return result;
}
java.util.function
www.xsolve.plAgile Software House
INTERFACE METHOD
Consumer<T> void accept(T t)
Supplier<T> T get()
Function<T, R> R apply(T t)
UnaryOperator<T> T apply(T t)
Predicate<T> boolean test(T t)
Lambdas summary
www.xsolve.plAgile Software House
● Lambda syntax: (arg1, arg2) -> arg2.compareTo(arg1)
● Method references: String::length
● @FunctionalInterface
● java.util.function
www.xsolve.plAgile Software House
Streams
Streams - motivation
www.xsolve.plAgile Software House
● C / C++ - arrays…
● Java / C# - Collections (List, Set…)
● Java 8 - Streams - Collections taken to another level!
Streams - example
www.xsolve.plAgile Software House
protected List<Book> books = new ArrayList<>();
public void init(){
String tolkien = "J.R.R. Tolkien";
String rowling = "J.K. Rowling";
String norris = "David Norris";
String theGod = "God Almighty";
books.addAll(Arrays.asList(
new Book("The Lord of the Rings", tolkien, 1216),
new Book("Silmarillion", tolkien, 365),
new Book("Harry Potter and the Philosopher's Stone", rowling, 223),
new Book("Harry Potter and the Half-Blood Prince", rowling, 554),
new Book("Harry Potter and the Deathly Hallows", rowling, 607),
new Book("Teach yourself Croatian", norris, 352),
new Book("The Bible", theGod, 1200),
new Book("The Hobbit", tolkien, 320)
));
TODO: find out● the authors● of the top-3● thickest books● other than the Bible
Streams - example
www.xsolve.plAgile Software House
// 1. filter out the Bible
List<Book> booksFiltered = new ArrayList<>();
for (Book book : books){
if (! "The Bible".equals(book.getTitle())) {
booksFiltered.add(book);
}
}
Java7 approach
Streams - example
www.xsolve.plAgile Software House
// 2. sort by number of pages, descending
booksFiltered.sort(new Comparator<Book>() {
@Override
public int compare(Book o1, Book o2) {
return o2.getPages().compareTo(o1.getPages());
}
});
Java7 approach
Streams - example
www.xsolve.plAgile Software House
// 3. list the authors
for (int i=0; i<3; i++) {
System.out.println(booksFiltered.get(i).getAuthor());
}
Java7 approach
Streams - example
www.xsolve.plAgile Software House
books.stream()
.filter(b -> ! "The Bible".equals(b.getTitle()))
.sorted((b1, b2) -> b2.getPages().compareTo(b1.getPages()))
.limit(3)
.map(Book::getAuthor)
.distinct()
.forEach(System.out::println);
Streams to the rescue!
TODO: find out● the authors● of the top-3● thickest books● other than the Bible
Streams - what are they?
www.xsolve.plAgile Software House
● Interface: Stream<String>, Stream<Book>...
● NOT data structures
● Just wrappers around existing data sources (Collections, Files…)
● Do NOT modify the contents of the underlying data sources
● InputStream, ObjectInputStream, FileInputStream
Streams - characteristics
www.xsolve.plAgile Software House
● Easily obtained from arrays or Collections
List aList = new ArrayList();
aList.stream();
Collection aCollection = new LinkedHashSet<>();
aCollection.stream();
Integer[] anArray = {1, 2, 3, 4, 5};
Stream.of(anArray); // Stream<Integer>
Stream.of("Hickory", "Dickory", "Dock");
// Stream<String>
aList.stream().filter(o -> o != null);
// Stream from another stream!
Chaining!
Streams - characteristics
www.xsolve.plAgile Software House
● Easily obtained from arrays or Collections
● ...and transformed into arrays or Collections
List aList =
aStream.collect(Collectors.toList());
Object[] anArray = aStream.toArray();
Streams - characteristics
www.xsolve.plAgile Software House
● Easily obtained from arrays or Collections
● ...and transformed into arrays or Collections
● Designed for Lambdas
aStream
.filter(b -> ! "Moby Dick".equals(b.getTitle()))
.sorted((b1, b2) ->
b2.getPages().compareTo(b1.getPages()))
.map(Book::getAuthor)
Streams - characteristics
www.xsolve.plAgile Software House
● Easily obtained from arrays or Collections
● ...and transformed into arrays or Collections
● Designed for Lambdas
● Lazy (!)
Streams - characteristics
www.xsolve.plAgile Software House
● Easily obtained from arrays or Collections
● ...and transformed into arrays or Collections
● Designed for Lambdas
● Lazy (!)
● Parallelizable (!!!)
bookCollection.parallelStream().forEach(book -> {
// do some badass long operation on the book
}
);
bookStream.parallel().forEach(book -> {
// do some badass long operation on the book
}
);
Streams - core methods (1/3)
www.xsolve.plAgile Software House
● forEach
void forEach(Consumer)
void forEachOrdered(Consumer)
Stream.of("Facebook", "Google", "xSolve")
.forEach(System.out::println);
output?
List<String> list =
Arrays.asList("Facebook",
"Google", "xSolve");
list.stream().forEach(String::toUpperCase);
System.out.println(list);
output?
Stream.of("Facebook", "Google", "xSolve")
.forEach(System.out::println).forEach
Stream.of("Facebook", "Google", "xSolve")
.forEach(System.out::println);
output:
Facebook
Google
xSolve
List<String> list =
Arrays.asList("Facebook",
"Google", "xSolve");
list.stream().forEach(String::toUpperCase);
System.out.println(list);
output: [Facebook, Google, xSolve]
Streams - core methods (1/3)
www.xsolve.plAgile Software House
● forEach
void forEach(Consumer)
void forEachOrdered(Consumer)
● map
(mapToDouble, mapToInt, mapToLong)
Stream map(Function mapper)
Stream.of("Facebook", "Google", "xSolve")
.map(str -> str.startsWith("x"))
.forEach(System.out::println);
output?
int sum = Stream.of("1", "2", "3")
.mapToInt(Integer::parseInt)
.sum();
System.out.println(sum);
output?
Stream.of("Facebook", "Google", "xSolve")
.map(str -> str.startsWith("x"))
.forEach(System.out::println);
output:
false
false
true
int sum = Stream.of("1", "2", "3")
.mapToInt(Integer::parseInt)
.sum();
System.out.println(sum);
output:
6
Streams - core methods (1/3)
www.xsolve.plAgile Software House
● forEach
void forEach(Consumer)
void forEachOrdered(Consumer)
● map
(mapToDouble, mapToInt, mapToLong)
Stream map(Function)
● filter
Stream filter(Predicate)
Stream.of("Facebook", "Google", "xSolve")
.filter(str ->
Character.isLowerCase(str.charAt(0)))
.forEach(System.out::println);
output?
Stream.of("Facebook", "Google", "xSolve")
.filter(str ->
Character.isLowerCase(str.charAt(0)))
.forEach(System.out::println);
output: xSolve
Streams - core methods (2/3)
www.xsolve.plAgile Software House
● findFirst
Optional findFirst()
String firstFound = Stream.of("Facebook",
"Google", "xSolve")
.filter(str -> str.contains("oo"))
.findFirst()
.get();
output?
String notFound = Stream.of("Facebook",
"Google", "xSolve")
.filter(str -> str.contains("yay!"))
.findFirst()
.orElse("404 not found :(");
System.out.println(notFound);
output?
String firstFound = Stream.of("Facebook",
"Google", "xSolve")
.filter(str -> str.contains("oo"))
.findFirst()
.get();
output: Facebook
String notFound = Stream.of("Facebook",
"Google", "xSolve")
.filter(str -> str.contains("yay!"))
.findFirst()
.orElse("404 not found :(");
System.out.println(notFound);
output:
404 not found :(
Streams - core methods (2/3)
www.xsolve.plAgile Software House
● findFirst
Optional findFirst()
● findAny
Optional findAny()
String anyFound = Stream.of("Facebook",
"Google", "xSolve")
.parallel()
.findAny()
.get();
System.out.println(anyFound);
output?
String anyFound = Stream.of("Facebook",
"Google", "xSolve")
.parallel()
.findAny()
.get();
System.out.println(anyFound);
output: Facebook
or: Google
or: xSolve
Streams - core methods (2/3)
www.xsolve.plAgile Software House
● findFirst
Optional findFirst()
● findAny
Optional findAny()
● collect
collect(Collector collector)
List<String> uppers = Stream.of("cyan",
"magenta", "yellow", "black")
.map(String::toUpperCase)
.collect(Collectors.toList());
System.out.println(uppers);
output?
List<String> uppers = Stream.of("cyan",
"magenta", "yellow", "black")
.map(String::toUpperCase)
.collect(Collectors.toList());
System.out.println(uppers);
output: [CYAN, MAGENTA, YELLOW, BLACK]
Streams - core methods (2/3)
www.xsolve.plAgile Software House
● findFirst
Optional findFirst()
● findAny
Optional findAny()
● collect
collect(Collector collector)
● toArray
Object[] toArray()
Object[] objArray = Stream.of("cyan",
"magenta", "yellow", "black")
.map(String::toUpperCase)
.toArray();
String[] strArray = Stream.of("cyan",
"magenta", "yellow", "black")
.map(String::toUpperCase)
.toArray(String[]::new);
Streams - core methods (3/3)
www.xsolve.plAgile Software House
● Reduce
T reduce(T starter, BinaryOperator)
Optional reduce(BinaryOperator)
String concatStarter =
Stream.of("A", "n", "n", "a")
.reduce("Lady ", String::concat);
System.out.println(concatStarter);
output?
String concat =
Stream.of("A", "n", "n", "a")
.reduce(String::concat)
.get();
System.out.println(concat);
output?
❏ Stream → single value
❏ IntStream – min(), max(),
sum(), average()
String concatStarter =
Stream.of("A", "n", "n", "a")
.reduce("Lady ", String::concat);
System.out.println(concatStarter);
output: Lady Anna
String concat =
Stream.of("A", "n", "n", "a")
.reduce(String::concat)
.get();
System.out.println(concat);
output: Anna
Streams - core methods (3/3)
www.xsolve.plAgile Software House
● Reduce
T reduce(T starter, BinaryOperator)
Optional reduce(BinaryOperator)
● boolean allMatch(Predicate)
boolean noneMatch(Predicate)
boolean anyMatch(Predicate)
boolean allMatch = Stream.of("Veronica",
"Anna", "Patricia", "Alan", "Thomas")
.allMatch(str -> str.endsWith("a"));
System.out.println(allMatch);
output?
boolean noneMatch = Stream.of("Veronica",
"Anna", "Patricia", "Alan", "Thomas")
.noneMatch(str -> str.endsWith("a"));
System.out.println(noneMatch);
output?
boolean anyMatch = Stream.of("Veronica",
"Anna", "Patricia", "Alan", "Thomas")
.anyMatch(str -> str.endsWith("a"));
System.out.println(anyMatch);
output?
boolean allMatch = Stream.of("Veronica",
"Anna", "Patricia", "Alan", "Thomas")
.allMatch(str -> str.endsWith("a"));
System.out.println(allMatch);
output: false
boolean noneMatch = Stream.of("Veronica",
"Anna", "Patricia", "Alan", "Thomas")
.noneMatch(str -> str.endsWith("a"));
System.out.println(noneMatch);
output: false
boolean anyMatch = Stream.of("Veronica",
"Anna", "Patricia", "Alan", "Thomas")
.anyMatch(str -> str.endsWith("a"));
System.out.println(anyMatch);
output: true
Streams - core methods (3.5/3)
www.xsolve.plAgile Software House
● long count()
● Stream sorted()
● Stream distinct()
● Stream limit(long maxSize)
● Stream skip(long n)
Streams - Terminal vs Non Terminal operations
www.xsolve.plAgile Software House
Terminal
(consume a Stream)
● forEach, forEachOrdered
● toArray, reduce, collect
● min, max, count
● anyMatch, allMatch,
noneMatch
● findFirst, findAny
Non-terminal
(return another Stream)
● map
● filter
● distinct, sorted
● peek
● limit, skip
● parallel, sequential,
unordered
Terminal
(consume a Stream)
● forEach, forEachOrdered
● toArray, reduce, collect
● min, max, count
● anyMatch, allMatch,
noneMatch
● findFirst, findAny
Non-terminal
(return another Stream)
● map
● filter
● distinct, sorted
● peek
● limit, skip
● parallel, sequential,
unordered
Short-circuit
operations
Streams - lazy evaluation
www.xsolve.plAgile Software House
books.addAll(Arrays. asList(
new Book("The Lord of the Rings" , tolkien, 1216),
new Book("Silmarillion" , tolkien, 365),
new Book("Harry Potter and something" , rowling, 223),
new Book("Harry Potter and blahblah" , rowling, 554)
// + 500k entries
));
books.stream()
.filter(it -> {
System. out.println("name: " + nameFilterCounter ++);
return "J.K. Rowling" .equals(it.getAuthor()) ;
})
.filter(it -> {
System. out.println("tpages: " +
pageFilterCounter ++);
return it.getPages() > 500;
})
.findFirst() ;
name: 0
name: 1
name: 2
pages: 0
name: 3
pages: 1
books.addAll(Arrays. asList(
new Book("The Lord of the Rings" , tolkien, 1216),
new Book("Silmarillion" , tolkien, 365),
new Book("Harry Potter and something" , rowling, 223),
new Book("Harry Potter and blahblah" , rowling, 554)
// + 500k entries
));
books.stream()
.filter(it -> {
System. out.println("name: " + nameFilterCounter ++);
return "J.K. Rowling" .equals(it.getAuthor()) ;
})
.filter(it -> {
System. out.println("tpages: " +
pageFilterCounter ++);
return it.getPages() > 500;
})
.findFirst(); ← short-circuit operation!
Streams - what you can’t do
www.xsolve.plAgile Software House
● Reuse Stream stream = Stream.of("J", "a", "v", "a");
stream.filter(...).map(...)
stream.map(...).forEach(...)
Streams - what you can’t do
www.xsolve.plAgile Software House
● Reuse
● Change surrounding local variables
int total = 0;
Stream.of("Mercury", "Venus", "Mars")
.forEach(str -> {
total += str.length();
});
int[] total = {0};
Stream.of("Mercury", "Venus", "Mars")
.forEach(str -> {
total[0] += str.length();
});
...but:
www.xsolve.plAgile Software House
File IO
www.xsolve.plAgile Software House
www.xsolve.plAgile Software House
File IO
Java6 approach
public void readFile() {
File file =
new File("/home/grzegorz/file.txt");
FileInputStream fis = null;
try {
fis = new FileInputStream(file);
int content;
while ((content = fis.read()) != -1) {
System.out.print((char) content);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (null != fis) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
www.xsolve.plAgile Software House
File IO
Java6 approach
Java7 approach
- java.lang.AutoCloseable
- java.io.Closeable
public void readFile() {
File file =
new File("/home/grzegorz/file.txt");
try (FileInputStream fis =
new FileInputStream(file)) {
int content;
while ((content = fis.read()) != -1) {
System.out.print((char) content);
}
} catch (IOException e) {
e.printStackTrace();
}
}
public void readFile() {
File file =
new File("/home/grzegorz/file.txt");
FileInputStream fis = null;
try {
fis = new FileInputStream(file);
int content;
while ((content = fis.read()) != -1) {
System.out.print((char) content);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (null != fis) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
www.xsolve.plAgile Software House
File IO
public void readFile() {
Path filePath =
Paths.get("/home/grzegorz/file.txt");
try (Stream<String> stream =
Files.lines(filePath)) {
stream.forEach(System.out::print);
} catch (IOException e) {
e.printStackTrace();
}
}
Java8 approach
public void readFile() {
File file =
new File("/home/grzegorz/file.txt");
try (FileInputStream fis =
new FileInputStream(file)) {
int content;
while ((content = fis.read()) != -1) {
System.out.print((char) content);
}
} catch (IOException e) {
e.printStackTrace();
}
}
Java7 approach
www.xsolve.plAgile Software House
File IO
public void readFile() {
File file =
new File("/home/grzegorz/file.txt");
FileInputStream fis = null;
try {
fis = new FileInputStream(file);
int content;
while ((content = fis.read()) != -1) {
System.out.print((char) content);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (null != fis) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Java6 approach
public void readFile() {
Path filePath =
Paths.get("/home/grzegorz/file.txt");
try (Stream<String> stream =
Files.lines(filePath)) {
stream.forEach(System.out::print);
} catch (IOException e) {
e.printStackTrace();
}
}
Java8 approach
vs.
www.xsolve.plAgile Software House
File IO - Path vs. File
“There is no one-to-one correspondence between the two APIs …”
http://docs.oracle.com/javase/tutorial/essential/io/legacy.html
www.xsolve.plAgile Software House
File IO - How to get Path?
Path p1 = Paths.get("some-file.txt");
Path p2 = Paths.get("C:MyFolderanother-file.txt");
www.xsolve.plAgile Software House
File IO - Methods of Path class
Methods:
toAbsolutePath, startsWith, endsWith, getFileName, getName,
getNameCount, subpath, getParent, getRoot, normalize, relativize
Sample Method Result
toAbsolutePath C:eclipse-workspacejavafile-ioinput-file.txt
getFileName input-file.tx
getRoot C:
www.xsolve.plAgile Software House
File IO - File.lines
Stream<String> lines = Files.lines("some-path");
● Can use all the cool and powerful Stream methods.
● Lazy evaluation.
● Throws IOException.
● Stream should be closed.
● Stream implements AutoCloseable
www.xsolve.plAgile Software House
File IO - Example
public List<Car> loadCars(Path filePath) {
try (Stream<String> allCars = Files.lines(filePath)) {
return allCars
.filter(car -> hasFourSeats(car))
.filter(carWithFourSeats -> this::isRed)
.map(redCarWithFourSeats -> addDoors(redCarWithFourSeats))
.sorted()
.distinct()
.collect(Collectors.toList());
} catch (IOException e) {
e.printStackTrace();
}
}
www.xsolve.plAgile Software House
File IO - Files.write
Files.write(somePath, lines, someCharset, someOption);
Files.write(somePath, fileArray, someOption);
● somePath to file,
● lines e.g. List<String> lines, bytes[] data
● someCharset e.g. StandardCharsets.UTF_8
● someOption e.q. StandardOpenOption.APPEND
www.xsolve.plAgile Software House
File IO - Files.write
Java7 approach
public void savePoems(List<String>
poems) {
File file = new
File("/home/grzegorz/poems.txt");
try (FileWriter fw = new
FileWriter(file)) {
for (String poem: poems) {
fw.write(poem);
}
} catch (IOException e) {
e.printStackTrace();
}
}
www.xsolve.plAgile Software House
File IO - Files.write
Java7 approach
public void savePoems(List<String>
poems) {
File file = new
File("/home/grzegorz/poems.txt");
try (FileWriter fw = new
FileWriter(file)) {
for (String poem: poems) {
fw.write(poem);
}
} catch (IOException e) {
e.printStackTrace();
}
}
Java8 approach
public void savePoems(List<String> poems) {
Path path =
Paths.get("/home/grzegorz/poems.txt");
try {
Files.write(path, poems,
StandardOpenOption.WRITE);
} catch (IOException e) {
e.printStackTrace();
}
}
www.xsolve.plAgile Software House
www.xsolve.plAgile Software House
● Coreservlets.com, Marty Hall - “Java 8 Tutorial”
http://www.coreservlets.com/java-8-tutorial/
● Confitura 2015, Grzegorz Piwowarek - “Lambdas && Monads” (PL)
https://youtu.be/VglEyjgxAKY
More on Java8
www.xsolve.plAgile Software House
You can find our job offers at
xsolve.pl/career
Thank you for your time!
Questions?
Marriage offers?
Free lunch?
team4java@xsolve.pl

Xlab #1: Advantages of functional programming in Java 8

  • 1.
    www.xsolve.plAgile Software House Advantagesof functional programming in Java 8
  • 2.
  • 3.
    www.xsolve.plAgile Software House ●10:00 - 10:25 Welcome! ● 10:30 - 10:40 Functional Programming ● 10:40 - 11:55 Lambdas ● 12:10 - 13:25 Streams ● 13:55 - 15:00 File IO Agenda
  • 4.
    Functional Programming www.xsolve.plAgile SoftwareHouse ● Concise ● Little “Boilerplate”
  • 5.
    Functional Programming inJVM www.xsolve.plAgile Software House ● Groovy: Closures ● Java 6: ● Java8 - Lambdas!
  • 6.
  • 7.
    // Java 7 button.addActionListener(new ActionListener () { @Override public void actionPerformed(ActionEvent e){ doSomethingWith(e) ; } }); Motivation www.xsolve.plAgile Software House // Java 8 button.addActionListener( e -> doSomethingWith(e)) ; vs
  • 8.
    // Java 7 Collections.sort(list, new Comparator<Integer>() { @Overide public int compare(final Integer o1, final Integer o2) { return o2.compareTo(o1) ; } }); Motivation www.xsolve.plAgile Software House // Java 8 Collections. sort( list, (o1, o2) -> o2.compareTo(o1)) ; vs
  • 9.
    Lambda syntax www.xsolve.plAgile SoftwareHouse new Comparator<String>() { @Override public int compare(final String s1, final String s2) { return s1.length() - s2.length(); } } (s1, s2) -> { return s1.length() - s2.length(); } (s1, s2) -> s1.length() - s2.length() (final String s1, final String s2) -> { return s1.length() - s2.length(); } (final String s1, final String s2) -> { return s1.length() - s2.length(); } (final String s1, final String s2) -> { return s1.length() - s2.length(); } new Comparator<String>() { @Override public int compare(final String s1, final String s2) { return s1.length() - s2.length(); } } (s1, s2) -> { return s1.length() - s2.length(); }
  • 10.
    Sorting Strings byLength www.xsolve.plAgile Software House // Java 7 example Collections .sort(list, new Comparator<String>() { @Override public int compare(final String s1, final String s2) { return s1.length() - s2.length() ; } } ); // Java 8 alternative Collections .sort(list, (s1, s2) -> s1.length() - s2.length()) ;
  • 11.
    Lambda syntax (oneargument) www.xsolve.plAgile Software House (s) -> s.toUpperCase() () -> doSomething() s -> s.toUpperCase()
  • 12.
    Method references www.xsolve.plAgile SoftwareHouse (args) -> ClassName.staticMethodName( args) ClassName::staticMethodName // Examples Math::cos Arrays::sort String::valueOf String::length Integer::compareTo
  • 13.
    Method references www.xsolve.plAgile SoftwareHouse Method Ref Type Example Equivalent Lambda SomeClass::staticMethod Math::cos x -> Math.cos(x) someObject::instanceMethod someString::toUpperCase () -> someString.toUpperCase() SomeClass::instanceMethod String::toUpperCase s -> s.toUpperCase() SomeClass::new Employee::new () -> new Employee()
  • 14.
    Lambdas with bigbody www.xsolve.plAgile Software House addActionListener(e -> { prepareFuel(); /* … */ launch(e); }); addActionListener(this::fireNuclearRocket); void fireNuclearRocket(ActionEvent e) { prepareFuel(); /* … */ launch(e); }
  • 15.
    Functional interface www.xsolve.plAgile SoftwareHouse @FunctionalInterface interface MyOperation { String apply(String s); } String transform(String s, MyOperation mo) { String result = mo.apply(s) ; log(s + " : " + result); return result; } // Java 7 transform("Java8", new MyOperation() { @Override public String apply(String s) { return s.toUpperCase() ; } }); // Java 8 transform("Java8", s -> s.toUpperCase()) ;
  • 16.
    Simplification 1 www.xsolve.plAgile SoftwareHouse transform("Java8", s -> s.toUpperCase()) ; transform("Java8", String::toLowerCase ); transform("Java8", String::toUpperCase) ; transform("Java8", String::trim);
  • 17.
    Simplification 2 (java.util.function) www.xsolve.plAgileSoftware House // before @FunctionalInterface interface MyOperation { String apply(String s); } String transform(String s, MyOperation mo) { String result = mo.apply(s) ; log(s + " : " + result); return result; } // after String transform(String s, UnaryOperator <String> uo) { String result = uo.apply(s) ; log(s + "<->" + result); return result; }
  • 18.
    java.util.function www.xsolve.plAgile Software House INTERFACEMETHOD Consumer<T> void accept(T t) Supplier<T> T get() Function<T, R> R apply(T t) UnaryOperator<T> T apply(T t) Predicate<T> boolean test(T t)
  • 19.
    Lambdas summary www.xsolve.plAgile SoftwareHouse ● Lambda syntax: (arg1, arg2) -> arg2.compareTo(arg1) ● Method references: String::length ● @FunctionalInterface ● java.util.function
  • 20.
  • 21.
  • 22.
    Streams - motivation www.xsolve.plAgileSoftware House ● C / C++ - arrays… ● Java / C# - Collections (List, Set…) ● Java 8 - Streams - Collections taken to another level!
  • 23.
    Streams - example www.xsolve.plAgileSoftware House protected List<Book> books = new ArrayList<>(); public void init(){ String tolkien = "J.R.R. Tolkien"; String rowling = "J.K. Rowling"; String norris = "David Norris"; String theGod = "God Almighty"; books.addAll(Arrays.asList( new Book("The Lord of the Rings", tolkien, 1216), new Book("Silmarillion", tolkien, 365), new Book("Harry Potter and the Philosopher's Stone", rowling, 223), new Book("Harry Potter and the Half-Blood Prince", rowling, 554), new Book("Harry Potter and the Deathly Hallows", rowling, 607), new Book("Teach yourself Croatian", norris, 352), new Book("The Bible", theGod, 1200), new Book("The Hobbit", tolkien, 320) )); TODO: find out● the authors● of the top-3● thickest books● other than the Bible
  • 24.
    Streams - example www.xsolve.plAgileSoftware House // 1. filter out the Bible List<Book> booksFiltered = new ArrayList<>(); for (Book book : books){ if (! "The Bible".equals(book.getTitle())) { booksFiltered.add(book); } } Java7 approach
  • 25.
    Streams - example www.xsolve.plAgileSoftware House // 2. sort by number of pages, descending booksFiltered.sort(new Comparator<Book>() { @Override public int compare(Book o1, Book o2) { return o2.getPages().compareTo(o1.getPages()); } }); Java7 approach
  • 26.
    Streams - example www.xsolve.plAgileSoftware House // 3. list the authors for (int i=0; i<3; i++) { System.out.println(booksFiltered.get(i).getAuthor()); } Java7 approach
  • 27.
    Streams - example www.xsolve.plAgileSoftware House books.stream() .filter(b -> ! "The Bible".equals(b.getTitle())) .sorted((b1, b2) -> b2.getPages().compareTo(b1.getPages())) .limit(3) .map(Book::getAuthor) .distinct() .forEach(System.out::println); Streams to the rescue! TODO: find out● the authors● of the top-3● thickest books● other than the Bible
  • 28.
    Streams - whatare they? www.xsolve.plAgile Software House ● Interface: Stream<String>, Stream<Book>... ● NOT data structures ● Just wrappers around existing data sources (Collections, Files…) ● Do NOT modify the contents of the underlying data sources ● InputStream, ObjectInputStream, FileInputStream
  • 29.
    Streams - characteristics www.xsolve.plAgileSoftware House ● Easily obtained from arrays or Collections List aList = new ArrayList(); aList.stream(); Collection aCollection = new LinkedHashSet<>(); aCollection.stream(); Integer[] anArray = {1, 2, 3, 4, 5}; Stream.of(anArray); // Stream<Integer> Stream.of("Hickory", "Dickory", "Dock"); // Stream<String> aList.stream().filter(o -> o != null); // Stream from another stream! Chaining!
  • 30.
    Streams - characteristics www.xsolve.plAgileSoftware House ● Easily obtained from arrays or Collections ● ...and transformed into arrays or Collections List aList = aStream.collect(Collectors.toList()); Object[] anArray = aStream.toArray();
  • 31.
    Streams - characteristics www.xsolve.plAgileSoftware House ● Easily obtained from arrays or Collections ● ...and transformed into arrays or Collections ● Designed for Lambdas aStream .filter(b -> ! "Moby Dick".equals(b.getTitle())) .sorted((b1, b2) -> b2.getPages().compareTo(b1.getPages())) .map(Book::getAuthor)
  • 32.
    Streams - characteristics www.xsolve.plAgileSoftware House ● Easily obtained from arrays or Collections ● ...and transformed into arrays or Collections ● Designed for Lambdas ● Lazy (!)
  • 33.
    Streams - characteristics www.xsolve.plAgileSoftware House ● Easily obtained from arrays or Collections ● ...and transformed into arrays or Collections ● Designed for Lambdas ● Lazy (!) ● Parallelizable (!!!) bookCollection.parallelStream().forEach(book -> { // do some badass long operation on the book } ); bookStream.parallel().forEach(book -> { // do some badass long operation on the book } );
  • 34.
    Streams - coremethods (1/3) www.xsolve.plAgile Software House ● forEach void forEach(Consumer) void forEachOrdered(Consumer) Stream.of("Facebook", "Google", "xSolve") .forEach(System.out::println); output? List<String> list = Arrays.asList("Facebook", "Google", "xSolve"); list.stream().forEach(String::toUpperCase); System.out.println(list); output? Stream.of("Facebook", "Google", "xSolve") .forEach(System.out::println).forEach Stream.of("Facebook", "Google", "xSolve") .forEach(System.out::println); output: Facebook Google xSolve List<String> list = Arrays.asList("Facebook", "Google", "xSolve"); list.stream().forEach(String::toUpperCase); System.out.println(list); output: [Facebook, Google, xSolve]
  • 35.
    Streams - coremethods (1/3) www.xsolve.plAgile Software House ● forEach void forEach(Consumer) void forEachOrdered(Consumer) ● map (mapToDouble, mapToInt, mapToLong) Stream map(Function mapper) Stream.of("Facebook", "Google", "xSolve") .map(str -> str.startsWith("x")) .forEach(System.out::println); output? int sum = Stream.of("1", "2", "3") .mapToInt(Integer::parseInt) .sum(); System.out.println(sum); output? Stream.of("Facebook", "Google", "xSolve") .map(str -> str.startsWith("x")) .forEach(System.out::println); output: false false true int sum = Stream.of("1", "2", "3") .mapToInt(Integer::parseInt) .sum(); System.out.println(sum); output: 6
  • 36.
    Streams - coremethods (1/3) www.xsolve.plAgile Software House ● forEach void forEach(Consumer) void forEachOrdered(Consumer) ● map (mapToDouble, mapToInt, mapToLong) Stream map(Function) ● filter Stream filter(Predicate) Stream.of("Facebook", "Google", "xSolve") .filter(str -> Character.isLowerCase(str.charAt(0))) .forEach(System.out::println); output? Stream.of("Facebook", "Google", "xSolve") .filter(str -> Character.isLowerCase(str.charAt(0))) .forEach(System.out::println); output: xSolve
  • 37.
    Streams - coremethods (2/3) www.xsolve.plAgile Software House ● findFirst Optional findFirst() String firstFound = Stream.of("Facebook", "Google", "xSolve") .filter(str -> str.contains("oo")) .findFirst() .get(); output? String notFound = Stream.of("Facebook", "Google", "xSolve") .filter(str -> str.contains("yay!")) .findFirst() .orElse("404 not found :("); System.out.println(notFound); output? String firstFound = Stream.of("Facebook", "Google", "xSolve") .filter(str -> str.contains("oo")) .findFirst() .get(); output: Facebook String notFound = Stream.of("Facebook", "Google", "xSolve") .filter(str -> str.contains("yay!")) .findFirst() .orElse("404 not found :("); System.out.println(notFound); output: 404 not found :(
  • 38.
    Streams - coremethods (2/3) www.xsolve.plAgile Software House ● findFirst Optional findFirst() ● findAny Optional findAny() String anyFound = Stream.of("Facebook", "Google", "xSolve") .parallel() .findAny() .get(); System.out.println(anyFound); output? String anyFound = Stream.of("Facebook", "Google", "xSolve") .parallel() .findAny() .get(); System.out.println(anyFound); output: Facebook or: Google or: xSolve
  • 39.
    Streams - coremethods (2/3) www.xsolve.plAgile Software House ● findFirst Optional findFirst() ● findAny Optional findAny() ● collect collect(Collector collector) List<String> uppers = Stream.of("cyan", "magenta", "yellow", "black") .map(String::toUpperCase) .collect(Collectors.toList()); System.out.println(uppers); output? List<String> uppers = Stream.of("cyan", "magenta", "yellow", "black") .map(String::toUpperCase) .collect(Collectors.toList()); System.out.println(uppers); output: [CYAN, MAGENTA, YELLOW, BLACK]
  • 40.
    Streams - coremethods (2/3) www.xsolve.plAgile Software House ● findFirst Optional findFirst() ● findAny Optional findAny() ● collect collect(Collector collector) ● toArray Object[] toArray() Object[] objArray = Stream.of("cyan", "magenta", "yellow", "black") .map(String::toUpperCase) .toArray(); String[] strArray = Stream.of("cyan", "magenta", "yellow", "black") .map(String::toUpperCase) .toArray(String[]::new);
  • 41.
    Streams - coremethods (3/3) www.xsolve.plAgile Software House ● Reduce T reduce(T starter, BinaryOperator) Optional reduce(BinaryOperator) String concatStarter = Stream.of("A", "n", "n", "a") .reduce("Lady ", String::concat); System.out.println(concatStarter); output? String concat = Stream.of("A", "n", "n", "a") .reduce(String::concat) .get(); System.out.println(concat); output? ❏ Stream → single value ❏ IntStream – min(), max(), sum(), average() String concatStarter = Stream.of("A", "n", "n", "a") .reduce("Lady ", String::concat); System.out.println(concatStarter); output: Lady Anna String concat = Stream.of("A", "n", "n", "a") .reduce(String::concat) .get(); System.out.println(concat); output: Anna
  • 42.
    Streams - coremethods (3/3) www.xsolve.plAgile Software House ● Reduce T reduce(T starter, BinaryOperator) Optional reduce(BinaryOperator) ● boolean allMatch(Predicate) boolean noneMatch(Predicate) boolean anyMatch(Predicate) boolean allMatch = Stream.of("Veronica", "Anna", "Patricia", "Alan", "Thomas") .allMatch(str -> str.endsWith("a")); System.out.println(allMatch); output? boolean noneMatch = Stream.of("Veronica", "Anna", "Patricia", "Alan", "Thomas") .noneMatch(str -> str.endsWith("a")); System.out.println(noneMatch); output? boolean anyMatch = Stream.of("Veronica", "Anna", "Patricia", "Alan", "Thomas") .anyMatch(str -> str.endsWith("a")); System.out.println(anyMatch); output? boolean allMatch = Stream.of("Veronica", "Anna", "Patricia", "Alan", "Thomas") .allMatch(str -> str.endsWith("a")); System.out.println(allMatch); output: false boolean noneMatch = Stream.of("Veronica", "Anna", "Patricia", "Alan", "Thomas") .noneMatch(str -> str.endsWith("a")); System.out.println(noneMatch); output: false boolean anyMatch = Stream.of("Veronica", "Anna", "Patricia", "Alan", "Thomas") .anyMatch(str -> str.endsWith("a")); System.out.println(anyMatch); output: true
  • 43.
    Streams - coremethods (3.5/3) www.xsolve.plAgile Software House ● long count() ● Stream sorted() ● Stream distinct() ● Stream limit(long maxSize) ● Stream skip(long n)
  • 44.
    Streams - Terminalvs Non Terminal operations www.xsolve.plAgile Software House Terminal (consume a Stream) ● forEach, forEachOrdered ● toArray, reduce, collect ● min, max, count ● anyMatch, allMatch, noneMatch ● findFirst, findAny Non-terminal (return another Stream) ● map ● filter ● distinct, sorted ● peek ● limit, skip ● parallel, sequential, unordered Terminal (consume a Stream) ● forEach, forEachOrdered ● toArray, reduce, collect ● min, max, count ● anyMatch, allMatch, noneMatch ● findFirst, findAny Non-terminal (return another Stream) ● map ● filter ● distinct, sorted ● peek ● limit, skip ● parallel, sequential, unordered Short-circuit operations
  • 45.
    Streams - lazyevaluation www.xsolve.plAgile Software House books.addAll(Arrays. asList( new Book("The Lord of the Rings" , tolkien, 1216), new Book("Silmarillion" , tolkien, 365), new Book("Harry Potter and something" , rowling, 223), new Book("Harry Potter and blahblah" , rowling, 554) // + 500k entries )); books.stream() .filter(it -> { System. out.println("name: " + nameFilterCounter ++); return "J.K. Rowling" .equals(it.getAuthor()) ; }) .filter(it -> { System. out.println("tpages: " + pageFilterCounter ++); return it.getPages() > 500; }) .findFirst() ; name: 0 name: 1 name: 2 pages: 0 name: 3 pages: 1 books.addAll(Arrays. asList( new Book("The Lord of the Rings" , tolkien, 1216), new Book("Silmarillion" , tolkien, 365), new Book("Harry Potter and something" , rowling, 223), new Book("Harry Potter and blahblah" , rowling, 554) // + 500k entries )); books.stream() .filter(it -> { System. out.println("name: " + nameFilterCounter ++); return "J.K. Rowling" .equals(it.getAuthor()) ; }) .filter(it -> { System. out.println("tpages: " + pageFilterCounter ++); return it.getPages() > 500; }) .findFirst(); ← short-circuit operation!
  • 46.
    Streams - whatyou can’t do www.xsolve.plAgile Software House ● Reuse Stream stream = Stream.of("J", "a", "v", "a"); stream.filter(...).map(...) stream.map(...).forEach(...)
  • 47.
    Streams - whatyou can’t do www.xsolve.plAgile Software House ● Reuse ● Change surrounding local variables int total = 0; Stream.of("Mercury", "Venus", "Mars") .forEach(str -> { total += str.length(); }); int[] total = {0}; Stream.of("Mercury", "Venus", "Mars") .forEach(str -> { total[0] += str.length(); }); ...but:
  • 48.
  • 49.
  • 50.
    www.xsolve.plAgile Software House FileIO Java6 approach public void readFile() { File file = new File("/home/grzegorz/file.txt"); FileInputStream fis = null; try { fis = new FileInputStream(file); int content; while ((content = fis.read()) != -1) { System.out.print((char) content); } } catch (IOException e) { e.printStackTrace(); } finally { if (null != fis) { try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } } }
  • 51.
    www.xsolve.plAgile Software House FileIO Java6 approach Java7 approach - java.lang.AutoCloseable - java.io.Closeable public void readFile() { File file = new File("/home/grzegorz/file.txt"); try (FileInputStream fis = new FileInputStream(file)) { int content; while ((content = fis.read()) != -1) { System.out.print((char) content); } } catch (IOException e) { e.printStackTrace(); } } public void readFile() { File file = new File("/home/grzegorz/file.txt"); FileInputStream fis = null; try { fis = new FileInputStream(file); int content; while ((content = fis.read()) != -1) { System.out.print((char) content); } } catch (IOException e) { e.printStackTrace(); } finally { if (null != fis) { try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } } }
  • 52.
    www.xsolve.plAgile Software House FileIO public void readFile() { Path filePath = Paths.get("/home/grzegorz/file.txt"); try (Stream<String> stream = Files.lines(filePath)) { stream.forEach(System.out::print); } catch (IOException e) { e.printStackTrace(); } } Java8 approach public void readFile() { File file = new File("/home/grzegorz/file.txt"); try (FileInputStream fis = new FileInputStream(file)) { int content; while ((content = fis.read()) != -1) { System.out.print((char) content); } } catch (IOException e) { e.printStackTrace(); } } Java7 approach
  • 53.
    www.xsolve.plAgile Software House FileIO public void readFile() { File file = new File("/home/grzegorz/file.txt"); FileInputStream fis = null; try { fis = new FileInputStream(file); int content; while ((content = fis.read()) != -1) { System.out.print((char) content); } } catch (IOException e) { e.printStackTrace(); } finally { if (null != fis) { try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } } } Java6 approach public void readFile() { Path filePath = Paths.get("/home/grzegorz/file.txt"); try (Stream<String> stream = Files.lines(filePath)) { stream.forEach(System.out::print); } catch (IOException e) { e.printStackTrace(); } } Java8 approach vs.
  • 54.
    www.xsolve.plAgile Software House FileIO - Path vs. File “There is no one-to-one correspondence between the two APIs …” http://docs.oracle.com/javase/tutorial/essential/io/legacy.html
  • 55.
    www.xsolve.plAgile Software House FileIO - How to get Path? Path p1 = Paths.get("some-file.txt"); Path p2 = Paths.get("C:MyFolderanother-file.txt");
  • 56.
    www.xsolve.plAgile Software House FileIO - Methods of Path class Methods: toAbsolutePath, startsWith, endsWith, getFileName, getName, getNameCount, subpath, getParent, getRoot, normalize, relativize Sample Method Result toAbsolutePath C:eclipse-workspacejavafile-ioinput-file.txt getFileName input-file.tx getRoot C:
  • 57.
    www.xsolve.plAgile Software House FileIO - File.lines Stream<String> lines = Files.lines("some-path"); ● Can use all the cool and powerful Stream methods. ● Lazy evaluation. ● Throws IOException. ● Stream should be closed. ● Stream implements AutoCloseable
  • 58.
    www.xsolve.plAgile Software House FileIO - Example public List<Car> loadCars(Path filePath) { try (Stream<String> allCars = Files.lines(filePath)) { return allCars .filter(car -> hasFourSeats(car)) .filter(carWithFourSeats -> this::isRed) .map(redCarWithFourSeats -> addDoors(redCarWithFourSeats)) .sorted() .distinct() .collect(Collectors.toList()); } catch (IOException e) { e.printStackTrace(); } }
  • 59.
    www.xsolve.plAgile Software House FileIO - Files.write Files.write(somePath, lines, someCharset, someOption); Files.write(somePath, fileArray, someOption); ● somePath to file, ● lines e.g. List<String> lines, bytes[] data ● someCharset e.g. StandardCharsets.UTF_8 ● someOption e.q. StandardOpenOption.APPEND
  • 60.
    www.xsolve.plAgile Software House FileIO - Files.write Java7 approach public void savePoems(List<String> poems) { File file = new File("/home/grzegorz/poems.txt"); try (FileWriter fw = new FileWriter(file)) { for (String poem: poems) { fw.write(poem); } } catch (IOException e) { e.printStackTrace(); } }
  • 61.
    www.xsolve.plAgile Software House FileIO - Files.write Java7 approach public void savePoems(List<String> poems) { File file = new File("/home/grzegorz/poems.txt"); try (FileWriter fw = new FileWriter(file)) { for (String poem: poems) { fw.write(poem); } } catch (IOException e) { e.printStackTrace(); } } Java8 approach public void savePoems(List<String> poems) { Path path = Paths.get("/home/grzegorz/poems.txt"); try { Files.write(path, poems, StandardOpenOption.WRITE); } catch (IOException e) { e.printStackTrace(); } }
  • 62.
  • 63.
    www.xsolve.plAgile Software House ●Coreservlets.com, Marty Hall - “Java 8 Tutorial” http://www.coreservlets.com/java-8-tutorial/ ● Confitura 2015, Grzegorz Piwowarek - “Lambdas && Monads” (PL) https://youtu.be/VglEyjgxAKY More on Java8
  • 64.
    www.xsolve.plAgile Software House Youcan find our job offers at xsolve.pl/career Thank you for your time! Questions? Marriage offers? Free lunch? team4java@xsolve.pl