An anonymous inner class (AIC) can be used to create a subclass of an abstract class or a concrete class. An AIC can also provide a concrete implementation of an interface, including the addition of state (fields). An instance of an AIC can be referred to using this in its method bodies, so further methods can be called on it, its state can be mutated over time, etc. None of these apply to lambdas.

I'd guess that the majority of uses of AICs were to provide stateless implementations of single functions and so can be replaced with lambda expressions, but there are other uses of AICs for which lambdas cannot be used. AICs are here to stay.

UPDATE

Another difference between AICs and lambda expressions is that AICs introduce a new scope. That is, names are resolved from the AIC's superclasses and interfaces and can shadow names that occur in the lexically enclosing environment. For lambdas, all names are resolved lexically.

Answer from Stuart Marks on Stack Overflow
Top answer
1 of 10
120

An anonymous inner class (AIC) can be used to create a subclass of an abstract class or a concrete class. An AIC can also provide a concrete implementation of an interface, including the addition of state (fields). An instance of an AIC can be referred to using this in its method bodies, so further methods can be called on it, its state can be mutated over time, etc. None of these apply to lambdas.

I'd guess that the majority of uses of AICs were to provide stateless implementations of single functions and so can be replaced with lambda expressions, but there are other uses of AICs for which lambdas cannot be used. AICs are here to stay.

UPDATE

Another difference between AICs and lambda expressions is that AICs introduce a new scope. That is, names are resolved from the AIC's superclasses and interfaces and can shadow names that occur in the lexically enclosing environment. For lambdas, all names are resolved lexically.

2 of 10
67

Lambdas though a great feature, will only work with SAM types. That is, interfaces with only a single abstract method. It would fail as soon as your interface contains more than 1 abstract method. That is where anonymous classes will be useful.

So, no we cannot just ignore anonymous classes. And just FYI, your sort() method can be more simplified, by skipping the type declaration for p1 and p2:

Collections.sort(personList, (p1, p2) -> p1.firstName.compareTo(p2.firstName));

You can also use method reference here. Either you add a compareByFirstName() method in Person class, and use:

Collections.sort(personList, Person::compareByFirstName);

or, add a getter for firstName, directly get the Comparator from Comparator.comparing() method:

Collections.sort(personList, Comparator.comparing(Person::getFirstName));
Discussions

performance - Big execution time difference between java Lambda vs Anonymous class - Stack Overflow
I was curious about performance of creation of java8 lambda instances against the same anonymous class. (Measurement performed on win32 java build 1.8.0-ea-b106). I've created very simple example and More on stackoverflow.com
🌐 stackoverflow.com
java - Lambda vs anonymous inner class performance: reducing the load on the ClassLoader? - Stack Overflow
I would like to know how big of a benefit lambdas have in Java 8. I agree that it might be more readable sometimes to use lambdas, but does it have really such of a big impact on the performance si... More on stackoverflow.com
🌐 stackoverflow.com
July 15, 2014
algorithm - Java lambdas 20 times slower than anonymous classes - Stack Overflow
I don't know what LeetCode does to achieve this weird performance, so the question is this: what it could be doing to make it that bad? ... If the code is executed only once (for the examples on leetcode) the decreasing execution time might be related due to the fact that the lambda bytecode is generated at runtime. Whereas your anonymous comparator class ... More on stackoverflow.com
🌐 stackoverflow.com
performance - Are there plans to make lambda expressions in Java more performant than anonymous classes? - Stack Overflow
When I first heard about lambdas in Java I thought that this was already the case. However, I later read that this study which says that this is not the true. It says that there are possibilities of More on stackoverflow.com
🌐 stackoverflow.com
🌐
Medium
medium.com › javarevisited › experienced-developers-use-these-quirks-to-create-better-java-lambdas-4ae656148274
Java 8 Lambdas vs Anonymous Classes Performance | Javarevisited
February 23, 2022 - Lambdas, with the help of indy, are converted to function objects. IDE suggests lambda instead of anonymous classes. Even so, Java runtime doesn't just convert lambda to an anonymous class.
🌐
Baeldung
baeldung.com › home › java › core java › lambda expression vs. anonymous inner class
Lambda Expression vs. Anonymous Inner Class | Baeldung
January 8, 2024 - This is because an anonymous class leads to an extra class file on the compilation, which takes additional time during class loading and verification during runtime. The performance of lambda expressions is better because the invokedynamic ...
Top answer
1 of 1
30

