2017 IEEE/ACM 39th International Conference on Software Engineering

Clone Refactoring with Lambda Expressions
Nikolaos Tsantalis, Davood Mazinanian, Shahriar Rostami
Computer Science and Software Engineering
Concordia University, Montreal, Canadatsantalis, d mazina, s rostam@encs.concordia.ca

proposed technique performs a sophisticated static source codeanalysis to extract intra- and inter-procedural data dependencies between the statements inside the clone fragments tobe merged, and examines whether these data dependencies
would be preserved after the refactoring of the clones. If theparameterization of the clone differences breaks at least oneof the originally existing dependencies, then the refactoring is
not behavior-preserving, and thus the clones are assessed as
non-refactorable. Using this refactorability analysis tool, we
performed a large-scale empirical study on clones detected byfour different clone detectors in nine open-source projects [12],where we found out that around 94% of the detected clones
belong to either Type-2 (i.e., structurally/syntactically identicalcode fragments with variations in identifier names, literalvalues, and types), or Type-3 (i.e., copied fragments withstatements changed, added or removed in addition to Type2 differences) categories. Only 14% of these Type-2 andType-3 clones were assessed as safely refactorable using thestandard parameterization approach. Among the top reasons
preventing these clones from being refactorable are (1) the
presence of different expressions within matched statements
whose parameterization would change the program behavior,(2) the presence of unmapped statements within the clone
fragments, also known as clone gaps, and (3) the presence ofdifferent method calls having a void return type (Java does
not allow parameters of void type).
Java 8 introduced Lambda expressions as a means to support
functional programming. A Lambda expression in Java 8, isan anonymous function containing either a block of statements
or a single expression that can be passed as a parameter to amethod, thus achieving behavior parameterization [13]. Oneof the most important features of a Lambda expression is thatit executes in the context of its invocation (i.e., inside themethod in which it is passed as an argument), and thus it canuse the values of the variables that are defined in that context.
This makes Lambda expressions ideal for the parameterizationof the three behavioral differences discussed in the previous
paragraph preventing the refactoring of Type-2 and Type-3
clones, since with Lambda expressions we can parameterize
behavior that is different among the clone fragments withoutchanging the original execution order.

Abstract—Lambda expressions have been introduced in Java
8 to support functional programming and enable behavior parameterization by passing functions as parameters to methods.
The majority of software clones (duplicated code) are known
to have behavioral differences (i.e., Type-2 and Type-3 clones).
However, to the best of our knowledge, there is no previous work to investigate the utility of Lambda expressions forparameterizing such behavioral differences in clones. In thispaper, we propose a technique that examines the applicability of
Lambda expressions for the refactoring of clones with behavioral
differences. Moreover, we empirically investigate the applicability
and characteristics of the Lambda expressions introduced torefactor a large dataset of clones. Our findings show that Lambda
expressions enable the refactoring of a significant portion ofclones that could not be refactored by any other means.
Keywords-Refactoring; Code duplication; Lambda expressions

I. I NTRODUCTION
The refactoring of software clones can help to reduce thesize of the code-base [1], [2], [3], avoid software defects due toinconsistent clone updates [4], [5], and minimize the negative
effect of duplicated code on maintenance effort and cost [6],[7]. A recent study involving GitHub contributors has shownthat they are seriously concerned about code duplication [8].
Among the top reasons they applied Extract Method refactorings was to reuse existing code (i.e., avoid duplication)and remove already existing duplication [8]. However, clone
refactoring is not trivial, because the majority of clones are not
identical code fragments, i.e., developers tend to modify the
copied code fragments to adjust them to another context, or
to different requirements. As a matter of fact, there are more
copy/pasted fragments in which minor to significant editing
activities took place than identical clones in repositories [9].
Motivation: The current state-of-the-art clone refactoring
techniques merge clones by introducing parameters in theextracted method for the expressions being different among
the merged clone fragments [10], [11]. After the refactoring,
the parameterized expressions are passed as arguments to theextracted method calls, and thus these expressions are evaluated before the execution of the extracted duplicated code.
However, this parameterization approach could cause a change
in the program behavior, especially when the parameterized
expressions are method calls and object creations, due to sideeffects on the state of the objects involved in these expressions.
In a previous work [12], we developed a refactorability
analysis approach that can automatically determine whether
the parameterization of the expressions being different between two clones could change the program behavior. The

1558-1225/17 $31.00 © 2017 IEEE
DOI 10.1109/ICSE.2017.14

Contributions: In this paper, we propose a technique and atool that utilizes Lambda expressions to enable the refactoringof Type-2 and Type-3 clones having behavioral differencesthat cannot be parameterized with regular parameters. In

5960

particular, we developed an algorithm to examine whether it
is possible to introduce Lambda expressions for the unmappedstatements (i.e., clone gaps) and expressions assessed as nonparameterizable by our previously proposed refactorability
analysis approach [12]. To the best of our knowledge, this is
the first work to investigate the use of Lambda expressions as ameans to refactor software clones with behavioral differences.
To evaluate the efficacy of the proposed technique, we firstassess its correctness by refactoring and testing 12,602 clone
pairs covered by unit tests, and reporting the compilation errors
and test failures that occurred. Next, we apply the proposed
technique on a dataset of 46,765 Type-2 and Type-3 clone
pairs, and report the percentage of the clone pairs whoserefactoring was enabled using Lambda expressions, and thecharacteristics of the introduced Lambda expressions. Finally,
we make publicly available the dataset of the examined clones
to facilitate future research on clone refactoring [14].

set up logic of the tests, while the last two statements constitutethe common tear down logic of the tests) into separate
methods. However, this approach might not be always feasible(e.g., the set up logic of the tests should return two variables,
namely saved and savedZone, and Java allows methods toreturn at most one value), and does not eliminate completely
the duplication (e.g., the two statements initializing the mockobjects and testing the assertion will remain duplicated). The
second approach is to parameterize the differences in the test
methods. Figure 1b shows the parameterization of the test
methods using two regular parameters. Note that in the extracted method the types of the mock objects have been generalized to the common superclass type RegularTimePeriod,and method getFirstMillisecond() is polymorphicallycalled. This parameterization is changing the program behavior
and makes the refactored tests fail. The reason is that themock objects are instantiated before the execution of theextracted method, when they are passed as arguments to theextracted method, and thus their instantiation is not using
the appropriate Locale and TimeZone configured in theset up logic of the tests. Through inter-procedural program
dependence analysis, we can see that Day and Hour constructors are using the static variables Locale.defaultLocale
and TimeZone.defaultTimeZone, defined by statements
Locale.setDefault() and TimeZone.setDefault(), respectively, in the set up logic, and thus there are interprocedural data dependencies from these statements to theconstructor invocations. Figure 1c shows the parameterizationof the test methods using Lambda expressions to pass thetwo different class instantiations as arguments to the extracted
method. Note that the type of the first parameter in theextracted method is the java.util.function.Supplier
functional interface (more details about functional interfaces
will be given in Section III-B), and the Lambda expressions
passed as arguments are executed by calling the get() method
over the Supplier parameter arg0. This parameterization ispreserving the program behavior and makes the refactored tests
pass, because the mock objects are instantiated in exactly thesame execution point as before the refactoring.

