SlideShare a Scribd company logo
JAVA 8 REVEALED
LAMBDAS, STREAMS.
Who We are
Bazlur Rahman Rokon
Associate Software Engineer, Therap Services, LLC
Sazzadur Rahman
Software Engineer, Kona Software Lab Ltd.
What’s new in Java 8
1. Lambda Expressions
2. Method references
3. Default methods
4. Bulk Data Operation → Stream API
5. Date-Time
6. And a lot more ……
Assumption
1. We really love abstraction
2. We Actually Build cool Stuffs
3. We are programmers and lazy
4. We work only day time and go home early (Well, we have life, right
:/ )
5. Users want too many features
6. As we are lazy, we don’t want to do too much work.
7. So we love “Less code, do more” philosophy
The Best Code is No Code At All
1. Code is bad
2. It rots
3. It requires periodic maintenance
4. But the fact is, we love coding, more specifically less
coding
Lambda in Action
public interface Runnable {
public abstract void run();
}
Lambda in Action cont.
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("JUGBD Meetup 3.0");
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("JUGBD Meetup 3.0");
}
}).start();
Code I’m
interested in
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("JUGBD Meetup 3.0");
}
}).start();
Ceremony
Less code ☺
new Thread(() -> System.out.println("JUGBD Meetup 3.0"))
.start();
What is Lambda Expression
() -> { }
What is Lambda Expression
(Thing t ) -> { }
What is Lambda Expression
(Thing t ) -> { }
(Thing t , More m) -> { }
Let’s have a situation
public class Person {
private String name;
private LocalDate birthday;
private Sex gender;
private String emailAddress;
private String cellNo;
// getters and setters//
What we want to do
1. Search based on characteristics and send
email/call
1. find older than 60 -> then need Elderly allowance
2. find voters
1. kids -> less than 18 -> they are not allowed to
vote, so ignore them
2. sort by name, by age
Take # 1
public void findPersonOlder(List<Person> persons) {
for (Person p : persons) {
if (p.getAge() > 60) {
sendEmail(p.getEmailAddress());
}
}
}
Take #2
public void findEligibleVoters(List<Person> persons) {
for (Person p : persons) {
if (p.getAge() > 18) {
sendEmail(p.getEmailAddress());
}
}
}
Take # 3
public void findTargetAudienceForAd(List<Person> persons) {
for (Person p : persons) {
if (p.getAge() > 25 &&
p.getGender() == Sex.MALE) {
sendEmail(p.getEmailAddress());
}
}
}
A lots of combinations
We can keep going on and on and
on….
Lets parameterize the behavior
public interface PersonPredicate {
public boolean testPerson(Person p);
}
public void processPerson(List<Person> persons,
PersonPredicate predicate) {
for (Person p : persons) {
if (predicate.testPerson(p)) {
sendEmail(p.getEmailAddress());
}
}
}
Revisit Take #2
processPerson(persons, new PersonPredicate() {
@Override
public boolean testPerson(Person p) {
return p.getAge() > 18;
}
});
Revisit Take #3
processPerson(persons, new PersonPredicate() {
@Override
public boolean testPerson(Person p) {
return p.getAge() > 25 &&
p.getGender() == Sex.MALE;
}
});
We want to call as well
public interface PersonConsumer {
public void accept (String phoneNumber);
}
public void processPerson(List<Person> persons,
PersonPredicate predicate,
PersonConsumer consumer) {
for (Person p : persons) {
if (predicate.testPerson(p)) {
String cellNo = p.getCellNo();
consumer.accept(cellNo);
}
}
}
Lets put it a bit harder
public void processPerson(List<Person> persons,
PersonPredicate predicate,
PersonConsumer consumer) {
for (Person p : persons) {
if (predicate.testPerson(p)) {
String cellNo = p.getCellNo();
consumer.accept(cellNo);
}
}
}
public interface PersonMapper {
public String map(Person p);
}
public void processPerson(List<Person> persons,
PersonPredicate predicate,
PersonMapper mapper,
PersonConsumer consumer) {
for (Person p : persons) {
if (predicate.testPerson(p)) {
String value = mapper.map(p);
consumer.accept(value);
}
Good going ..
processPerson(persons,new PersonPredicate() {
@Override
public boolean testPerson(Person p) {
return p.getAge() > 18;
}
}, new PersonMapper() {
@Override
public String map(Person p) {
return p.getCellNo();
}
}, new PersonConsumer() {
@Override
public void accept(String value) {
call(value);
}
});
Achieved behavior parameterization
Powerfull, but verbose and clunky
Revisit the Again
processPerson(persons, new PersonPredicate() {
@Override
public boolean testPerson(Person p) {
return p.getAge() > 18;
}
});
Boilerplate code
processPerson(persons, new PersonPredicate() {
@Override
public boolean testPerson(Person p) {
return p.getAge() > 18;
}
});
We are in the age of Java 8 , lets throw
away boilerplate code
processPerson(persons,
p
return p.getAge() > 18;
);
Our first lambda
processPerson(persons, p -> p.getAge() > 18);
Lets call voters
processPerson(persons,
p -> p.getAge() > 18,
p1 -> p1.getCellNo(),
c -> call(c)
);
Functional Interface
@FunctionalInterface
public interface PersonMapper {
public String map(Person p);
}
public interface PersonPredicate {
public boolean testPerson(Person p);
}
@FunctionalInterface
public interface PersonMapper {
public String map(Person p);
}
Stream API
So we were basically doing
Source -> filter -> map -> apply
Lambda Lambda Lambda
Stream API
persons
.stream()
.filter(p-> p.getAge()>19)
.map(p-> p.getCellNo())
.forEach( c-> call(c));
What is Stream?
•A sequence of elements from a source supporting sequential and parallel
aggregate operations, While completely abstracting the details of low level
multi threading logic.
•Sources can be Any type of Collection, Array, or any I/O operation who
provides data to the Stream.
•Aggregate operations are operations to collect or extract necessary
information from a stream or collection.
What is Stream?
persons
.stream()
.filter(p-> p.getAge()>19)
.map(p-> p.getCellNo())
.forEach( c-> call(c));
Intermdediate Operation
Terminal Operation
Get Stream
Source
Pipelining
Intermdediate Operation
Intermediate Operations
map
flatMap
filter
sorted
distinct
skip
limit
Map and flatMap
List<Integer> numbers = Arrays.asList(1, 2, 3, 4);
List<List<Integer>> mapped =
numbers.stream()
.map(number -> Arrays.asList(number -1, number, number +1))
.collect(Collectors.toList());
System.out.println(mapped); //:> [[0, 1, 2], [1, 2, 3], [2, 3, 4], [3, 4, 5]]
List<Integer> flattened =
numbers.stream()
.flatMap(number -> Arrays.asList(number -1, number, number +1).stream())
.collect(Collectors.toList());
System.out.println(flattened); //:> [0, 1, 2, 1, 2, 3, 2, 3, 4, 3, 4, 5]
Terminal Operation
collect
allMatch
noneMatch
findFirst
findAny
reduce
forEach
allMatch and noneMatch
//Check if All of the students have distinction
Boolean hasAllStudentsWithDistinction = students.stream()
.allMatch(student -> student.getScore() > 80);
//Return true if None of the students are over distinction
Boolean hasAllStudentsBelowDistinction = students.stream()
.noneMatch(student -> student.getScore() > 80);
Reduce
Reduces the whole stream into a single value
//Summing all elements of a stream
Integer sum = numbers.stream()
.reduce(0, (x, y) -> x + y); //reduce(identity, accumulator)
Integer min = numbers.stream()
.reduce(0, Integer::min);
What about having no terminal
Operation?
persons
.stream()
.filter(p-> p.getAge()>19)
.map(p-> p.getCellNo())
Intermdediate Operation
Get Stream
Source
Pipelining Intermdediate Operation
Lazy and Eager
Did you scrolled your facebook timeline, down to the beginning?
Laziness of Stream operations
• Current era is of Big Data, Parallel Processing and being real time.
• When dealing with Big Data Laziness is a big deal.
• Stream API is inherently Lazy and based on “Process on Demand”
behavior.
Laziness of Stream operations
Stream<String> streamOfNames = students.stream()
.map(student -> {
System.out.println("In Map - " +
student.getName());
return student.getName();
});
//Just to add some delay
for (int i = 1; i <= 5; i++) {
Thread.sleep(1000);
System.out.println(i + " sec");
}
//Called a terminal operation on the stream
streamOfNames.collect(Collectors.toList());
Output:
1 sec
2 sec
3 sec
4 sec
5 sec
In Map - Tom
In Map - Chris
In Map - Dave
Short Circuit
//List of first 3 students who have age > 20
students.stream()
.filter(s -> s.getAge() > 20)
.map(Student::getName)
.limit(3)
.collect(Collectors.toList());
Thanks…

More Related Content

PPTX
Grails queries
PDF
SeaJUG March 2004 - Groovy
PDF
Java 8 Streams & Collectors : the Leuven edition
PDF
Introduction to Erlang
PDF
Simplifying java with lambdas (short)
PDF
Going reactive in java
PPTX
Groovy
PDF
Functional Programming with Groovy
Grails queries
SeaJUG March 2004 - Groovy
Java 8 Streams & Collectors : the Leuven edition
Introduction to Erlang
Simplifying java with lambdas (short)
Going reactive in java
Groovy
Functional Programming with Groovy

What's hot (20)

PDF
Evolving with Java - How to remain Relevant and Effective
PDF
The Magic Of Elixir
PDF
Refactoring for Software Design Smells - Tech Talk
PDF
Searching and sorting by B kirron Reddi
PDF
Lambdas and Streams Master Class Part 2
PDF
Collectors in the Wild
PDF
Python Workshop Part 2. LUG Maniapl
PDF
Python dictionary : past, present, future
PDF
Rxjava2 custom operator
PDF
Creating Lazy stream in CSharp
PDF
The Ring programming language version 1.5.2 book - Part 11 of 181
PDF
Refactoring to Java 8 (Devoxx BE)
PDF
The TclQuadcode Compiler
DOCX
Diifeerences In C#
PDF
Java 8, Streams & Collectors, patterns, performances and parallelization
PDF
Pragmatic functional refactoring with java 8
PPTX
Kotlin – the future of android
PDF
The Ring programming language version 1.8 book - Part 37 of 202
PPTX
C# 7.0 Hacks and Features
PDF
JavaScript Fundamentals with Angular and Lodash
Evolving with Java - How to remain Relevant and Effective
The Magic Of Elixir
Refactoring for Software Design Smells - Tech Talk
Searching and sorting by B kirron Reddi
Lambdas and Streams Master Class Part 2
Collectors in the Wild
Python Workshop Part 2. LUG Maniapl
Python dictionary : past, present, future
Rxjava2 custom operator
Creating Lazy stream in CSharp
The Ring programming language version 1.5.2 book - Part 11 of 181
Refactoring to Java 8 (Devoxx BE)
The TclQuadcode Compiler
Diifeerences In C#
Java 8, Streams & Collectors, patterns, performances and parallelization
Pragmatic functional refactoring with java 8
Kotlin – the future of android
The Ring programming language version 1.8 book - Part 37 of 202
C# 7.0 Hacks and Features
JavaScript Fundamentals with Angular and Lodash
Ad

Viewers also liked (14)

PPTX
Top 8 disability coordinator resume samples
DOCX
Philosophy on Scientific Teaching
PDF
a&n_LookBook
PPTX
Top 8 grants coordinator resume samples
PDF
RS_LookBook
DOCX
Angus Lindt
PPTX
Top 8 athletic coordinator resume samples
PPTX
Top 8 fundraiser coordinator resume samples
PPTX
JVM Ecosystem Languages And The Future of JVM
PPTX
Ti saraswatiap
PPTX
Top 8 life enrichment coordinator resume samples
PPTX
Top 8 editorial coordinator resume samples
PPTX
Smart Card to the Cloud for Convenient, Secured NFC Payment
PPTX
Top 8 irb coordinator resume samples
Top 8 disability coordinator resume samples
Philosophy on Scientific Teaching
a&n_LookBook
Top 8 grants coordinator resume samples
RS_LookBook
Angus Lindt
Top 8 athletic coordinator resume samples
Top 8 fundraiser coordinator resume samples
JVM Ecosystem Languages And The Future of JVM
Ti saraswatiap
Top 8 life enrichment coordinator resume samples
Top 8 editorial coordinator resume samples
Smart Card to the Cloud for Convenient, Secured NFC Payment
Top 8 irb coordinator resume samples
Ad

Similar to Java 8 revealed (20)

PDF
Java 8 - functional features
PDF
Harnessing the Power of Java 8 Streams
PDF
Java 8 - A step closer to Parallelism
PDF
Lambdas & Streams
PDF
Java 8 new features or the ones you might actually use
PDF
Functional aspects of java 8
ODP
Lambda Chops - Recipes for Simpler, More Expressive Code
PDF
Apouc 2014-java-8-create-the-future
PPTX
Java 8
PPTX
Functional Programming With Lambdas and Streams in JDK8
PPTX
Java8lambda
PPTX
Lambdas and-streams-s ritter-v3
PPTX
Java 8 new features
PDF
Java SE 8 best practices
PDF
javase8bestpractices-151015135520-lva1-app6892
PPTX
Project Lambda: Evolution of Java
PDF
Java 8 by example!
PPTX
Lambdas : Beyond The Basics
PPTX
PPTX
Functional programming with_jdk8-s_ritter
Java 8 - functional features
Harnessing the Power of Java 8 Streams
Java 8 - A step closer to Parallelism
Lambdas & Streams
Java 8 new features or the ones you might actually use
Functional aspects of java 8
Lambda Chops - Recipes for Simpler, More Expressive Code
Apouc 2014-java-8-create-the-future
Java 8
Functional Programming With Lambdas and Streams in JDK8
Java8lambda
Lambdas and-streams-s ritter-v3
Java 8 new features
Java SE 8 best practices
javase8bestpractices-151015135520-lva1-app6892
Project Lambda: Evolution of Java
Java 8 by example!
Lambdas : Beyond The Basics
Functional programming with_jdk8-s_ritter

Recently uploaded (20)

PDF
medical staffing services at VALiNTRY
PDF
Digital Strategies for Manufacturing Companies
PPTX
history of c programming in notes for students .pptx
PDF
Navsoft: AI-Powered Business Solutions & Custom Software Development
PDF
Adobe Premiere Pro 2025 (v24.5.0.057) Crack free
PDF
Understanding Forklifts - TECH EHS Solution
PPTX
Agentic AI Use Case- Contract Lifecycle Management (CLM).pptx
PPTX
Agentic AI : A Practical Guide. Undersating, Implementing and Scaling Autono...
PPTX
Introduction to Artificial Intelligence
PPTX
Odoo POS Development Services by CandidRoot Solutions
PDF
Design an Analysis of Algorithms I-SECS-1021-03
PDF
Which alternative to Crystal Reports is best for small or large businesses.pdf
PPTX
VVF-Customer-Presentation2025-Ver1.9.pptx
PDF
AI in Product Development-omnex systems
PDF
Wondershare Filmora 15 Crack With Activation Key [2025
PDF
PTS Company Brochure 2025 (1).pdf.......
PPTX
Operating system designcfffgfgggggggvggggggggg
PPTX
CHAPTER 2 - PM Management and IT Context
PDF
top salesforce developer skills in 2025.pdf
PDF
2025 Textile ERP Trends: SAP, Odoo & Oracle
medical staffing services at VALiNTRY
Digital Strategies for Manufacturing Companies
history of c programming in notes for students .pptx
Navsoft: AI-Powered Business Solutions & Custom Software Development
Adobe Premiere Pro 2025 (v24.5.0.057) Crack free
Understanding Forklifts - TECH EHS Solution
Agentic AI Use Case- Contract Lifecycle Management (CLM).pptx
Agentic AI : A Practical Guide. Undersating, Implementing and Scaling Autono...
Introduction to Artificial Intelligence
Odoo POS Development Services by CandidRoot Solutions
Design an Analysis of Algorithms I-SECS-1021-03
Which alternative to Crystal Reports is best for small or large businesses.pdf
VVF-Customer-Presentation2025-Ver1.9.pptx
AI in Product Development-omnex systems
Wondershare Filmora 15 Crack With Activation Key [2025
PTS Company Brochure 2025 (1).pdf.......
Operating system designcfffgfgggggggvggggggggg
CHAPTER 2 - PM Management and IT Context
top salesforce developer skills in 2025.pdf
2025 Textile ERP Trends: SAP, Odoo & Oracle

Java 8 revealed

  • 2. Who We are Bazlur Rahman Rokon Associate Software Engineer, Therap Services, LLC Sazzadur Rahman Software Engineer, Kona Software Lab Ltd.
  • 3. What’s new in Java 8 1. Lambda Expressions 2. Method references 3. Default methods 4. Bulk Data Operation → Stream API 5. Date-Time 6. And a lot more ……
  • 4. Assumption 1. We really love abstraction 2. We Actually Build cool Stuffs 3. We are programmers and lazy 4. We work only day time and go home early (Well, we have life, right :/ ) 5. Users want too many features 6. As we are lazy, we don’t want to do too much work. 7. So we love “Less code, do more” philosophy
  • 5. The Best Code is No Code At All 1. Code is bad 2. It rots 3. It requires periodic maintenance 4. But the fact is, we love coding, more specifically less coding
  • 6. Lambda in Action public interface Runnable { public abstract void run(); }
  • 7. Lambda in Action cont. new Thread(new Runnable() { @Override public void run() { System.out.println("JUGBD Meetup 3.0"); } }).start();
  • 8. new Thread(new Runnable() { @Override public void run() { System.out.println("JUGBD Meetup 3.0"); } }).start(); Code I’m interested in
  • 9. new Thread(new Runnable() { @Override public void run() { System.out.println("JUGBD Meetup 3.0"); } }).start(); Ceremony
  • 10. Less code ☺ new Thread(() -> System.out.println("JUGBD Meetup 3.0")) .start();
  • 11. What is Lambda Expression () -> { }
  • 12. What is Lambda Expression (Thing t ) -> { }
  • 13. What is Lambda Expression (Thing t ) -> { } (Thing t , More m) -> { }
  • 14. Let’s have a situation public class Person { private String name; private LocalDate birthday; private Sex gender; private String emailAddress; private String cellNo; // getters and setters//
  • 15. What we want to do 1. Search based on characteristics and send email/call 1. find older than 60 -> then need Elderly allowance 2. find voters 1. kids -> less than 18 -> they are not allowed to vote, so ignore them 2. sort by name, by age
  • 16. Take # 1 public void findPersonOlder(List<Person> persons) { for (Person p : persons) { if (p.getAge() > 60) { sendEmail(p.getEmailAddress()); } } }
  • 17. Take #2 public void findEligibleVoters(List<Person> persons) { for (Person p : persons) { if (p.getAge() > 18) { sendEmail(p.getEmailAddress()); } } }
  • 18. Take # 3 public void findTargetAudienceForAd(List<Person> persons) { for (Person p : persons) { if (p.getAge() > 25 && p.getGender() == Sex.MALE) { sendEmail(p.getEmailAddress()); } } }
  • 19. A lots of combinations We can keep going on and on and on….
  • 20. Lets parameterize the behavior public interface PersonPredicate { public boolean testPerson(Person p); }
  • 21. public void processPerson(List<Person> persons, PersonPredicate predicate) { for (Person p : persons) { if (predicate.testPerson(p)) { sendEmail(p.getEmailAddress()); } } }
  • 22. Revisit Take #2 processPerson(persons, new PersonPredicate() { @Override public boolean testPerson(Person p) { return p.getAge() > 18; } });
  • 23. Revisit Take #3 processPerson(persons, new PersonPredicate() { @Override public boolean testPerson(Person p) { return p.getAge() > 25 && p.getGender() == Sex.MALE; } });
  • 24. We want to call as well public interface PersonConsumer { public void accept (String phoneNumber); }
  • 25. public void processPerson(List<Person> persons, PersonPredicate predicate, PersonConsumer consumer) { for (Person p : persons) { if (predicate.testPerson(p)) { String cellNo = p.getCellNo(); consumer.accept(cellNo); } } }
  • 26. Lets put it a bit harder public void processPerson(List<Person> persons, PersonPredicate predicate, PersonConsumer consumer) { for (Person p : persons) { if (predicate.testPerson(p)) { String cellNo = p.getCellNo(); consumer.accept(cellNo); } } }
  • 27. public interface PersonMapper { public String map(Person p); }
  • 28. public void processPerson(List<Person> persons, PersonPredicate predicate, PersonMapper mapper, PersonConsumer consumer) { for (Person p : persons) { if (predicate.testPerson(p)) { String value = mapper.map(p); consumer.accept(value); }
  • 29. Good going .. processPerson(persons,new PersonPredicate() { @Override public boolean testPerson(Person p) { return p.getAge() > 18; } }, new PersonMapper() { @Override public String map(Person p) { return p.getCellNo(); } }, new PersonConsumer() { @Override public void accept(String value) { call(value); } });
  • 31. Revisit the Again processPerson(persons, new PersonPredicate() { @Override public boolean testPerson(Person p) { return p.getAge() > 18; } });
  • 32. Boilerplate code processPerson(persons, new PersonPredicate() { @Override public boolean testPerson(Person p) { return p.getAge() > 18; } });
  • 33. We are in the age of Java 8 , lets throw away boilerplate code processPerson(persons, p return p.getAge() > 18; );
  • 34. Our first lambda processPerson(persons, p -> p.getAge() > 18);
  • 35. Lets call voters processPerson(persons, p -> p.getAge() > 18, p1 -> p1.getCellNo(), c -> call(c) );
  • 36. Functional Interface @FunctionalInterface public interface PersonMapper { public String map(Person p); } public interface PersonPredicate { public boolean testPerson(Person p); } @FunctionalInterface public interface PersonMapper { public String map(Person p); }
  • 38. So we were basically doing Source -> filter -> map -> apply Lambda Lambda Lambda
  • 40. What is Stream? •A sequence of elements from a source supporting sequential and parallel aggregate operations, While completely abstracting the details of low level multi threading logic. •Sources can be Any type of Collection, Array, or any I/O operation who provides data to the Stream. •Aggregate operations are operations to collect or extract necessary information from a stream or collection.
  • 41. What is Stream? persons .stream() .filter(p-> p.getAge()>19) .map(p-> p.getCellNo()) .forEach( c-> call(c)); Intermdediate Operation Terminal Operation Get Stream Source Pipelining Intermdediate Operation
  • 43. Map and flatMap List<Integer> numbers = Arrays.asList(1, 2, 3, 4); List<List<Integer>> mapped = numbers.stream() .map(number -> Arrays.asList(number -1, number, number +1)) .collect(Collectors.toList()); System.out.println(mapped); //:> [[0, 1, 2], [1, 2, 3], [2, 3, 4], [3, 4, 5]] List<Integer> flattened = numbers.stream() .flatMap(number -> Arrays.asList(number -1, number, number +1).stream()) .collect(Collectors.toList()); System.out.println(flattened); //:> [0, 1, 2, 1, 2, 3, 2, 3, 4, 3, 4, 5]
  • 45. allMatch and noneMatch //Check if All of the students have distinction Boolean hasAllStudentsWithDistinction = students.stream() .allMatch(student -> student.getScore() > 80); //Return true if None of the students are over distinction Boolean hasAllStudentsBelowDistinction = students.stream() .noneMatch(student -> student.getScore() > 80);
  • 46. Reduce Reduces the whole stream into a single value //Summing all elements of a stream Integer sum = numbers.stream() .reduce(0, (x, y) -> x + y); //reduce(identity, accumulator) Integer min = numbers.stream() .reduce(0, Integer::min);
  • 47. What about having no terminal Operation? persons .stream() .filter(p-> p.getAge()>19) .map(p-> p.getCellNo()) Intermdediate Operation Get Stream Source Pipelining Intermdediate Operation
  • 48. Lazy and Eager Did you scrolled your facebook timeline, down to the beginning?
  • 49. Laziness of Stream operations • Current era is of Big Data, Parallel Processing and being real time. • When dealing with Big Data Laziness is a big deal. • Stream API is inherently Lazy and based on “Process on Demand” behavior.
  • 50. Laziness of Stream operations Stream<String> streamOfNames = students.stream() .map(student -> { System.out.println("In Map - " + student.getName()); return student.getName(); }); //Just to add some delay for (int i = 1; i <= 5; i++) { Thread.sleep(1000); System.out.println(i + " sec"); } //Called a terminal operation on the stream streamOfNames.collect(Collectors.toList()); Output: 1 sec 2 sec 3 sec 4 sec 5 sec In Map - Tom In Map - Chris In Map - Dave
  • 51. Short Circuit //List of first 3 students who have age > 20 students.stream() .filter(s -> s.getAge() > 20) .map(Student::getName) .limit(3) .collect(Collectors.toList());