UPDATE

A few comments wondering if my benchmark at the bottom was flawed - after introducing a lot of randomness (to prevent the JIT from optimising too much stuff), I still get similar results so I tend to think it is ok.

In the meantime, I have come across this presentation by the lambda implementation team. Page 16 shows some performance figures: inner classes and closures have similar performance / non-capturing lambda are up to 5x times faster.

And @StuartMarks posted this JVMLS 2013 talk from Sergey Kuksenko on lambda performance. The bottom line is that post JIT compilation, lambdas and anonymous classes perform similarly on current Hostpot JVM implementations.


YOUR BENCHMARK

I have also run your test, as you posted it. The problem is that it runs for as little as 20 ms for the first method and 2 ms for the second. Although that is a 10:1 ratio, it is in no way representative because the measurement time is way too small.

I have then taken modified your test to allow for more JIT warmup and I get similar results as with jmh (i.e. no difference between anonymous class and lambda).

public class Main {

    static interface ICallback {
        void payload();
    }
    static void measureAnonymousClass() {
        final int arr[] = {0};
        ICallback clb = new ICallback() {
            @Override
            public void payload() {
                arr[0]++;
            }
        };
        clb.payload();
    }
    static void measureLambda() {
        final int arr[] = {0};
        ICallback clb = () -> {
            arr[0]++;
        };
        clb.payload();
    }
    static void runTimed(String message, Runnable act) {
        long start = System.nanoTime();
        for (int i = 0; i < 10_000_000; i++) {
            act.run();
        }
        long end = System.nanoTime();
        System.out.println(message + ":" + (end - start));
    }
    public static void main(String[] args) {
        runTimed("as lambdas", Main::measureLambda);
        runTimed("anonymous class", Main::measureAnonymousClass);
        runTimed("as lambdas", Main::measureLambda);
        runTimed("anonymous class", Main::measureAnonymousClass);
        runTimed("as lambdas", Main::measureLambda);
        runTimed("anonymous class", Main::measureAnonymousClass);
        runTimed("as lambdas", Main::measureLambda);
        runTimed("anonymous class", Main::measureAnonymousClass);
    }
}

The last run takes about 28 seconds for both methods.


JMH MICRO BENCHMARK

I have run the same test with jmh and the bottom line is that the four methods take as much time as the equivalent:

void baseline() {
    arr[0]++;
}

In other words, the JIT inlines both the anonymous class and the lambda and they take exactly the same time.

Results summary:

Benchmark                Mean    Mean error    Units
empty_method             1.104        0.043  nsec/op
baseline                 2.105        0.038  nsec/op
anonymousWithArgs        2.107        0.028  nsec/op
anonymousWithoutArgs     2.120        0.044  nsec/op
lambdaWithArgs           2.116        0.027  nsec/op
lambdaWithoutArgs        2.103        0.017  nsec/op
🌐
Medium
medium.com › @nagarjun_nagesh › lambda-functions-vs-anonymous-inner-classes-in-java-80893c2214d5
Lambda Functions vs. Anonymous Inner Classes in Java | by Nagarjun (Arjun) Nagesh | Medium
February 23, 2024 - Lambda functions are implemented using invokedynamic bytecode instructions, which offer better performance compared to the traditional approach of using anonymous inner classes. Additionally, lambda functions have less overhead in terms of memory ...
Find elsewhere
🌐
NashTech Blog
blog.nashtechglobal.com › home › java lambda vs anonymous class
Java Lambda Vs Anonymous Class - NashTech Blog
March 11, 2022 - The Performance of the lambda expression is better as it is pure compile-time activity and doesn’t incur extra cost during runtime. However, the Performance of the anonymous inner class is lower as requires class loading at runtime.
🌐
E Innovations
eginnovations.com › blog › demystifying-java-lambda-expressions
Demystifying Java Lambda Expressions | eG Innovations
February 29, 2024 - As a result, the more anonymous inner classes you have, the longer it may take for your application to start up, potentially leading to a less responsive user experience. Java lambda expressions result in lesser number of classes and therefore ...
🌐
Prgrmmng
prgrmmng.com › home › series › java lambdas and functional interfaces › lambdas vs anonymous classes: performance, readability, and maintainability
Lambdas vs Anonymous Classes: Performance, Readability, and Maintainability | prgrmmng.com
August 11, 2025 - Use lambdas for clean, expressive, and performant code when implementing functional interfaces. Prefer anonymous classes for more complex, stateful implementations or when working with legacy code.
🌐
Medium
medium.com › @ntiinsd › java-lambdas-vs-anonymous-classes-which-wins-in-2025-359677efd659
Java Lambdas vs. Anonymous Classes: Which Wins in 2025? | by inside Nikita's Mind | Medium
June 28, 2025 - They shine in stream operations and event handling. Anonymous Classes are inner classes without a name, used for implementing interfaces or extending classes, offering flexibility but often verbose syntax.
Top answer
1 of 1
85

You are obviously encountering the first-time initialization overhead of lambda expressions. As already mentioned in the comments, the classes for lambda expressions are generated at runtime rather than being loaded from your class path.

However, being generated isn’t the cause for the slowdown. After all, generating a class having a simple structure can be even faster than loading the same bytes from an external source. And the inner class has to be loaded too. But when the application hasn’t used lambda expressions before¹, even the framework for generating the lambda classes has to be loaded (Oracle’s current implementation uses ASM under the hood). This is the actual cause of the slowdown, loading and initialization of a dozen internally used classes, not the lambda expression itself².

You can easily verify this. In your current code using lambda expressions, you have two identical expressions (i1, i2) -> Integer.compare(i1.start, i2.start). The current implementation doesn’t recognize this (actually, the compiler doesn’t provide a hint neither). So here, two lambda instances, having even different classes, are generated. You can refactor the code to have only one comparator, similar to your inner class variant:

final Comparator<? super Interval> comparator
  = (i1, i2) -> Integer.compare(i1.start, i2.start);
int start = Collections.binarySearch(intervals, newInterval, comparator);
int skip = start >= 0 ? start : -start - 1;
int end = Collections.binarySearch(intervals.subList(skip, intervals.size()),
                                   new Interval(newInterval.end, 0),
                                   comparator);

You won’t notice any significant performance difference, as it’s not the number of lambda expressions that matters, but just the class loading and initialization of the framework, which happens exactly once.

You can even max it out by inserting additional lambda expressions like

final Comparator<? super Interval> comparator1
    = (i1, i2) -> Integer.compare(i1.start, i2.start);
final Comparator<? super Interval> comparator2
    = (i1, i2) -> Integer.compare(i1.start, i2.start);
final Comparator<? super Interval> comparator3
    = (i1, i2) -> Integer.compare(i1.start, i2.start);
final Comparator<? super Interval> comparator4
    = (i1, i2) -> Integer.compare(i1.start, i2.start);
final Comparator<? super Interval> comparator5
    = (i1, i2) -> Integer.compare(i1.start, i2.start);

without seeing any slowdown. It’s really the initial overhead of the very first lambda expression of the entire runtime you are noticing here. Since Leetcode itself apparently doesn’t use lambda expressions before entering your code, whose execution time gets measured, this overhead adds to your execution time here.

See also “How will Java lambda functions be compiled?” and “Does a lambda expression create an object on the heap every time it's executed?”

¹ This implies that JDK code that will be executed before handing control over to your application doesn’t use lambda expressions itself. Since this code stems from times before the introduction of lambda expressions, this is usually the case. With newer JDKs, modular software will be initialized by different, newer code, which seems to use lambda expressions, so the initialization of the runtime facility can’t be measured within the application anymore in these setups.