II. M OTIVATING E XAMPLESIn this section, we use two examples of clones from opensource projects to motivate the reader about the usefulness ofLambda expressions in the refactoring of clones.
Example 1: Figure 1a shows two duplicated methods foundin the test code of the JFreeChart project (version 1.0.10)
that create a mock object of Day and Hour type, respectively, to test its method getFirstMillisecond(). Both test
methods initially save the current Locale and TimeZone of
the system into temporary variables saved and savedZone,
respectively, and set the Locale to UK and the TimeZone toEurope/London, before instantiating the mock object. After
testing an assertion with assertEquals(), the Locale and
TimeZone of the system is reset to the original values savedin the temporary variables. The reset of the Locale and
TimeZone is necessary to avoid affecting other unit tests
whose execution follows. The duplicated test methods are
Type-2 clones and have only two differences (highlighted
in yellow), namely (1) the type of the mock object being
instantiated, and (2) the literal of long type passed as the firstargument in assertEquals(). It should be emphasized thatthe same test method is duplicated 9 times in the JFreeChart
test code-base, each time testing a different subclass type of
the RegularTimePeriod superclass type, namely Day, Hour,
Millisecond, Minute, Month, Quarter, Second, Week,
and Year, with exactly the same differences.
If we assume that the developers of these test methods
decide to test the mock objects with another Locale and/or
TimeZone, they would have to apply the same changes 9times, which requires significant effort and time. Therefore, we
can argue that this is an interesting case for refactoring, assuming that future test maintenance activities are probable. In fact
there is evidence that developers read, write, and maintain testcode [15], [16], [17], and thus clone refactoring could facilitate
test code reuse, understandability, and maintainability.
To refactor these test methods there are two alternative
approaches. The first approach is to extract the identical functionality (i.e., the first four statements constitute the common

Example 2: Figure 2a shows two duplicated methods foundin the Apache Ant project (version 1.7.0) that belong toclasses LineContains and LineContainsRegExp, respectively. Both methods implement a similar logic, i.e., they reada stream line-by-line (the current line is saved in the line
field), and the first method (left side of Figure 2a) examines ifline contains one of the words inside the contains vector,
while the second method (right side of Figure 2a) examines ifline matches with one of the regular expressions inside theregexps vector. The duplicated methods are Type-3 clones
and have two main differences, namely (1) the types of theelements inside the vectors (contains is a vector of String
objects, while regexps is a vector of RegularExpression
objects), and (2) the logic behind the matching of line asindicated by the unmapped statements (highlighted in red)
inside the inner for loop.

61
60

Difference between mapped statements

Data dependence

public void testGetFirstMillisecond() {public void testGetFirstMillisecond() {Locale saved = Locale.getDefault();
Locale saved = Locale.getDefault();
Locale.setDefault(Locale.UK);
Locale.setDefault(Locale.UK);
TimeZone savedZone = TimeZone.getDefault();
TimeZone savedZone = TimeZone.getDefault();
TimeZone.setDefault(TimeZone.getTimeZone("Europe/London")); TimeZone.setDefault(TimeZone.getTimeZone("Europe/London"));Day d = new Day(1, 3, 1970);
Hour h = new Hour(15, 1, 4, 2006);
assertEquals(5094000000L, d.getFirstMillisecond());
assertEquals(1143900000000L, h.getFirstMillisecond());
Locale.setDefault(saved);
Locale.setDefault(saved);
TimeZone.setDefault(savedZone);
TimeZone.setDefault(savedZone);}}(a) A pair of clones found in the tests of the JFreeChart open-source project
public void testGetFirstMillisecond() {extracted(new Day(1, 3, 1970), 5094000000L);}

public void testGetFirstMillisecond() {extracted(new Hour(15, 1, 4, 2006), 1143900000000L);}

public void extracted(RegularTimePeriod arg0, long arg1) {Locale saved = Locale.getDefault();
Locale.setDefault(Locale.UK);
TimeZone savedZone = TimeZone.getDefault();
TimeZone.setDefault(TimeZone.getTimeZone("Europe/London"));RegularTimePeriod d = arg0;
assertEquals(arg1, d.getFirstMillisecond());
Locale.setDefault(saved);
TimeZone.setDefault(savedZone);}(b) Parameterization with regular parameters changing the program behavior
public void testGetFirstMillisecond() {extracted(()->new Day(1, 3, 1970), 5094000000L);}

public void testGetFirstMillisecond() {extracted(()->new Hour(15, 1, 4, 2006), 1143900000000L);}

public void extracted(Supplier<RegularTimePeriod> arg0, long arg1) {Locale saved = Locale.getDefault();
Locale.setDefault(Locale.UK);
TimeZone savedZone = TimeZone.getDefault();
TimeZone.setDefault(TimeZone.getTimeZone("Europe/London"));RegularTimePeriod d = arg0.get();assertEquals(arg1, d.getFirstMillisecond());
Locale.setDefault(saved);
TimeZone.setDefault(savedZone);}(c) Parameterization with Lambda expressions preserving the program behavior
Fig. 1. Using Lambda expressions to enable the refactoring of Type-2 clones.

Data dependence
Unmapped statement
Difference between mapped statements
protected int extracted(Vector vector,
public int read()public int read()
Function<Integer, Boolean> matcher)throws IOException {throws IOException {throws IOException {1 if (!getInitialized()) {1 if (!getInitialized()) {if (!getInitialized()) {22
initialize();
initialize();
initialize();
setInitialized(true);
setInitialized(true);
setInitialized(true);
3
3
}
}
}
4 int ch = -1;
4 int ch = -1;
int ch = -1;
5 if (line != null) {5 if (line != null) {if (line != null) {66ch = line.charAt(0);ch = line.charAt(0);ch = line.charAt(0);77if (line.length() == 1) {if (line.length() == 1) {if (line.length() == 1) {8
8line = null;line = null;line = null;} else {} else {} else {99line = line.substring(1);line = line.substring(1);line = line.substring(1);}}}} else {} else {} else {10
10
final int containsSize = contains.size();
final int regexpsSize = regexps.size();
final int containsSize = vector.size();1111
for (line = readLine();for (line = readLine();for (line = readLine();line != null;line != null;line != null;line = readLine()) {line = readLine()) {line = readLine()) {1212boolean matches = true;
boolean matches = true;
boolean matches = true;13
for (int i = 0; matches && i<containsSize; i++) { 13for (int i = 0; matches && i<regexpsSize; i++) {for (int i = 0; matches && i<containsSize; i++) {14
14String containsStr =RegularExpression regexp =(String)contains.elementAt(i);(RegularExpression)regexps.elementAt(i);matches = (boolean)matcher.apply(i);Regexp re = regexp.getRegexp(getProject());
15
matches = line.indexOf(containsStr)>=0;
matches = re.matches(line);
15
16
}
}
}
if (matches ^ isNegated()) {16
17
if (matches ^ isNegated()) {if (matches ^ isNegated()) {break;
17
18
break;
break;}}}}}}
if (line != null) {19
18
if (line != null) {if (line != null) {return read();19
20
return read();return read();
}
}
}
}
}
}
return ch;
20 return ch;
21 return ch;}}}(a) A pair of clones found in the Apache Ant open-source project
public int read() throws IOException {return extracted(contains,(Integer i) -> {String containsStr = (String)contains.elementAt(i);return line.indexOf(containsStr)>=0;});}

Fig. 2.

(b) Extracted method after refactoring

public int read() throws IOException {return extracted(regexps,(Integer i) -> {RegularExpression regexp = (RegularExpression)regexps.elementAt(i);Regexp re = regexp.getRegexp(getProject());
return re.matches(line);});}(c) Clones after refactoring with Lambda expressions
Using Lambda expressions to enable the refactoring of Type-3 clones.

62
61

To refactor these methods one could first try to convert
them into Type-2 clones by moving the unmapped statements
before or after the common code. In our previous work [12],we observed some typical patterns of Type-3 clones that canbe easily converted into Type-2 clones by inlining temporary
variables that appear in only one of the clones, or by moving
statements declaring a variable at a different nesting level.
However, in the example of Figure 2a it is not possible tomove the unmapped statements, because they depend on thevalue of variable i that increments after each iteration of theinner for loop (i.e., there is a data dependence from the forloop, which declares and increments variable i to the first
unmapped statement that uses i to retrieve the next elementfrom the vector). In turn, the statements that follow inside
the inner for depend on the variable declared by the first
unmapped statement (i.e., containsStr and regexp, respectively), as shown by the data dependencies. Therefore, we needa parameterization approach that preserves the execution of theunmapped statements inside the inner for loop.
Figure 2c shows the parameterization of the methods using
Lambda expressions to pass the two different line matching
behaviors as arguments to the extracted method (Figure 2b).
The Lambda expressions (Figure 2c) take as input parameteri and return the matching result as a boolean. The typeof the second parameter in the extracted method is the Javapredefined java.util.function.Function functional interface, and the Lambda expressions passed as arguments
are executed by calling the apply(i) method through the
Function parameter matcher. This example demonstrates
that Lambda expressions are executed in the context of their
invocation, and thus they can use the values of the variables
that are defined in that context (i.e., variable i).
Alternatively, these methods could be parameterized by applying the Template Method design pattern [18], i.e., introducing a new abstract method in the common superclass where theextracted code (i.e., template) will be pulled up, replacing theuncommon code with a call to the abstract method, and finallyoverriding the abstract method in the subclasses containing theoriginal clones with the corresponding behavior. However, it
is not always possible to apply the Form Template Method
refactoring [19], because (a) the clones might exist in the sameclass or in classes not having a common superclass, (b) it
might not be always possible to make the common superclassabstract, if the project contains objects instantiated from thecommon superclass, (c) the common superclass might haveother subclasses that must provide an implementation for the
newly introduced abstract method without necessarily needing
its functionality, and (d) it might not be always possible tointroduce a new intermediate common superclass (i.e., extract
superclass) to host the template method, if the subclasses
containing the original clones belong to different levels of theinheritance hierarchy. On the other hand, there are no such
restrictions for the application of Lambda expressions.
With these examples, it becomes clear that Lambda expressions can enable the refactoring of clones whose parameterization is not feasible or behavior-preserving by other means.

III. A PPROACH
A. Input
The input of our approach is the output of the clone
refactorability analysis tool from our prior research [12],which takes as input a pair of clone fragments, and returns
a mapping between the statements of the clone fragments,
along with the differences (i.e., pairs of expressions being
different) inside the mapped statements, and a list of unmappedstatements (i.e., statements that could not be matched with any
statement from the other clone fragment due to incompatible
AST structure) for each clone fragment. In a nutshell, thesolution proposed in our prior research [12] applies a maximum
common subgraph algorithm [20] on the Program Dependence
Graphs [21] of the clones in a divide-and-conquer fashion bybreaking the initial statement mapping problem to smaller subproblems based on the control dependence structure of theclones. In this way, it explores the search space of alternative
mapping solutions in order to maximize the number of mappedstatements and minimize the number of differences between
them. Additionally, it can properly handle clones in whichmatching statements have been reordered, in contrast to tokenbased differencing approaches, such as MCIDiff [22], that do
not consider the syntactic structure of the program.
A visual representation of the extracted information isshown in Figure 2a, where the differences between the mappedstatements are highlighted in yellow and the unmapped statements are highlighted in red. In the final phase, a list of
preconditions is examined to determine whether the detecteddifferences can be safely parameterized with regular parameters, and whether the unmapped statements can be safely
moved before or after the common code. If the examinedpreconditions fail, the corresponding differences or unmappedstatements are associated with a precondition violation, andthe clones are assessed as non-refactorable.
Our current work focuses on the differences and unmappedstatements associated with precondition violations and proposes a method to examine whether their parameterization
with Lambda expressions is feasible.
B. Lambda Unification
Since Lambda expressions are anonymous functions, theunification of two code fragments into a common function (ora functional interface following the Java terminology) requiresthat these code fragments can be abstracted to two functions
with an identical signature. More specifically, there are three
conditions that should be met regarding the signature:1) The code fragments should return at most one variable ofthe same type, or different types that can be generalized to
a common type.
2) The code fragments should require the same input parameter types from the extracted duplicated code.
3) The code fragments should throw the same exception types.
Our approach can be divided into 4 parts:
1. Handling of statement gaps:
A statement gap consists of two sets of consecutive unmapped statements Si and Sj , which are nested at the same

