12. What are lambda functions?
❖ (Java 8) One way to think about lambdas is
“anonymous function” or “unnamed function” - they
are functions without a name and are not associated
with any clas
s
❖ They don’t change external state
13. What is functional programming?
❖ Functional languages view programs as an entity—
called a function—that accepts inputs and produces
output
❖ Functions are connected together by their outputs to
other functions’ input
s
❖ Underlying approach: “Evaluate an expression. Then
use the results for something else.”
20. $ cat limerick.txt
There was a young lady of Niger
Who smiled as she rode on a tiger.
They returned from the ride
With the lady inside
And a smile on the face of the tiger.
21. $ cat limerick.txt | tr -cs "[:alpha:]" "n" | awk '{print length(), $0}' | sort | uniq
1 a
2 as
2 of
2 on
3 And
3 Who
3 she
3 the
3 was
4 They
4 With
4 face
4 from
4 lady
4 ride
4 rode
5 Niger
5 There
5 smile
5 tiger
5 young
6 inside
6 smiled
8 returned
22. List<String> lines
= Files.readAllLines(Paths.get("./limerick.txt"), Charset.defaultCharset());
Map<Integer, List<String>> wordGroups
= lines.stream()
.map(line -> line.replaceAll("W", "n").split("n"))
.flatMap(Arrays::stream)
.sorted()
.distinct()
.collect(Collectors.groupingBy(String::length));
wordGroups.forEach( (count, words) -> {
words.forEach(word -> System.out.printf("%d %s %n", count, word));
});
1 a
2 as
2 of
2 on
3 And
3 Who
3 she
3 the
3 was
4 They
4 With
4 face
4 from
4 lady
4 ride
4 rode
5 Niger
5 There
5 smile
5 tiger
5 young
6 inside
6 smiled
8 returned
24. public static void main(String []file) throws Exception {
// process each file passed as argument
// try opening the file with FileReader
try (FileReader inputFile = new FileReader(file[0])) {
int ch = 0;
while( (ch = inputFile.read()) != -1) {
// ch is of type int - convert it back to char
System.out.print( (char)ch );
}
}
// try-with-resources will automatically release FileReader object
}
public static void main(String []file) throws Exception {
Files.lines(Paths.get(file[0])).forEach(System.out::println);
}
Existing APIs are enriched with
lambdas and streams support
25. Java 8 is the new Groovy ;-)
import java.io.*;
class Type {
public sta
ti
c void main(String []
fi
les) {
// process each
fi
le passed as argument
for(String
fi
le :
fi
les) {
// try opening the
fi
le with FileReader
try (FileReader inputFile = new FileReader(
fi
le)) {
int ch = 0;
while( (ch = inputFile.read()) != -1) {
// ch is of type int - convert it back to char
System.out.print( (char)ch );
}
} catch (FileNotFoundExcep
ti
on fnfe) {
System.err.prin
tf
("Cannot open the given
fi
le %s ",
fi
le);
}
catch(IOExcep
ti
on ioe) {
System.err.prin
tf
("Error when processing
fi
le %s; skipping it",
fi
le);
}
// try-with-resources will automa
ti
cally release FileReader object
}
}
}
args.each { println new File(it).getText() }
30. Java 8 lambdas - “Hello world!”
interface LambdaFunction
{
void call();
}
class FirstLambda {
public static void main(String []args)
{
LambdaFunction lambdaFunction = () -> System.out.println("Hello world");
lambdaFunction.call();
}
}
Functional interface - provides
signature for lambda functions
Lambda function/expression
Call to the lambda
Prints “Hello world” on the console when executed
31. Parts of a lambda expression
() -> System.out.println("Hello world");
No parameters, i.e., ()
Arrow operator that separates
parameters and the body
The lambda body
Return type “void” inferred from the body
32. Method references
Method references - “syntactic sugar” for lambda
functions
They “route” function parameters
arg -> System.out.println(arg)
System.out::println
34. Method references
Cannot use method references when lambda functions do
more than“routing” function parameters
strings.forEach(string -> System.out.println(string.toUpperCase()));
More processing here than just
“routing” parameters
36. “Effectively final” variables
import java.util.Arrays
;
import java.util.List;
class PigLatin
{
public static void main(String []args)
{
String suf
fi
x = "ay";
List<String> strings = Arrays.asList("one", "two", "three", "four")
;
strings.forEach(string -> System.out.println(string + suf
fi
x));
}
}
Accessing “local variable” suf
fi
x
here; hence it is considered
“effectively
fi
nal”
37. “Effectively final” variables
import java.util.Arrays
;
import java.util.List;
class PigLatin
{
public static void main(String []args)
{
String suf
fi
x = "ay";
List<String> strings = Arrays.asList("one", "two", "three", “four")
;
suf
fi
x = "e";
// assign to suf
fi
x variable
strings.forEach(string -> System.out.println(string + suf
fi
x));
}
}
PigLatinAssign.java:9: error: local variables referenced from a
lambda expression must be final or effectively final
strings.forEach(string -> System.out.println(string + suffix));
^
1 error
38. Agenda
• Introduction & Overview
• Lambdas
• Functional interfaces
• Streams
• Parallel streams
• Date & Time package
• Refactoring to Java 8
52. Built-in interfaces
Predicate<T> Checks a condition and returns a
boolean value as result
In
fi
lter() method in
java.util.stream.Stream which
is used to remove elements in the
stream that don’t match the given
condition (i.e., predicate) asConsumer<T> Operation that takes an argument but
returns nothing
In forEach() method in
collections and in
java.util.stream.Stream; this
method is used for traversing all
the elements in the collection orFunction<T,
R>
Functions that take an argument and
return a result
In map() method in
java.util.stream.Stream to
transform or operate on the passed
value and return a result.
Supplier<T> Operation that returns a value to the
caller (the returned value could be
same or different values)
In generate() method in
java.util.stream.Stream to
create a in
fi
nite stream of
elements.
53. Predicate interface
Stream.of("hello", "world"
)
.
fi
lter(str -> str.startsWith("h")
)
.forEach(System.out::println);
The
fi
lter() method takes a Predicate
as an argument (predicates are
functions that check a condition and
return a boolean value)
55. Predicate interface
A Predicate<T> “af
fi
rms” something as true or
false: it takes an argument of type T, and returns
a
boolean value. You can call test() method on a
Predicate object.
@FunctionalInterfac
e
public interface Predicate<T>
{
boolean test(T t)
;
// other methods elide
d
}
56. Predicate interface: Example
import java.util.function.Predicate;
public class PredicateTest
{
public static void main(String []args)
{
Predicate<String> nullCheck = arg -> arg != null
;
Predicate<String> emptyCheck = arg -> arg.length() > 0
;
Predicate<String> nullAndEmptyCheck = nullCheck.and(emptyCheck)
;
String helloStr = "hello"
;
System.out.println(nullAndEmptyCheck.test(helloStr))
;
String nullStr = null
;
System.out.println(nullAndEmptyCheck.test(nullStr))
;
}
}
Prints:
tru
e
false
57. Predicate interface: Example
import java.util.List
;
import java.util.ArrayList
;
public class RemoveIfMethod
{
public static void main(String []args)
{
List<String> greeting = new ArrayList<>()
;
greeting.add("hello")
;
greeting.add("world")
;
greeting.removeIf(str -> !str.startsWith("h"))
;
greeting.forEach(System.out::println)
;
}
}
Prints:
hello
60. Consumer interface
A Consumer<T> “consumes” something: it takes
an argument (of generic type T) and returns
nothing (void). You can call accept() method on a
Consumer object.
@FunctionalInterfac
e
public interface Consumer<T>
{
void accept(T t)
;
// the default andThen method elide
d
}
65. Function interface
A Function<T, R> “operates” on something and
returns something: it takes one argument (of
generic type T) and returns an object (of generic
type R). You can call apply() method on a Function
object.
@FunctionalInterfac
e
public interface Function<T, R>
{
R apply(T t)
;
// other methods elide
d
}
67. Function interface: Example
import java.util.Arrays
;
import java.util.function.Function
;
public class CombineFunctions
{
public static void main(String []args)
{
Function<String, Integer> parseInt = Integer:: parseInt
;
Function<Integer, Integer> absInt = Math:: abs
;
Function<String, Integer> parseAndAbsInt = parseInt.andThen(absInt)
;
Arrays.stream("4, -9, 16".split(", ")
)
.map(parseAndAbsInt
)
.forEach(System. out ::println)
;
}
}
Prints:
4
9
16
68. Supplier interface
import java.util.stream.Stream
;
import java.util.Random
;
class GenerateBooleans
{
public static void main(String []args)
{
Random random = new Random()
;
Stream.generate(random::nextBoolean
)
.limit(2
)
.forEach(System.out::println)
;
}
}
Prints two boolean
values “true” and “false”
in random order
70. Supplier interface
A Supplier<T> “supplies” takes nothing but
returns something: it has no arguments and
returns an object (of generic type T). You can call
get() method on a Supplier object
@FunctionalInterfac
e
public interface Supplier<T>
{
T get()
;
// no other methods in this interfac
e
}
71. Supplier interface: Example
Supplier<String> currentDateTime = () -> LocalDateTime.now().toString()
;
System.out.println(currentDateTime.get());
Prints current time:
2015-10-16T12:40:55.164
72. Summary of built-in interfaces in
java.util.function interface
❖ There are only four core functional interfaces in this
package: Predicate, Consumer, Function, and Supplier.
❖ The rest of the interfaces are primitive versions, binary
versions, and derived interfaces such as
UnaryOperator interface.
❖ These interfaces differ mainly on the signature of the
abstract methods they declare.
❖ You need to choose the suitable functional interface
based on the context and your need.
73. Agenda
• Introduction & Overview
• Lambdas
• Functional interfaces
• Stream
s
• Parallel streams
• Date & Time package
• Refactoring to Java 8
74. Java 8 streams (and parallel streams)
:
Excellent example of applying functional
programming in practice
80. IntStream.range(1, 6
)
You can use range or iterate
factory methods in the
IntStream interface
IntStream.iterate(1, i -> i + 1).limit(5)
81. 1 2 3 4 5
1 4 9 16 25
map(i -> i * i)
IntStream.range(1, 5).map(i -> i * i).forEach(System.out::println);
Using streams instead of imperative for i = 1 to 5, print i * i
88. Pattern.compile(" ").splitAsStream("java 8 streams").forEach(System.out::println);
This code splits the input string “java 8
streams” based on whitespace and hence
prints the strings “java”, “8”, and
“streams” on the console
101. long numOfPrimes = LongStream.rangeClosed(2, 100_000)
.
fi
lter(PrimeNumbers::isPrime)
.count();
System.out.println(numOfPrimes);
Prints 9592
2.510 seconds
107. import java.util.Arrays
;
class StringConcatenator
{
public static String result = ""
;
public static void concatStr(String str)
{
result = result + " " + str
;
}
}
class StringSplitAndConcatenate
{
public static void main(String []args)
{
String words[] = "the quick brown fox jumps over the lazy dog".split(" ")
;
Arrays.stream(words).forEach(StringConcatenator::concatStr)
;
System.out.println(StringConcatenator.result)
;
}
}
Gives wrong results with
with parallel() call
108. Agenda
• Introduction & Overview
• Lambdas
• Functional interfaces
• Streams
• Parallel streams
• Date & Time package
• Refactoring to Java 8
109. –Craig Larman
"The critical design tool for software development
is a mind well educated in design principles"
111. Discussion Example
// using java.util.Date
Date today = new Date();
System.out.println(today);
$ java DateUse
Wed Dec 02 17:17:08 IST 2015
Why should we get the
time and timezone details
if I only want a date? Can
I get rid of these parts?
No!
112. So What?!
Date today = new Date();
System.out.println(today);
Date todayAgain = new Date();
System.out.println(todayAgain);
System.out.println(today.compareTo(todayAgain) == 0);
Thu Mar 17 13:21:55 IST 2016
Thu Mar 17 13:21:55 IST 2016
false
What is going
on here?
116. Refactored Solution
LocalDate today = LocalDate.now();
System.out.println(today);
LocalDate todayAgain = LocalDate.now();
System.out.println(todayAgain);
System.out.println(today.compareTo(todayAgain) == 0);
2016-03-17
2016-03-17
true
Works
fi
ne
now!
117. Refactored Example …
You can use only date,
time, or even timezone,
and combine them as
needed!
LocalDate today = LocalDate.now();
System.out.println(today);
LocalTime now = LocalTime.now();
System.out.println(now);
ZoneId id = ZoneId.of("Asia/Tokyo");
System.out.println(id);
LocalDateTime todayAndNow = LocalDateTime.now();
System.out.println(todayAndNow);
ZonedDateTime todayAndNowInTokyo = ZonedDateTime.now(ZoneId.of("Asia/Tokyo"));
System.out.println(todayAndNowInTokyo);
2016-03-17
13:28:06.927
Asia/Tokyo
2016-03-17T13:28:06.928
2016-03-17T16:58:06.929+09:00[Asia/Tokyo]
118. “Fluent interfaces”
❖ Code is more readable and easier to use
:
❖ Classes in this package have numerous static methods
(many of them factory methods)
❖ Methods in the classes follow a common naming
convention (for example, they use the pre
fi
xes plus
and minus to add or subtract date or time values)
119. java.time Sub-packages
❖ java.time.temporal —Accesses date/time
fi
elds and
unit
s
❖ java.time.format —Formats the input and output of
date/time object
s
❖ java.time.zone —Handles time zone
s
❖ java.time.chrono —Supports calendar systems such as
Japanese and Thai calendars
120. ISO-8601 Calendar System Format
❖ The Java 8 date and time API uses ISO 8601 as the
default calendar format.
❖ In this internationally accepted format, the date and
time values are sorted from the largest to the smallest
unit of time: year, month/week, day, hour, minute,
second, and millisecond/nanosecond
.
❖ Example: LocalDate is represented in the in a year-
month-day format (YYYY-MM-DD), as in, 2015-10-26.
122. java.time.LocalDate
LocalDate valentinesDay = LocalDate.of(2016, 14, 2);
System.out.println("Valentine's day is on: " + valentinesDay);
Exception in thread "main"
java.time.DateTimeException: Invalid value
for MonthOfYear(valid values 1 - 12): 14
123. java.time.LocalDate
long visaValidityDays = 180L;
LocalDate currDate = LocalDate.now();
System.out.println("My Visa expires on: " + currDate.plusDays(visaValidityDays));
My Visa expires on: 2016-04-23
127. java.time.LocalTime
long hours = 6;
long minutes = 30;
LocalTime currTime = LocalTime.now();
System.out.println("Current time is: " + currTime);
System.out.println("My meeting is at: " +
currTime.plusHours(hours).plusMinutes(minutes));
Current time is: 12:29:13.62
4
My meeting is at: 18:59:13.624
130. java.time.LocalDateTime
LocalDateTime christmas = LocalDateTime.of(2015, 12, 25, 0, 0);
LocalDateTime newYear = LocalDateTime.of(2016, 1, 1, 0, 0);
System.out.println("New Year 2016 comes after Christmas 2015”
+ newYear.isAfter(christmas));
New Year 2016 comes after
Christmas 2015? true
131. java.time.LocalDateTime
LocalDateTime dateTime = LocalDateTime.now();
System.out.println("Today's date and current time: " + dateTime);
System.out.println("The date component is: " + dateTime.toLocalDate());
System.out.println("The time component is: " + dateTime.toLocalTime());
Today's date and current time:
2015-11-04T13:19:10.49
7
The date component is: 2015-11-0
4
The time component is: 13:19:10.497
132. java.time.Instant
import java.time.Instant;
public class UsingInstant {
public static void main(String args[]){
// prints the current timestamp with UTC as time zone
Instant currTimeStamp = Instant.now();
System.out.println("Instant timestamp is: "+ currTimeStamp);
// prints the number of seconds as Unix timestamp from epoch time
System.out.println("Number of seconds elapsed: " + currTimeStamp.getEpochSecond());
// prints the Unix timestamp in milliseconds
System.out.println("Number of milliseconds elapsed: " + currTimeStamp.toEpochMilli());
}
}
Instant timestamp is: 2015-11-02T03:16:04.502
Z
Number of seconds elapsed: 144643416
4
Number of milliseconds elapsed: 1446434164502
133. java.time.Period
LocalDate manufacturingDate = LocalDate.of(2016, Month.JANUARY, 1);
LocalDate expiryDate = LocalDate.of(2018, Month.JULY, 18);
Period expiry = Period.between(manufacturingDate, expiryDate);
System.out.printf("Medicine will expire in: %d years, %d months, and %d days (%s)n",
expiry.getYears(), expiry.getMonths(), expiry.getDays(), expiry);
Medicine will expire in: 2 years, 6 months, and 17
days (P2Y6M17D)
135. The Java 8 date and time API differentiates how humans
and computers use date- and time-related information.
For example, the Instant class represents a Unix
timestamp and internally uses long and int variables.
Instant values are not very readable or usable by
humans because the class does not support methods
related to day, month, hours, and so on (in contrast, the
Period class supports such methods).
139. TemporalUnit
import java.time.temporal.ChronoUnit;
public class ChronoUnitValues {
public static void main(String []args) {
System.out.println("ChronoUnit DateBased TimeBased Duration");
System.out.println("---------------------------------------");
for(ChronoUnit unit : ChronoUnit.values()) {
System.out.printf("%10s t %b tt %b tt %s %n”,
unit, unit.isDateBased(), unit.isTimeBased(), unit.getDuration());
}
}
}
140.
141. ZoneId
System.out.println("My zone id is: " + ZoneId.systemDefault());
My zone id is: Asia/Kolkata
ZoneId AsiaKolkataZoneId = ZoneId.of("Asia/Kolkata");
144. ZonedDateTime
ZoneId singaporeZone = ZoneId.of(“Asia/Singapore");
ZonedDateTime dateTimeInSingapore =
ZonedDateTime.of(LocalDateTime.of(2016, Month.JANUARY, 1, 6, 0), singaporeZone);
ZoneId aucklandZone = ZoneId.of("Paci
fi
c/Auckland");
ZonedDateTime sameDateTimeInAuckland =
dateTimeInSingapore.withZoneSameInstant(aucklandZone);
Duration timeDifference = Duration.between(
dateTimeInSingapore.toLocalTime(),
sameDateTimeInAuckland.toLocalTime());
System.out.printf("Time difference between %s and %s zones is %d hours”,
singaporeZone, aucklandZone, timeDifference.toHours());
Time difference between Asia/Singapore and
Paci
fi
c/Auckland zones is 5 hours
145. Daylight Savings
ZoneId kolkataZone = ZoneId.of("Asia/Kolkata");
Duration kolkataDST = kolkataZone.getRules().getDaylightSavings(Instant.now());
System.out.printf("Kolkata zone DST is: %d hours %n", kolkataDST.toHours());
ZoneId aucklandZone = ZoneId.of("Paci
fi
c/Auckland");
Duration aucklandDST = aucklandZone.getRules().getDaylightSavings(Instant.now());
System.out.printf("Auckland zone DST is: %d hours", aucklandDST.toHours());
Kolkata zone DST is: 0 hour
s
Auckland zone DST is: 1 hours
147. DateTimeFormatter
Wake up time: 06:00:00
LocalTime wakeupTime = LocalTime.of(6, 0, 0);
System.out.println("Wake up time: " + DateTimeFormatter.ISO_TIME.format(wakeupTime));
01 Jan 2016
DateTimeFormatter customFormat = DateTimeFormatter.ofPattern("dd MMM yyyy");
System.out.println(customFormat.format(LocalDate.of(2016, Month.JANUARY, 01)));
148. Uppercase and lowercase letters can have similar or
different meanings when used in format strings fo
r
dates and times. Read the Javadoc for these patterns
carefully before trying to use these letters. For example
,
in dd-MM-yy, MM refers to month; however, in dd-mm-
yy, mm refers to minutes !
149. Formatting Dates
• G (era: BC, AD)
• y (year of era: 2015, 15)
• Y (week-based year: 2015, 15)
• M (month: 11, Nov, November)
• w (week in year: 13)
• W (week in month: 2)
• E (day name in week: Sun, Sunday)
• D (day of year: 256)
• d (day of month: 13)
150. Custom Date Patterns
public class CustomDatePatterns {
public static void main(String []args) {
// patterns from simple to complex ones
String [] dateTimeFormats = {
"dd-MM-yyyy", /* d is day (in month), M is month, y is year */
"d '('E')' MMM, YYYY", /*E is name of the day (in week), Y is year*/
"w'th week of' YYYY", /* w is the week of the year */
"EEEE, dd'th' MMMM, YYYY" /*E is day name in the week */
};
LocalDateTime now = LocalDateTime.now();
for(String dateTimeFormat : dateTimeFormats) {
System.out.printf("Pattern "%s" is %s %n", dateTimeFormat,
DateTimeFormatter.ofPattern(dateTimeFormat).format(now));
}
}
} Pattern "dd-MM-yyyy" is 05-11-201
5
Pattern "d '('E')' MMM, YYYY" is 5 (Thu) Nov, 201
5
Pattern "w'th week of' YYYY" is 45th week of 201
5
Pattern "EEEE, dd'th' MMMM, YYYY" is Thursday, 05th November, 2015
151. Formatting Times
• a (marker for the text a.m./p.m. marker)
• H (hour: value range 0–23)
• k (hour: value range 1–24)
• K (hour in a.m./p.m.: value range 0–11)
• h (hour in a.m./p.m.: value range 1–12)
• m (minute)
• s (second)
• S (fraction of a second)
• z (time zone: general time-zone format)
152. Custom Time Patterns
class CustomTimePatterns {
public static void main(String []args) {
// patterns from simple to complex ones
String [] timeFormats = {
"h:mm", /* h is hour in am/pm (1-12), m is minute */
"hh 'o''clock'", /* '' is the escape sequence to print a single quote */
"H:mm a", /* H is hour in day (0-23), a is am/pm*/
"hh:mm:ss:SS", /* s is seconds, S is milliseconds */
"K:mm:ss a" /* K is hour in am/pm(0-11) */
};
LocalTime now = LocalTime.now();
for(String timeFormat : timeFormats) {
System.out.printf("Time in pattern "%s" is %s %n", timeFormat,
DateTimeFormatter.ofPattern(timeFormat).format(now));
}
}
}
Time in pattern "h:mm" is 12:2
7
Time in pattern "hh 'o''clock'" is 12 o'cloc
k
Time in pattern "H:mm a" is 12:27 P
M
Time in pattern "hh:mm:ss:SS" is 12:27:10:4
1
Time in pattern "K:mm:ss a" is 0:27:10 PM
153. Flight Travel - Time Calculation - Example
DateTimeFormatter dateTimeFormatter =
DateTimeFormatter.ofPattern("dd MMM yyyy hh.mm a");
// Leaving on 1st Jan 2016, 6:00am from "Singapore"
ZonedDateTime departure = ZonedDateTime.of(
LocalDateTime.of(2016, Month.JANUARY, 1, 6, 0),
ZoneId.of("Asia/Singapore"));
System.out.println("Departure: " + dateTimeFormatter.format(departure));
// Arrival on the same day in 10 hours in "Auckland"
ZonedDateTime arrival =
departure.withZoneSameInstant(ZoneId.of("Paci
fi
c/Auckland")).plusHours(10);
System.out.println("Arrival: " + dateTimeFormatter.format(arrival));
Departure: 01 Jan 2016 06.00 A
M
Arrival: 01 Jan 2016 09.00 PM
154. Agenda
• Introduction & Overview
• Lambdas
• Functional interfaces
• Streams
• Parallel streams
• Date & Time package
• Refactoring to Java 8
155. Examples of refactorings (to Java 8)
❖ Convert anonymous inner
classes to lambda expressions
(when they are functional
interfaces)
❖ Convert for/foreach loops to
streams (i.e., external iteration
to internal iteration
)
❖ Replace nested if conditions and
loops and instead use enhanced
stream methods in collections
156. Refactoring loops to streams
❖ Replace if conditions with stream functions that return
boolean value (
fi
lter,
fi
ndFirst, anyMatch, …)
❖ Replace for, while, and do-while loops with stream
operations (especially forEach)
❖ Replace accumulation operations with collect, or reduce
(or its special forms such as sum, count, etc)
157. public static void main(String []file) throws Exception {
// process each file passed as argument
// try opening the file with FileReader
try (FileReader inputFile = new FileReader(file[0])) {
int ch = 0;
while( (ch = inputFile.read()) != -1) {
// ch is of type int - convert it back to char
System.out.print( (char)ch );
}
}
// try-with-resources will automatically release FileReader object
}
public static void main(String []file) throws Exception {
Files.lines(Paths.get(file[0])).forEach(System.out::println);
}
Exploit enriched Java APIs with
lambdas and streams support
External iteration (for loop) to internal
iteration (forEach in sterams)
159. Source: LAMBDAFICATOR: From Imperative to Functional Programming through Automated Refactoring. Lyle Franklin; Alex
Gyori; Jan Lahoda; Danny Dig. 35th International Conference on Software Engineering (ICSE), 2013.
160. Tool support for refactoring
❖ Most Java IDEs provide
suggestions to automatically
refactor to lambdas and
streams
❖ IDEs that support Java 8
refactoring include: Eclipse,
IntelliJ Idea and NetBeans