² The initialization time has been reduced significantly in newer JDKs. There are different possible causes, general performance improvements, dedicated lambda optimizations, or both. Improving initialization time in general, is an issue that the JDK developers did not forget.

🌐
Medium
mcvalls.medium.com › java-lambda-expressions-and-anonymous-classes-3b49489388b5
Java: Lambda Expressions and Anonymous Classes | by Marcelo Valls | Medium
February 22, 2022 - I’ve once heard a dev talking about “some functional programming engine” working behind the scenes (?), or saying things like “Lambda expressions perform terribly bad” and so on… but actually, they are just anonymous classes implemented in the place. The key about Lambda Expressions is that they represent algorithms. Even if they are Anonymous Classes and can be referenced as simple Java Objects, they are still representing algorithms, and it allows us to think about our code in a more functional way.
🌐
Stack Overflow
stackoverflow.com › questions › 27409330 › are-there-plans-to-make-lambda-expressions-in-java-more-performant-than-anonymou
performance - Are there plans to make lambda expressions in Java more performant than anonymous classes? - Stack Overflow
It's almost certainly better now than it was as of that presentation. It might have passed the point where it beats anonymous classes, and it might not have; I don't know of up-to-date benchmarks.
🌐
O'Reilly
oreilly.com › library › view › refactoring-to-modern › 9780134653617 › RFMJ_03_01.html
3.1 Performance of Anonymous Inner Classes versus Lambda Expressions - Refactoring to Modern Java [Video]
1.1 Why Java 8? 4m 42s1.2 Prerequisites · 4m 55s1.3 Project Code · 1m 43s · 2.1 Lambda Expressions · 22m 1s2.2 Collections and the Streams API · 28m 25s2.3 Getting to Grips with Optional · 14m 7s · 3.1 Performance of Anonymous Inner Classes versus Lambda Expressions ·
🌐
Javaplanet
javaplanet.io › home › lambda expressions › performance considerations with lambda expressions
Performance Considerations with Lambda Expressions -
September 6, 2025 - One of the main concerns regarding the performance of lambda expressions is the object creation overhead. Lambda expressions are compiled into anonymous classes under the hood, which can lead to additional memory allocation and runtime overhead. Anonymous Class Creation: When a lambda expression ...
🌐
DZone
dzone.com › coding › frameworks › how lambdas and anonymous inner classes work
How Lambdas And Anonymous Inner Classes Work
February 8, 2017 - Lambdas implement a functional interface. Anonymous Inner Classes can extend a class or implement an interface with any number of methods.
🌐
LinkedIn
linkedin.com › pulse › java-8-lambdas-vs-anonymous-classes-saral-saxena
Java 8 Lambdas Vs Anonymous Classes
March 8, 2018 - So the reason to opt for lambdas is just because concise code, more readability, less ceremony to do simple things i.e. replacement of anonymous class (you still have to write an anonymous class, in case of lambda you don't have to write a class). Reuse of code, create lambda expressions and pass it around methods. Further more introduction of lambda enabled number of good things in API such as Stream which provides an abstraction over the iteration. In Java 1.7 there was a new JVM Opcode was released named invokedynamic and Java 8 Lambda uses this.
🌐
Medium
medium.com › @damian.kolasa › performance-implications-of-lambdas-and-method-references-when-mapping-a-stream-in-java-79f6e2da6806
Performance implications of lambdas and method references when mapping a stream in Java | by Damian Kolasa | Medium
June 13, 2018 - Or we can do a performance hack and remove one of the mapping functions: Lambda expression and more coarse grained mapping. We can ditch lambdas altogether and just create a anonymous instance of a required interface. Of course we know that creating a class instance (our implementation) every time we need to map a Person to a City is a bit of overkill (eden space problems).
🌐
TutorialsPoint
tutorialspoint.com › differences-between-anonymous-class-and-lambda-expression-in-java
Differences between anonymous class and lambda expression in Java?\\n
July 10, 2020 - By using a lambda expression, we can declare methods without any name. An anonymous class object generates a separate class file after compilation that increases the size of a jar file while a lambda expression is converted into a private method.