63
62

Function checkPreconditions (line 8) takes as input two sets ofstatements and examines the following list of preconditions:level. To determine whether a statement gap can be parameterized in the form of Lambda expressions, we propose
Algorithm 1. In a nutshell, the proposed algorithm is a recursive function that can expand backwards and/or forwards theoriginal sets of statements (if necessary), so that the final setsof statements require the same input parameters and produce
the same output. Additionally, when the aforementioned conditions are finally met, it also examines a list of preconditions
to ensure that the introduction of the Lambda expressions is
feasible and behavior-preserving.

1) The statements contained in Si and Sj should collectively
throw the same exception types.
2) Sets Si and Sj should not include branching statements(break, continue) without including the corresponding
target switch or loop statement.
3) Sets Si and Sj should not include conditional returnstatements (i.e., return without an expression causing a
direct exit from the method containing the clone).
4) If sets Si and Sj contain return statements with an
expression returning a value, then all possible execution
flows should end with a return statement.
5) If sets Si and Sj contain statements using variables declared in the code remaining in the original methods
after refactoring, then these variables should be final oreffectively final (i.e., a variable or parameter whose value isnever changed after it is initialized [23]). This condition applies only to local variables and parameters of the methods
containing the clone fragments, but not to accessed fields,
and it is required because Java handles Lambda expressions
as single-method anonymous classes [24].
6) Sets Si and Sj should not include all statements of theoriginal clone fragments. This condition is necessary to
avoid cases where the expansion might cover the entire
clone fragments.

Algorithm 1 Recursive function determining if a statement
gap can be parameterized in the form of Lambda expressions
Input: A statement-level gap [Si , Sj ]Output: true if Lambda refactoring is feasible, false otherwise, updated sets [Si0 , Sj0 ] if expansion occurred
1: function L AMBDA R EFACTORABLE (Si , Sj )2:
UVi = usedVariables(Si )3:
UVj = usedVariables(Sj )4:
if commonParameters(UVi , UVj ) then5:
RVi = returnedVariables(Si )6:
RVj = returnedVariables(Sj )7:
if validReturnType(RVi , RVj ) then8:
if checkPreconditions(Si , Sj ) then9:
return true10:
end if
11:
else if [Si0 , Sj0 ] = forward(Si , Sj ) 6= [Si , Sj ] then12:
return L AMBDA R EFACTORABLE(Si0 , Sj0 )13:
end if
14:
else if [Si0 , Sj0 ] = backward(Si , Sj ) 6= [Si , Sj ] then15:
return L AMBDA R EFACTORABLE(Si0 , Sj0 )16:
end if17:
return false
18: end function

Finally, function backward (line 14) adds the statement executed right before the first statement in Si and Sj , respectively,
as long as this statement is nested at the same level. Function
forward (line 11) adds the statement executed right after thelast statement in Si and Sj , respectively, as long as thisstatement is nested at the same level and contains differences,which cannot be parameterized with regular parameters.
2. Handling of expression differences:
An expression difference consists of two expressions foundin two mapped statements of the clone fragments, which may
have a different syntactic structure (i.e., different types of AST
nodes), but are evaluated to the same type or types having
a common superclass. For example, in the clones shown in
Figure 2a mapped statements 15 and 16 from each clone,
contain an expression difference highlighted in yellow. The expressions have a different AST type (on the left clone fragment
we have an infix expression line.indexOf(containsStr)>= 0, while on the right one we have a method invocation expression re.matches(line)), but both of them are evaluatedto type boolean. As a result, the condition validReturnType
is met by default, and the only remaining conditions thatshould be examined to determine if the two expressions can beparameterized as Lambdas is commonParameters and checkPreconditions (only preconditions 1 and 5 are applicable).

Function usedVariables (lines 2, 3) takes as input a set ofstatements and returns the set of variables that are collectively
used in the input statements. Function returnedVariables (lines5, 6) takes as input a set of statements and returns the set ofvariables that are modified in the input statements and areused by code executed after the input statements. FunctioncommonParameters (line 4) takes as input two sets of variables
and examines if the types of the corresponding variables
are the same. It should be noted that the input sets do notneed to have the same cardinality, as long as one of themis a proper (or strict) subset of the other, and the additionalvariables of the superset are declared before the clone fragment
to be extracted (e.g., parameters of the method containing
the clone fragment). This relaxation was necessary in orderto deal with overloaded method calls accepting a different
number of arguments. Function validReturnType (line 7) takes
as input two sets of variables and examines if the cardinalityof both sets is equal to zero or one (i.e., one variable can be
returned at most). When the cardinality of both sets is equal
to one, it additionally examines if the types of the variables
are the same, or if they are sub-types of a common superclass.

3. Merging of overlapping gaps and expression differences:
After all statement gaps and expression differences areprocessed, we apply a post-processing step to determine if
some of them can be merged in order to minimize the6463number of Lambda expressions that should be introduced.
More specifically, we apply three merging operations:
1) If the statements corresponding to an expression difference
are included inside an expanded statement gap, then only
the statement gap is parameterized.
2) If a statement gap is subsumed by another one (i.e., all
its statements are included within a larger statement gap),
then only the larger one is parameterized.
3) If two statement gaps have an overlap (i.e., they share somecommon statements, but do not subsume one another), thenthey are merged into a single statement gap. If the merged
statement gap is refactorable according to Algorithm 1,then the original overlapping statement gaps are not parameterized, and only the merged one is parameterized.

matches} and RVj = {boolean matches}. As a result,

now the sets Si0 and Sj0 contain statements that require thesame input parameters and produce the same output, and thus
no further expansion is needed.
IV. E VALUATION

To assess the correctness and applicability of the proposed
technique for enabling the refactoring of clones with nontrivial behavioral differences, we designed a study aiming toanswer the following research questions:
RQ1: Does the proposed approach refactor clones without
introducing compile errors or changing program behavior?
RQ2: What portion of the clones that cannot be parameterizedwith regular parameters, becomes refactorable with
Lambda expressions?
RQ3: What are the characteristics of the introduced Lambda
expressions?

4. Creating appropriate functional interfaces:
For each one of the final statement gaps and expression
differences an appropriate functional interface should be added
as a parameter to the extracted method. Java 8 provides a list of
predefined functional interfaces in the java.util.function
package, which are used whenever it is possible:
1) Function<T,R>: The Lambda expressions take as input
one argument (T) and return a result (R).
2) Supplier<T>: The Lambda expressions take no input
arguments and return a result (T).
3) Consumer<T>: The Lambda expressions take as input one
argument (T) and return no result.
All aforementioned functional interface types do not support
exception throwing. Therefore, when the Lambda expressions
take as input two or more arguments and/or throw one ormore exceptions, a custom functional interface needs to be
introduced within the same class that the extracted method
will be placed in:

A. Experiment Setup
To investigate our research questions we created a large
and diverse dataset of clones extracted from 9 open source
projects using 4 different clone detectors, consisting of 46,765
clone pairs having statement gaps (Type-3) and/or expression
differences (Type-2) that were assessed as non-refactorable
using the standard parameterization approach [12].
Subject Selection: To avoid bias in the selection of projects
and enable the comparison of our results with previous studies,
we adopted the systems used in the studies conducted by Tairasand Gray [10] and Tsantalis et al. [12], shown in Table I.
TABLE IE XAMINED P ROJECTS@FunctionalInterface
interface CustomInterface {T0 apply(T1 arg1, T2 arg2, ...) throws E1, E2, ...;}

C. Running Example
In this subsection, we will demonstrate the application of
Algorithm 1 on the motivating example we used in Section II,
shown in Figure 2a. The initial input to the algorithm is thesets of statements Si = {14} and Sj = {14, 15}. Both sets ofstatements are nested at the same level under the mapped forloops (with IDs 13 and 13, respectively). The sets of usedvariables are UVi = {int i} and UVj = {int i}, andthus the function commonParameters returns true, and there
is no need for a backward expansion of the sets Si and Sj .
However, the sets of returned variables are RVi = {String
containsStr} and RVj = {Regexp re}, and thus thefunction validReturnType returns false, because the types ofthe variables differ and cannot be generalized to a common
super-type. Therefore, the function forward is executed andupdates the original input statements to Si0 = {14, 15} andSj0 = {14, 15, 16}. After the forward expansion, the setsof used variables UVi and UVj remain the same, while thesets of returned variables are becoming RVi = {boolean

Project

DomainAge†

KLoC

Apache Ant 1.7.0
Columba 1.4
EMF 2.4.1
JMeter 2.3.2
JEdit 4.2
JFreeChart 1.0.10
JRuby 1.4.0
Hibernate 3.3.2
SQuirreL SQL 3.0.3

Java application build tool
email clientmodeling framework
server performance testing
text editor
chart library
programming language
Java persistence framework
universal SQL client

61/2
11/2

67
75
118
54
51
76
101
209
141

51/2
71/4
5
71/2
31/2
71/2
8

† years of development from the initial release to the examined release

The dataset includes projects from 9 different application
domains, having a different development history ranging from
2 to 8 years. We assume that these two variation points affectthe variability of the clones present in these systems, and thus
the generalizability of our findings.
Clone Detector Selection: We used 4 popular clone detection
tools, namely CCFinder [25], Deckard [26], CloneDR [27],and NiCad [28]. The selection criteria, tool descriptions, andconfiguration settings are detailed in [12]. We also kept in thedataset only one instance of the clones reported by multiple
tools to avoid having duplicate data points.
Data Collection: Figure 3 shows the process we followed forcollecting the data required to investigate our questions.

65
64

CCFinder
DeckardCloneDR
NiCad

1

ComputeTest Coverage<clones><systeminfo processor="nicad3" system="_" granularity="locks-blind" threshold="20%"minlines="5" maxlines="2500"/><cloneinfo npcs="26190" npairs="21264"/><runinfo ncompares="8598538" cputime="1916955"/><classinfo nclasses="583"/><class classid="1" nclones="2" nlines="148" similarity="93"><source file="WeblogicDeploymentTool.java" startline="709" endline="903" pcid="13283"></source><source file="WebsphereDeploymentTool.java" startline="679" endline="866" pcid="13119"></source></class><class classid="2" nclones="2" nlines="114" similarity="95"><source file="CBZip2OutputStream.java" startline="213" endline="364" pcid="25654"></source><source file="CBZip2OutputStream.java" startline="368" endline="515" pcid="25674"></source></class>2
Clone Pairs<class classid="3" nclones="2" nlines="61" similarity="90"><source file="TarFileSetTest.java" startline="41" endline="112" pcid="885"></source><source file="ZipFileSetTest.java" startline="41" endline="112" pcid="1113"></source></class><class classid="4" nclones="2" nlines="60" similarity="80"><source file="CBZip2InputStream.java" startline="653" endline="721" pcid="25598"></source><source file="CBZip2InputStream.java" startline="588" endline="641" pcid="25583"></source></class>

Clone Detector
Results

Coverage
ReportSpreadsheet

No

HTML Reports
CompileErrorsYesCompileErrors?

Fig. 3.

Mapping
Information

Test Results

No

Approach: The execution of the entire test suite of a project
after each refactoring is rather time consuming. Therefore, for
the investigation of RQ1, we narrowed down our analysis ona single project, namely JFreeChart. The reason we selected
this project is that it has one of the highest unit test sourcecode coverage (e.g., 54.4% coverage for the src directoryand 69.5% including tests), and the fastest test suite execution
time (less than 10 seconds) among the examined projects.
Moreover, JFreeChart contains clones with diverse relative
locations, allowing to test all clone refactoring scenarios supported by our refactoring engine (i.e., Extract Method, Extract
and Pull Up Method, Form Template Method, Extract Utility
Method). We collected 12,602 clone pairs that were assessedas Lambda-parameterizable by our approach and were coveredby unit tests, out of which 230 (1.8%) are located in thesame method, 1,821 (14.5%) are located in the same class,
9,585 (76%) are located in different classes having a common
superclass, and 966 (7.7%) are located in unrelated classes.
Each clone pair was refactored and tested by executing theentire test suite of the project after each refactoring. To thebest of our knowledge, this is one of the most extensive
evaluations of a clone refactoring engine, even comparable tothe evaluation of tools specialized in the testing of refactoring
engines, such as SafeRefactor [32] and ASTGen [33].

8

6

Yes
Covered by
Unit Tests?

be possible to refactor these clones without causing any
compilation errors, and all tests of the project should passafter the application of the refactoring, assuming the clones
are covered by unit tests.

3

Clone Instances
Information

7

Undo
Refactoring
Run Tests

LambdaAnalysis

Parsing

Precondition
Violations
CSV Files

Yes
5

4

Building

RefactoringNo

Precondition
Violations?

The workflow applied for the collection of the experimental data.

We have fully automated the data collection process, bydeveloping an Eclipse command-line application [29] that:
1) Computes the unit test code coverage for the project underanalysis using the JaCoCo library [30].
2) Parses the output of clone detection tools and determines if
the clones are fully, partially, or not covered by unit tests.
3) Executes the proposed technique implemented as part of
the JDeodorant Eclipse plug-in [31] in headless mode foreach pair of clones reported by a clone detection tool.
4) Applies the appropriate refactoring for each pair of clones
assessed as Lambda-parameterizable by the proposed technique, based on the relative location of the clones.
5) Builds the project after each refactoring and reports any
compilation errors.
6) Executes the test suite of the project for each refactored
pair of clones that is covered by unit tests, compares thetest results after refactoring with those before refactoring,and reports any differences.
7) Restores the project in its original state after each refactoring, by undoing the applied refactoring and rebuilding the
project.
8) Stores the collected information in CSV files (used forstatistical analysis), HTML reports (containing statement
mapping information and precondition violations for a pairof clones), and a spreadsheet (containing information about
all clones examined in the project and links to the reports).

Results: None of the 12,602 applied refactorings caused acompilation error, and only one refactoring led to a test
failure. The clones involved in the test failure are themethods writeObject() in classes XYShapeAnnotation
and DialValueIndicator, respectively. The problem is
actually caused from the way that the statements ofthese methods are matched by [12] and the special roleof these methods in the serialization of objects. Morespecifically, the methods include statements calling special functions (e.g., SerialUtilities.writePaint(),
SerialUtilities.writeStroke()) that write the fieldvalues of the classes into a stream. For the deserialization
phase, the methods readObject() located in the same classes
are used to restore the serialized field values by reading themin a specific order from the stream. However, the statement
mapping algorithm [12] matches the statements of the methods
in a different order than their original order in an attempt tomaximize the number of mapped statements. This is causing
the field values to be inserted in a different order into thestream after the refactoring, and thus the deserialization fails.
We consider that this issue can be fixed by improving the
mapping algorithm [12] to assume the presence of data dependencies between statements reading/writing from/to a stream.

B. Correctness of Lambda Refactorings (RQ1)
Motivation: The goal of RQ1 is to ensure that the proposed
approach can safely refactor clones using Lambda expressions
without introducing compilation errors and changing program
behavior. This kind of evaluation is essential to strengthen thevalidity of the collected empirical data that will be used toanswer RQ2 and RQ3. Our hypothesis is that if our approachassesses the behavioral differences appearing between a pairof clone fragments as Lambda-parameterizable, then it should

Conclusion: We found that the proposed clone refactoring
approach is very reliable by testing it on 12,602 pairs of clones.
Our clone refactoring engine did not introduce any compilation
errors and caused only one test failure.

66
65

C. Applicability of Lambda Expressions (RQ2)
Motivation: The goal of RQ2 is to assess the applicability of
Lambda expressions for the refactoring of Type-2 and Type3 clones. Answering this question will help us understandhow useful are Lambda expressions for parameterizing the
behavioral differences existing in typical Type-2 and Type3 clones detected by clone detection tools. Moreover, we
break down the collected results taking into account three
dimensions: (1) the source code type (clones in production
vs. test code), (2) the relative location (clones within the same
method, same class, same inheritance hierarchy, or unrelatedclasses), and (3) the clone type (Type-2 vs. Type-3). This will
help us understand if Lambda expressions are more usefulfor a particular category of clones. Finally, we investigate thepercentage of the clone pairs for which the Template Method
design pattern can be safely applied as an alternative solution
to Lambda expressions.

All clone pairs went through Lambda analysis (step 3 inFigure 3), and those without precondition violations wererefactored and compiled (but not tested). We consider that aclone pair refactored with Lambda expressions can be safely
refactored using the Template Method design pattern in twocases: 1) when the clone is extracted to a new superclass,because it can be declared abstract and thus we can add
abstract methods for the behavioral differences that will beoverridden by its subclasses containing the original clone
fragments, and 2) when the clone is extracted to an existingsuperclass that is already abstract and is only inherited by
the two subclasses containing the original clone fragments.
TABLE IIIC LONE T YPE AND L AMBDA A PPLICABILITY
Clone TypeTABLE IIR ELATIVE C LONE L OCATION AND L AMBDA A PPLICABILITY

Source Type

Clone Location#Pairs (%)#Applicable (%)

All

Same method
Same classSame Java file
Same hierarchy
Unrelated classes
Total

2832 ( 6.1%)
10723 (22.9%)
141 ( 0.3%)25025 (53.5%)8044 (17.2%)
46765 (100%)

1340 (47.3%)
7644 (71.3%)
113 (80.1%)
15824 (63.2%)
2297 (28.6%)
27218 (58.2%)

Production

Same method
Same classSame Java file
Same hierarchy
Unrelated classes
Total

2343 ( 7.5%)8715 (28.0%)
129 ( 0.4%)12315 (39.5%)
7661 (24.6%)
31163 (100%)

1209 (51.6%)
5800 (66.6%)
101 (78.3%)
6663 (54.1%)
2238 (29.2%)
16011 (51.4%)

Test

Same method
Same classSame Java file
Same hierarchy
Unrelated classes
Total

489 ( 3.1%)
2008 (12.9%)
12 ( 0.1%)
12710 (81.5%)383 ( 2.5%)
15602 (100%)

131 (26.8%)
1844 (91.8%)
12 ( 100%)
9161 (72.1%)
59 (15.4%)
11207 (71.8%)#Pairs (%)#Applicable (%)

Type II

28363 (60.65%)

16173 (57.02%)

Type III

18402 (39.35%)

11045 (60.02%)

Results: As we can observe in the last column of Table II, theparameterization with Lambda expressions is feasible in 58.2%of the examined clone pairs. Moreover, Lambda expressions
tend to be more applicable to clones detected in test code thanclones detected in production code (71.8% vs. 51.4%). We
believe this is due to the nature of the differences appearing
in test clones, which are mostly related to the instantiation of
the objects being tested and the assertions being examined. We
also found that the clones located in the same class or different
subclasses in the same inheritance hierarchy tend to be morerefactorable with Lambda expressions than clones located inunrelated classes. This result shows that the behavioral differences found in more “distant” clones (i.e., located in unrelatedclasses) are more difficult to be abstracted into Lambdas,
possibly because the implemented requirements are different.
Regarding the applicability of Lambdas with respect to clone
types, as we can observe in the last column of Table III,the percentage of Type-2 and Type-3 clones that can beparameterized using Lambda expressions is very similar (57%
vs. 60%). Finally, out of the 27,218 clone pairs refactoredwith Lambda expressions, we found that the Template Method
design pattern could be applied in only 34.2% of them.

Approach: Our analysis focused on 46,765 clone pairs having
statement gaps (Type-3) and/or expression differences (Type2) that were assessed as non-refactorable by [12]. This meansthat it is not possible to move the statement gaps before orafter the common code, and introduce regular parameters forthe expression differences, due to data dependencies between
the code in the gaps/differences and the common code to be
extracted. The third column of Table II shows the number andpercentage of clone pairs in 5 different categories of relative
location, for all clone pairs, those detected in production code,and those detected in test code, respectively. Two thirds of theexamined clone pairs belong to production code, while one
third of them to test code. We can also observe that most of
the clone pairs are located in different subclasses of the same
inheritance hierarchy (especially for clones in test code), while
the second most frequent relative clone location is within thesame class declaration. There is also a significant number ofclone pairs located in unrelated classes of the production code.
Regarding the types of the examined clone pairs, as shownin the second column of Table III, 60% of them are Type-2
clones, while the remaining 40% are Type-3 clones.

Conclusion: We found that Lambda expressions is a promisingJava feature for the refactoring of clones with behavioral differences, especially for those located in test code. In addition,
Lambda expressions tend to be more beneficial for clones
located in the same class or subclasses in the same inheritancehierarchy. Moreover, Lambda expressions can equally benefit
both Type-2 and Type-3 clones. Finally, the Template Method
design pattern can be used as an alternative approach toLambdas in only one third of the refactored clone pairs.
D. Characteristics of Lambda Expressions (RQ3)
Motivation: In the previous research question, we saw that
Lambda expressions can be very effective in the refactoring ofclones with behavioral differences. However, this refactoring
tends to disperse the duplicated code from two locations
originally to three locations after refactoring, i.e., the code67
66

corresponding to behavioral differences remains in the original
locations and is passed as Lambdas to the extracted method,while the common code is extracted to another method in
the same class, a superclass, or a utility class. The goal of
RQ3 is to assess the effect of Lambda expressions on thedispersion of the original code. According to best practiceguidelines, Lambda expressions should be short [34], and developers should prefer the standard functional interfaces [35].
When the clone fragments have a small number of behavioral
differences with a small size that can be parameterized using
the predefined functional interface types provided by Java, theresulting refactored code will be less dispersed. The smaller
the number and size of the differences, the more the code isconcentrated to a single location after refactoring. The morepredefined functional interface types are applicable, the lessnew custom types will be introduced after refactoring.

50

1

40

20
10

25.00%
7.04%

9.50%

0

20
0

Consumer Custom Function Supplier

0.73%

3.68%

Consumer Custom Function Supplier(a) Actual Functional Interface types(b) Break down of Custom types
Fig. 5. Distribution of Functional Interface Types.

Results: As we can observe in the box plot shown in Figure 4a,
the median value for the number of Lambda expression perclone pair is equal to 1, while the third (upper) quartile is equal
to 2. This means that 50% of the refactored clone pairs require
only one Lambda expression, while 75% of them require twoor less. Regarding the size of the Lambdas, for expression
differences the median value is equal to 1/6 of the clone
fragment size (box plot on the left side of Figure 4b), while forstatement gaps the median value is equal to 1/3 of the clone
fragment size (box plot on the right side of Figure 4b). Finally,
as we can observe in Figure 5a almost 60% of the Lambda
expressions can be parameterized using the Java predefined
functional interface types (i.e., Function, Supplier, Consumer),and thus there is no need to create custom types. As we
can observe in Figure 5b, an additional 30% of the custom
types could be converted to the Java predefined types if they
supported exception throwing, increasing the Lambdas that
could be potentially covered by the predefined types to 72%.
Conclusion: The majority of the refactored clone pairs requirea small number (two or less) of Lambda expressions toparameterize their behavioral differences. On average, the sizeof the Lambda expressions is relatively small covering 1/6of the clone fragment for expression differences, and 1/3 ofthe clone fragment for statement gaps. 60% of the Lambda
expressions can be parameterized with the Java predefined
functional interface types. This could increase to 72% if theJava predefined types supported exception throwing.
E. Threats to Validity
Internal: How reliable is the used statement mapping algorithm? The algorithm used for the mapping of the statements
within the clone fragments [12] definitely affects the resultsof this study, since it produces the expression differences
and statement gaps used as input by the proposed Lambda
refactoring approach. This algorithm maximizes the numberof matched statements and handles the matching of reorderedstatements between the clone fragments. Despite the fact that
it is using data dependence information (coming from interprocedural data flow analysis) as well as type binding information (coming from the compiler), to guide the matching of
the statements, there might be some cases where the statement
mapping returned by the algorithm is not the most accurate due
to missing dependencies resulting from an incomplete analysis.
However, the extensive testing we performed on 12,602 clone
pairs (Section IV-B) gives us the confidence that the usedstatement mapping algorithm is reliable and accurate.

1.00

0.33
2

60

30

Approach: Our analysis focused on the 27,218 clone pairs
refactored with Lambda expressions. We used the following
indirect measures for code dispersion:
1) The number of Lambda expressions required to parameterize the behavioral differences of the clone fragments.
2) The relative size of the Lambda expressions to the size ofthe clone fragments.
3) The functional interface types used to parameterize thebehavioral differences of the clone fragments.
For each clone pair, we count the number of Lambda expressions required to parameterize its behavioral differences(Figure 4a). For each Lambda expression, we compute theratio of its size (i.e., number of statements) over the size ofthe clone fragment (Figure 4b). In particular, for expression
differences, we approximate their size to one statement, although an expression is always part of a statement. Finally,for each Lambda expression, we record the functional interface
type (Function, Supplier, Consumer, or custom) used to parameterize the corresponding behavioral difference (Figure 5a).
Moreover, since the Java predefined functional interface types
do not support exception throwing, our refactoring implementation introduces a new custom type whenever the code inside
the Lambda expressions is throwing an exception, even if thenumber of arguments meets the requirements of a predefined
type. Therefore, we investigate the percentage of the custom
types that could be potentially converted to the Java predefined
types, if they supported exception throwing (Figure 5b).
28

70.59%
42.73%

40.73%

40

0.17
0.00
Expression Diffs Statement Gaps(a) Number of Lambda Expressions(b) Size of Lambda Expressions
Fig. 4. Characteristics of the Lambda Expressions in refactored clone pairs.

6867How does the clone-pair granularity affect the results? The
results of this study are reported at clone-pair level, because
the used statement mapping algorithm does not support theanalysis of clone groups (also known as clone classes) containing more than two clone fragments, but only pairs of clones.
Whenever a clone group is analyzed, we apply our techniqueon every possible combination of clone pairs (i.e., n2 fora group with n clone fragments). The majority of the clonegroups analyzed in this study contain 2 or 3 clone instances(the median is equal to 2, the third quartile is equal to 3,
and the mean size is 2.9). This means that for most clonegroups the number of clone pair combinations is either 1 or 3,
and thus reporting the results at clone-group level would not
significantly affect our findings.

for refactoring [2]. However, systematic edits cannot captureclones that are not consistently updated, mainly because thedevelopers are not aware of their existence, or clones that arenever updated. On the other hand, an approach based on the
input of clone detectors is more generic and universal, since
existing tools can detect both consistently and inconsistently
modified clones depending on their configuration (i.e., similarity threshold), as well as stable clones. Other clone refactoring
techniques have a more restricted scope. For instance, Tairasand Gray [10] focus only on Type-2 clones having expression
differences whose parameterization is free of side-effects.
Hotta et al. [37] and Juillerat et al. [38] focus only on clones
that can be refactored by applying the Template Method design
pattern. Our technique has a much broader scope being able
to handle clones with diverse relative locations and behavioral
differences. Finally, there are works based on machine learningthat recommend clones for refactoring [1], [2], [3].

External: How representative are the examined clones? The
clone detectors used in the study have several configuration
options, related to the size and similarity of the clones. Even
minor changes in the settings can affect significantly the characteristics of the detected clones [36]. Wang et al. introduced asearch-based approach to determine the configurations (fromthe space of all configuration choices) that maximizes tool
agreement [36]. However, in our study it is important to get
as more diverse clones as possible from each clone detector.
Therefore, we used the default or recommended configuration
options for each tool. These settings have been consistently
used in a large number of empirical studies and can beconsidered as standards.
How representative are the examined projects? We included
in our study 9 projects coming from 9 different application
domains, but also having a different Java version compatibility.
For example, the projects EMF and JRuby are using the newer
language features, such as Generics and varargs, but otherprojects like Ant are compatible with previous Java versions.
This diversity in the domain and the language features usedby each project makes possible to generalize our findings toseveral other open-source projects with similar characteristics.
Moreover, we adopted the exact same systems used in previous
studies [10], [12] to avoid bias in the selection of subjects.

Lambda Refactoring: Gyori et al. [39], [40] developed a tool,
named L AMBDA F ICATOR, which automates two refactorings
introducing Lambda expressions. The first refactoring converts
anonymous inner classes to lambda expressions. The second
one converts for loops that iterate over Collections tofunctional operations that use lambda expressions. The goalof this work is to make the code more succinct by eliminating
anonymous classes, and enable unobtrusive parallelism by applying functional operations like map or filter to iterations.
However, our goal is to leverage Lambda expressions in order
to eliminate code duplication.
Lambda-related Studies: There is a very limited numberof studies investigating the effect of Lambda expressions on
development, debugging and testing effort. A recent controlled
experiment comparing the use of C++ lambdas with iterators [41] has shown that participants spent more time withcompiler errors, and had more errors, when using lambdas
as compared to iterators, suggesting difficulty with the syntax
chosen for C++. However, the experience level of the participants had a large effect on the experiment results, since
professionals were more likely to complete tasks, with orwithout lambdas, and could do so more quickly than students.
Therefore, the experience of the developers, the language syntax, and tool support (e.g., for debugging lambda expressions)play a significant role on the understandability of the code.

Verifiability: To make the results of this study reproducible,
we provide online all the artifacts required to reproduce andreplicate the experiments, including the source code of ourtools [31], [29], the results of the clone detection tools usedin the experiment, and the R scripts we developed to obtain
the results of the experiments [14].

VI. C ONCLUSIONSIn summary, the main conclusions and lessons learned are:1) Lambdas are effective for parameterizing behavioral differences (58% applicability), especially for test clones (72%).
2) Lambdas are equally beneficial for parameterizing Type-2
and Type-3 clones (57% vs. 60% applicability).
3) The majority of clones require one or two Lambdas.
4) 60% of the Lambdas can be parameterized using just threeof the Java predefined functional interface types.
5) Extending these functional interface types to support exception throwing, would increase the aforementioned percentage to 72%.

V. R ELATED W ORK
Clone Refactoring: Meng et al. [11] proposed a technique for
automated clone refactoring based on systematic edits (i.e.,
similar edits to different locations in the source code). One
major difference is that Meng et al. [11] rely on systematicedits, while our approach takes as input the results of clone
detection tools. Relying on systematic edits for clone refactoring is a rather intuitive solution, since it is believed thatclones being frequently and consistently modified during theevolution of a software system should have a higher priority

69
68

R EFERENCES[21] J. Ferrante, K. J. Ottenstein, and J. D. Warren, “The program dependence
graph and its use in optimization,” ACM Transactions on Programming
Languages and Systems, vol. 9, no. 3, pp. 319–349, Jul. 1987.
[22] Y. Lin, Z. Xing, Y. Xue, Y. Liu, X. Peng, J. Sun, and W. Zhao, “Detecting
differences across multiple instances of code clones,” in Proceedings ofthe 36th International Conference on Software Engineering, 2014, pp.
164–174.
[23] Oracle. The Java™ Tutorials – Local Classes. [Online]. Available:
https://docs.oracle.com/javase/tutorial/java/javaOO/localclasses.html[24] ——. The Java™ Tutorials – Lambda Expressions. [Online]. Available: https://docs.oracle.com/javase/tutorial/java/javaOO/
lambdaexpressions.html[25] T. Kamiya, S. Kusumoto, and K. Inoue, “CCFinder: A multilinguistic
token-based code clone detection system for large scale source code.”IEEE Trans. Software Eng., vol. 28, no. 7, pp. 654–670, 2002.
[26] L. Jiang, G. Misherghi, Z. Su, and S. Glondu, “DECKARD: Scalable
and accurate tree-based detection of code clones,” in Proceedings ofthe 29th International Conference on Software Engineering, 2007, pp.
96–105.
[27] I. Baxter, A. Yahin, L. Moura, M. Sant’Anna, and L. Bier, “Clone
detection using abstract syntax trees,” in Proceedings of the International
Conference on Software Maintenance, 1998, pp. 368–377.
[28] C. K. Roy and J. R. Cordy, “NICAD: Accurate detection of near-missintentional clones using flexible pretty-printing and code normalization,”in Proceedings of the 16th IEEE International Conference on Program
Comprehension, 2008, pp. 172–181.
[29] Tsantalis. JDeodorant – Commandline. [Online]. Available: https://github.com/tsantalis/jdeodorant-commandline[30] EclEmma. JaCoCo Java Code Coverage Library. [Online]. Available:
http://www.eclemma.org/jacoco/[31] Tsantalis. JDeodorant – JLS8-support branch. [Online]. Available:
https://github.com/tsantalis/JDeodorant/tree/JLS8-support[32] G. Soares, R. Gheyi, and T. Massoni, “Automated behavioral testingof refactoring engines,” IEEE Transactions on Software Engineering,
vol. 39, no. 2, pp. 147–162, Feb 2013.
[33] B. Daniel, D. Dig, K. Garcia, and D. Marinov, “Automated testing of
refactoring engines,” in Proceedings of the 6th Joint Meeting of theEuropean Software Engineering Conference and the ACM SIGSOFT
Symposium on the Foundations of Software Engineering, 2007, pp. 185–
194.
[34] JetBrains IntelliJ IDEA Blog. Java 8 top tips. [Online]. Available:
https://blog.jetbrains.com/idea/2016/07/java-8-top-tips/[35] Baeldung. Lambda expressions and functional interfaces: Tips
and best practices. [Online]. Available: http://www.baeldung.com/
java-8-lambda-expressions-tips[36] T. Wang, M. Harman, Y. Jia, and J. Krinke, “Searching for better
configurations: A rigorous approach to clone evaluation,” in Proceedingsof the 2013 9th Joint Meeting on Foundations of Software Engineering,ser. ESEC/FSE 2013. New York, NY, USA: ACM, 2013, pp. 455–465.
[37] K. Hotta, Y. Higo, and S. Kusumoto, “Identifying, tailoring, and suggesting form template method refactoring opportunities with program
dependence graph,” in Proceedings of the 16th European Conference
on Software Maintenance and Reengineering, 2012, pp. 53–62.
[38] N. Juillerat and B. Hirsbrunner, “Toward an implementation of the”form template method” refactoring,” in Proceedings of the SeventhIEEE International Working Conference on Source Code Analysis andManipulation, ser. SCAM ’07. Washington, DC, USA: IEEE Computer
Society, 2007, pp. 81–90.
[39] A. Gyori, L. Franklin, D. Dig, and J. Lahoda, “Crossing the gap
from imperative to functional programming through refactoring,” inProceedings of the 2013 9th Joint Meeting on Foundations of Software
Engineering, ser. ESEC/FSE 2013. New York, NY, USA: ACM, 2013,
pp. 543–553.
[40] L. Franklin, A. Gyori, J. Lahoda, and D. Dig, “LAMBDAFICATOR:
From imperative to functional programming through automated refactoring,” in Proceedings of the 2013 International Conference on Software
Engineering, ser. ICSE ’13. Piscataway, NJ, USA: IEEE Press, 2013,
pp. 1287–1290.
[41] P. M. Uesbeck, A. Stefik, S. Hanenberg, J. Pedersen, and P. Daleiden,“An empirical study on the impact of C++ lambdas and programmer
experience,” in Proceedings of the 38th International Conference on
Software Engineering, ser. ICSE ’16. New York, NY, USA: ACM,
2016, pp. 760–771.

[1] W. Wang and M. W. Godfrey, “Recommending clones for refactoring
using design, context, and history,” in Proceedings of the IEEE International Conference on Software Maintenance and Evolution, 2014, pp.
331–340.
[2] M. Mondal, C. Roy, and K. Schneider, “Automatic ranking of clones
for refactoring through mining association rules,” in Proceedings of theIEEE Conference on Software Maintenance, Reengineering and Reverse
Engineering, 2014 Software Evolution Week, 2014, pp. 114–123.
[3] M. Mondal, C. K. Roy, and K. A. Schneider, “Automatic identificationof important clones for refactoring and tracking,” in Proceedings of the
14th IEEE International Working Conference on Source Code Analysis
and Manipulation, 2014, pp. 11–20.
[4] E. Juergens, F. Deissenboeck, B. Hummel, and S. Wagner, “Do code
clones matter?” in Proceedings of the 31st International Conference on
Software Engineering, 2009, pp. 485–495.
[5] N. Bettenburg, W. Shang, W. M. Ibrahim, B. Adams, Y. Zou, and A. E.
Hassan, “An empirical study on inconsistent changes to code clones at
the release level,” Science of Computer Programming, vol. 77, no. 6,
pp. 760–776, 2012.
[6] A. Lozano and M. Wermelinger, “Assessing the effect of clones onchangeability,” in Proceedings of the 24th IEEE International Conference on Software Maintenance, 2008, pp. 227–236.
[7] S. Thummalapenta, L. Cerulo, L. Aversano, and M. Di Penta, “Anempirical study on the maintenance of source code clones,” Empirical
Software Engineering, vol. 15, no. 1, pp. 1–34, 2010.
[8] D. Silva, N. Tsantalis, and M. T. Valente, “Why we refactor? confessionsof github contributors,” in Proceedings of the 24th ACM SIGSOFTInternational Symposium on the Foundations of Software Engineering,ser. FSE ’16, 2016.
[9] H. Sajnani, V. Saini, J. Svajlenko, C. K. Roy, and C. V. Lopes,“SourcererCC: Scaling code clone detection to big-code,” in Proceedingsof the 38th International Conference on Software Engineering, ser. ICSE
’16. New York, NY, USA: ACM, 2016, pp. 1157–1168.
[10] R. Tairas and J. Gray, “Increasing clone maintenance support by unifying
clone detection and refactoring activities,” Inf. Softw. Technol., vol. 54,
no. 12, pp. 1297–1307, Dec. 2012.
[11] N. Meng, L. Hua, M. Kim, and K. S. McKinley, “Does automatedrefactoring obviate systematic editing?” in Proceedings of the 37th
International Conference on Software Engineering - Volume 1, ser. ICSE
’15. Piscataway, NJ, USA: IEEE Press, 2015, pp. 392–402.
[12] N. Tsantalis, D. Mazinanian, and G. P. Krishnan, “Assessing therefactorability of software clones,” IEEE Transactions on Software
Engineering, vol. 41, no. 11, pp. 1055–1090, Nov 2015.
[13] R.-G. Urma, M. Fusco, and A. Mycroft, Java 8 in Action: Lambdas,
Streams, and Functional-style Programming, 1st ed. Greenwich, CT,
USA: Manning Publications Co., 2014.
[14] N. Tsantalis, D. Mazinanian, and S. Rostami. Clone Refactoringwith Lambda Expressions – Dataset. [Online]. Available: http://tiny.cc/ICSE17[15] G. Fraser, M. Staats, P. McMinn, A. Arcuri, and F. Padberg, “Doesautomated unit test generation really help software testers? a controlled
empirical study,” ACM Trans. Softw. Eng. Methodol., vol. 24, no. 4, pp.
23:1–23:49, Sep. 2015.
[16] S. Panichella, A. Panichella, M. Beller, A. Zaidman, and H. C. Gall,“The impact of test case summaries on bug fixing performance: An
empirical investigation,” in Proceedings of the 38th International Conference on Software Engineering, ser. ICSE ’16. New York, NY, USA:ACM, 2016, pp. 547–558.
[17] A. van Deursen, L. Moonen, A. Bergh, and G. Kok, “Refactoring test
code,” in Proceedings of the 2nd International Conference on Extreme
Programming and Flexible Processes in Software Engineering, ser. XP
2001, 2001, pp. 92–95.
[18] E. Gamma, R. Helm, R. Johnson, and J. Vlissides, Design Patterns:
Elements of Reusable Object-Oriented Software.
Addison-Wesley,
1995.
[19] M. Fowler, Refactoring: Improving the Design of Existing Code.
Boston, MA, USA: Addison-Wesley Longman Publishing Co., Inc.,
1999.
[20] J. J. McGregor, “Backtrack search algorithms and the maximal common
subgraph problem,” Software: Practice and Experience, vol. 12, no. 1,
pp. 23–34, 1982.

70
69