[{"data":1,"prerenderedAt":135},["ShallowReactive",2],{"qa-\u002Fjava\u002Fstreams-functional\u002Flambdas-functional-interfaces":3},{"page":4,"siblings":119,"blog":132},{"id":5,"title":6,"body":7,"description":11,"difficulty":14,"extension":15,"framework":16,"frameworkSlug":17,"meta":18,"navigation":19,"order":20,"path":21,"questions":22,"questionsCount":109,"related":110,"seo":111,"seoDescription":112,"stem":113,"subtopic":114,"topic":115,"topicSlug":116,"updated":117,"__hash__":118},"qa\u002Fjava\u002Fstreams-functional\u002Flambdas-functional-interfaces.md","Lambdas Functional Interfaces",{"type":8,"value":9,"toc":10},"minimark",[],{"title":11,"searchDepth":12,"depth":12,"links":13},"",2,[],"medium","md","Java","java",{},true,1,"\u002Fjava\u002Fstreams-functional\u002Flambdas-functional-interfaces",[23,28,32,36,40,44,48,52,56,60,64,68,73,77,81,85,89,93,97,101,105],{"id":24,"difficulty":25,"q":26,"a":27},"what-is-a-lambda","easy","What is a lambda expression in Java?","A lambda is an **anonymous function** — a block of behavior you can pass around\nas a value, without writing a named method or a class. It's compact syntax for\nimplementing a **functional interface** (an interface with a single abstract\nmethod). Introduced in **Java 8**, it brought functional-style programming to\nthe language.\n\n```java\n\u002F\u002F verbose anonymous class\nRunnable r1 = new Runnable() {\n  public void run() { System.out.println(\"hi\"); }\n};\n\n\u002F\u002F same thing as a lambda\nRunnable r2 = () -> System.out.println(\"hi\");\n```\n\nThe compiler matches the lambda to the interface's single method, so `r2`'s body\n*becomes* `run()`. Lambdas make code that takes behavior as a parameter\n(callbacks, comparators, stream operations) far less verbose.\n",{"id":29,"difficulty":25,"q":30,"a":31},"lambda-syntax-variants","What are the different lambda syntax forms?","A lambda is `parameters -> body`. The parts can be written several ways\ndepending on how many parameters there are and whether the body is one\nexpression or a block.\n\n```java\n()        -> 42                 \u002F\u002F no params, expression body\nx         -> x * 2             \u002F\u002F one param, parens optional\n(x)       -> x * 2            \u002F\u002F one param, explicit parens\n(x, y)    -> x + y           \u002F\u002F multiple params need parens\n(int x, int y) -> x + y      \u002F\u002F explicit types (rare; usually inferred)\n(x, y)    -> { return x + y; } \u002F\u002F block body needs { } and return\n```\n\nKey rules: **single-expression** bodies have no braces and no `return` (the value\nis implicit); a **block** body needs braces *and* an explicit `return` if it\nreturns a value. Parameter types are usually inferred, so you omit them.\n",{"id":33,"difficulty":25,"q":34,"a":35},"functional-interface","What is a functional interface?","A functional interface is an interface with exactly **one abstract method**\n(a **SAM** — Single Abstract Method). That single method is the target a lambda\nor method reference implements. It can still have any number of `default` and\n`static` methods — those don't count toward the one-abstract-method rule.\n\n```java\n@FunctionalInterface\ninterface Transformer {\n  String apply(String s);          \u002F\u002F the one abstract method\n  default String twice(String s) { return apply(apply(s)); } \u002F\u002F allowed\n}\n\nTransformer upper = s -> s.toUpperCase();\n```\n\nExamples in the JDK: `Runnable`, `Callable`, `Comparator`, and everything in\n`java.util.function`. Because there's only one abstract method, the compiler\nknows unambiguously which method your lambda body implements.\n",{"id":37,"difficulty":14,"q":38,"a":39},"functional-interface-annotation","What does the @FunctionalInterface annotation do?","`@FunctionalInterface` is an **optional** marker that tells the compiler \"this\ninterface is meant to have exactly one abstract method.\" If you accidentally add\na second abstract method, the build **fails** — it's a safety net, not a\nrequirement.\n\n```java\n@FunctionalInterface\ninterface Calc {\n  int op(int a, int b);\n  \u002F\u002F int other(int x);  \u002F\u002F would cause a COMPILE ERROR\n}\n```\n\nThe annotation has no runtime effect; a lambda works on any interface with one\nabstract method whether or not it's annotated. But adding it documents intent and\n**protects callers** who rely on lambda compatibility from a careless edit.\nNote methods inherited from `Object` (like `equals`) don't count as abstract.\n",{"id":41,"difficulty":14,"q":42,"a":43},"function-package-table","What are the core interfaces in java.util.function?","`java.util.function` provides the **general-purpose** functional interfaces so\nyou rarely need to write your own. The four families are Function, Consumer,\nSupplier, and Predicate, plus operator\u002Ftwo-arg variants:\n\n| Interface | Abstract method | Takes \u002F returns |\n| --------- | --------------- | --------------- |\n| `Function\u003CT,R>` | `R apply(T t)` | T -> R |\n| `BiFunction\u003CT,U,R>` | `R apply(T,U)` | (T,U) -> R |\n| `Supplier\u003CT>` | `T get()` | () -> T |\n| `Consumer\u003CT>` | `void accept(T t)` | T -> void |\n| `BiConsumer\u003CT,U>` | `void accept(T,U)` | (T,U) -> void |\n| `Predicate\u003CT>` | `boolean test(T t)` | T -> boolean |\n| `BiPredicate\u003CT,U>` | `boolean test(T,U)` | (T,U) -> boolean |\n| `UnaryOperator\u003CT>` | `T apply(T t)` | T -> T |\n| `BinaryOperator\u003CT>` | `T apply(T,T)` | (T,T) -> T |\n\n`UnaryOperator` and `BinaryOperator` are just `Function`\u002F`BiFunction` specialized\nto a single type — handy for things like `String::trim` or `Integer::sum`.\n",{"id":45,"difficulty":25,"q":46,"a":47},"function-interface","What is the Function interface used for?","`Function\u003CT,R>` represents a **transformation**: it takes one argument of type\n`T` and returns a result of type `R` via `apply`. It's the workhorse behind\n`Stream.map`.\n\n```java\nFunction\u003CString, Integer> length = s -> s.length();\nlength.apply(\"hello\");          \u002F\u002F 5\n\n\u002F\u002F used in a stream\nList\u003CInteger> lens = names.stream()\n                          .map(String::length)\n                          .toList();\n```\n\nWhen input and output are the *same* type, prefer `UnaryOperator\u003CT>` for\nclarity. For two inputs use `BiFunction\u003CT,U,R>`.\n",{"id":49,"difficulty":25,"q":50,"a":51},"supplier-consumer","What is the difference between Supplier and Consumer?","They're mirror images. A **`Supplier\u003CT>`** takes **no input** and **produces** a\nvalue (`T get()`) — a factory or lazy source. A **`Consumer\u003CT>`** **takes** a\nvalue and **returns nothing** (`void accept(T)`) — a side effect like printing\nor storing.\n\n```java\nSupplier\u003CDouble> rng = () -> Math.random();  \u002F\u002F produces\nrng.get();\n\nConsumer\u003CString> printer = s -> System.out.println(s); \u002F\u002F consumes\nprinter.accept(\"hi\");\n```\n\nSuppliers power lazy evaluation (`Optional.orElseGet`, `Logger` message\nsuppliers); consumers power `forEach` and `Optional.ifPresent`. Think of it as\n**output-only vs input-only**.\n",{"id":53,"difficulty":25,"q":54,"a":55},"predicate-interface","What is the Predicate interface?","`Predicate\u003CT>` takes a `T` and returns a **boolean** via `test` — it represents a\ncondition. It's what `Stream.filter` expects.\n\n```java\nPredicate\u003CInteger> isEven = n -> n % 2 == 0;\nisEven.test(4);                 \u002F\u002F true\n\nList\u003CInteger> evens = nums.stream()\n                          .filter(isEven)\n                          .toList();\n```\n\nPredicates compose with `and`, `or`, and `negate` (covered separately), letting\nyou build complex conditions from simple ones. For two arguments use\n`BiPredicate\u003CT,U>`.\n",{"id":57,"difficulty":14,"q":58,"a":59},"andthen-compose","What is the difference between andThen and compose on Function?","Both **chain** two functions, but in opposite order. `f.andThen(g)` runs **f\nfirst, then g** on f's result. `f.compose(g)` runs **g first, then f** — matching\nthe mathematical `f(g(x))`.\n\n```java\nFunction\u003CInteger,Integer> times2 = x -> x * 2;\nFunction\u003CInteger,Integer> plus3  = x -> x + 3;\n\ntimes2.andThen(plus3).apply(5);  \u002F\u002F (5*2)+3 = 13\ntimes2.compose(plus3).apply(5);  \u002F\u002F (5+3)*2 = 16\n```\n\nMnemonic: **andThen reads left-to-right** (do this, *and then* that);\n**compose reads inside-out**. Both return a *new* `Function`, leaving the\noriginals untouched.\n",{"id":61,"difficulty":14,"q":62,"a":63},"predicate-composition","How do you combine predicates with and, or, and negate?","`Predicate` has three default composition methods that return a **new** predicate:\n**`and`** (both must pass), **`or`** (either passes), and **`negate`** (flips the\nresult). They let you build readable compound conditions.\n\n```java\nPredicate\u003CString> notBlank = s -> !s.isBlank();\nPredicate\u003CString> shortStr = s -> s.length() \u003C 10;\n\nPredicate\u003CString> valid = notBlank.and(shortStr);\nPredicate\u003CString> blank = notBlank.negate();\nPredicate\u003CString> either = notBlank.or(shortStr);\n\nvalid.test(\"hello\");            \u002F\u002F true\n```\n\n`and` short-circuits like `&&` (skips the second test if the first fails). There's\nalso a static `Predicate.not(...)` (Java 11+) so you can negate a method\nreference: `filter(Predicate.not(String::isBlank))`.\n",{"id":65,"difficulty":14,"q":66,"a":67},"method-references","What is a method reference and what are its four kinds?","A method reference (`::`) is shorthand for a lambda that **just calls an existing\nmethod**. When a lambda does nothing but forward its arguments to one method, a\nmethod reference is cleaner. There are **four kinds**:\n\n| Kind | Syntax | Lambda equivalent |\n| ---- | ------ | ----------------- |\n| Static | `Integer::parseInt` | `s -> Integer.parseInt(s)` |\n| Bound instance | `out::println` (specific object) | `s -> out.println(s)` |\n| Unbound instance | `String::toUpperCase` (type) | `s -> s.toUpperCase()` |\n| Constructor | `ArrayList::new` | `() -> new ArrayList\u003C>()` |\n\n```java\nFunction\u003CString,Integer> parse = Integer::parseInt;     \u002F\u002F static\nConsumer\u003CString> print = System.out::println;           \u002F\u002F bound\nFunction\u003CString,String> up = String::toUpperCase;       \u002F\u002F unbound\nSupplier\u003CList\u003CString>> make = ArrayList::new;           \u002F\u002F constructor\n```\n\nThe compiler infers which method from the target functional interface's signature.\n",{"id":69,"difficulty":70,"q":71,"a":72},"bound-vs-unbound","hard","What is the difference between a bound and unbound instance method reference?","Both reference an instance method, but differ in **who supplies the receiver**\n(the object the method runs on). A **bound** reference captures a *specific*\nobject now; an **unbound** reference uses the *first argument* as the receiver.\n\n```java\nString prefix = \"Hello, \";\n\u002F\u002F BOUND — receiver is the captured `prefix` object\nFunction\u003CString,String> greet = prefix::concat;\ngreet.apply(\"Ada\");             \u002F\u002F \"Hello, Ada\"\n\n\u002F\u002F UNBOUND — receiver is the lambda's first arg\nFunction\u003CString,Integer> len = String::length;\nlen.apply(\"Ada\");               \u002F\u002F 3  (called as \"Ada\".length())\n```\n\nTell them apart by the left side of `::`: a **value\u002Fvariable** is bound, a\n**type name** is unbound. For an unbound reference the functional interface has\none *extra* leading parameter for the receiver.\n",{"id":74,"difficulty":70,"q":75,"a":76},"effectively-final","What does \"effectively final\" mean for variables captured by a lambda?","A lambda may **capture** local variables from its enclosing scope, but only ones\nthat are **final or effectively final** — meaning assigned exactly once and never\nreassigned afterward (even without the `final` keyword). Reassigning a captured\nvariable is a **compile error**.\n\n```java\nint factor = 3;                 \u002F\u002F effectively final — never reassigned\nFunction\u003CInteger,Integer> f = x -> x * factor;  \u002F\u002F OK\n\nint counter = 0;\nRunnable bad = () -> counter++; \u002F\u002F COMPILE ERROR — counter is reassigned\n```\n\nInstance and static fields are *not* subject to this — only **local variables**.\nThe restriction exists because the lambda captures a **copy of the value**, so\nallowing reassignment would create confusing divergence between the two copies.\n",{"id":78,"difficulty":70,"q":79,"a":80},"mutable-capture-workaround","Why can't a lambda mutate a captured local variable, and what's the workaround?","Because the lambda may **outlive** the method that created it (it can be stored\nand run later, possibly on another thread). Java captures locals **by value**, so\nletting you mutate the original would be ambiguous and unsafe. The fix is to\nmutate **state held inside an object** the variable points to, rather than the\nvariable itself.\n\n```java\n\u002F\u002F won't compile: total is a reassigned local\n\u002F\u002F int total = 0; list.forEach(n -> total += n);\n\nint[] total = {0};              \u002F\u002F array holds mutable state\nlist.forEach(n -> total[0] += n);\n\nAtomicInteger sum = new AtomicInteger();   \u002F\u002F thread-safe alternative\nlist.forEach(sum::addAndGet);\n```\n\nThat said, the *idiomatic* answer is to avoid mutation entirely — use a stream\nreduction (`mapToInt(...).sum()`) instead of accumulating into a captured variable.\n",{"id":82,"difficulty":70,"q":83,"a":84},"lambda-vs-anonymous-class","What is the difference between a lambda and an anonymous inner class?","They look similar but differ in important ways:\n\n| Aspect | Lambda | Anonymous class |\n| ------ | ------ | --------------- |\n| `this` | refers to the **enclosing** instance | refers to the **anonymous object** |\n| New scope | **no** new scope (shares the method's) | introduces its own scope |\n| Shadowing | can't shadow enclosing locals | can declare same-named locals |\n| Compilation | **`invokedynamic`** (no extra `.class`) | generates a separate `.class` file |\n| State | only the SAM (one method) | can have fields and multiple methods |\n\n```java\nRunnable lambda = () -> System.out.println(this); \u002F\u002F enclosing `this`\nRunnable anon = new Runnable() {\n  public void run() { System.out.println(this); } \u002F\u002F the Runnable itself\n};\n```\n\nThe `this` binding is the classic interview gotcha: inside a lambda, `this` is the\nsurrounding object, *not* the functional-interface instance.\n",{"id":86,"difficulty":70,"q":87,"a":88},"invokedynamic","How are lambdas compiled — do they create a class file?","No. Unlike anonymous classes (which generate a `Foo$1.class` at compile time),\nlambdas are compiled to an **`invokedynamic`** bytecode instruction plus a private\nsynthetic method holding the body. At **runtime** the JVM's `LambdaMetafactory`\nbuilds the implementation **lazily** on first use.\n\n```text\nanonymous class -> extra .class file generated at compile time\nlambda          -> invokedynamic; implementation linked at runtime\n```\n\nBenefits: **no class-file explosion**, smaller jars, and the JVM can optimize the\nstrategy over time. A stateless lambda that captures nothing may even be reused as\na **singleton**. This is why lambdas are generally lighter than anonymous classes.\n",{"id":90,"difficulty":14,"q":91,"a":92},"target-typing","What is target typing for a lambda?","A lambda has **no inherent type** — its type is determined by the **context** it\nappears in, called the **target type**. The same lambda can implement different\nfunctional interfaces depending on the variable, parameter, or return type it's\nassigned to.\n\n```java\nRunnable r       = () -> doWork();          \u002F\u002F target type Runnable\nCallable\u003CVoid> c = () -> { doWork(); return null; };\n\nComparator\u003CString> byLen = (a, b) -> a.length() - b.length();\n\u002F\u002F the SAME shape could fit any (String,String)->int interface\n```\n\nThe compiler reads the target type, finds its single abstract method, and checks\nthe lambda's parameters and return against that signature. This is why a lambda\ncan't be assigned to `var` (no target to infer from) or `Object`.\n",{"id":94,"difficulty":70,"q":95,"a":96},"exceptions-in-lambdas","How do you handle checked exceptions in a lambda?","A lambda may only throw checked exceptions that its **target functional\ninterface declares**. The `java.util.function` interfaces declare **none**, so a\nlambda calling a checked-exception method won't compile — you must handle it.\n\n```java\n\u002F\u002F won't compile: Files.readString throws IOException\n\u002F\u002F Function\u003CPath,String> f = p -> Files.readString(p);\n\nFunction\u003CPath,String> f = p -> {\n  try { return Files.readString(p); }\n  catch (IOException e) { throw new UncheckedIOException(e); }\n};\n```\n\nOptions: **try\u002Fcatch inside** the lambda (often wrapping in an unchecked\nexception), use an interface that *does* declare the exception (e.g. `Callable`),\nor write a small \"throwing function\" wrapper utility. There's no\nbuilt-in checked-exception-friendly functional interface.\n",{"id":98,"difficulty":14,"q":99,"a":100},"primitive-specializations","Why does java.util.function have primitive specializations like IntFunction?","To **avoid autoboxing**. Using `Function\u003CInteger,Integer>` boxes every `int` into\nan `Integer` object on the heap — costly in hot loops and streams. The primitive\nspecializations work directly on `int`, `long`, and `double`, eliminating that\noverhead.\n\n| Specialization | Signature |\n| -------------- | --------- |\n| `IntFunction\u003CR>` | `int -> R` |\n| `ToIntFunction\u003CT>` | `T -> int` |\n| `IntUnaryOperator` | `int -> int` |\n| `IntBinaryOperator` | `(int,int) -> int` |\n| `IntPredicate` | `int -> boolean` |\n| `IntSupplier` \u002F `IntConsumer` | `() -> int` \u002F `int -> void` |\n\n```java\nIntUnaryOperator square = x -> x * x;   \u002F\u002F no boxing\nsquare.applyAsInt(5);                    \u002F\u002F 25\n```\n\n`IntStream`, `LongStream`, and `DoubleStream` use these throughout, which is why\n`mapToInt(...).sum()` is faster than mapping to boxed `Integer`s.\n",{"id":102,"difficulty":14,"q":103,"a":104},"comparator-lambdas","How are lambdas and method references used to build Comparators?","`Comparator` is a functional interface, so you can write one as a lambda — but the\n**factory methods** `comparing`, `thenComparing`, and `reversed` make it far\ncleaner, and they take method references for the sort key.\n\n```java\n\u002F\u002F raw lambda\nComparator\u003CPerson> byAge = (a, b) -> Integer.compare(a.age(), b.age());\n\n\u002F\u002F idiomatic: key extractor + chaining\nComparator\u003CPerson> c = Comparator\n    .comparing(Person::lastName)\n    .thenComparing(Person::firstName)\n    .reversed();\n\npeople.sort(c);\n```\n\n`comparing` takes a `Function` (the key extractor) and builds the comparison for\nyou. For primitive keys use `comparingInt`\u002F`comparingDouble` to avoid boxing.\nThis is one of the most common real-world uses of method references.\n",{"id":106,"difficulty":14,"q":107,"a":108},"lambda-scope-this","What does `this` refer to inside a lambda?","Inside a lambda, **`this` refers to the enclosing instance** — the object whose\nmethod contains the lambda — *not* to the functional-interface object the lambda\nbecomes. This is because a lambda does **not** create a new scope; it's\nlexically part of its surrounding method.\n\n```java\nclass Widget {\n  String name = \"panel\";\n  Runnable make() {\n    return () -> System.out.println(this.name); \u002F\u002F \"panel\" — Widget's this\n  }\n}\n```\n\nContrast with an anonymous class, where `this` is the anonymous object itself, so\naccessing the outer instance needs `Widget.this`. This lexical-`this` behavior\nmakes lambdas more intuitive for capturing enclosing state, and is a frequent\ninterview discriminator between the two.\n",21,null,{"description":11},"Java lambdas interview questions — lambda syntax, functional interfaces, the java.util.function package, method references, effectively final capture, and @FunctionalInterface.","java\u002Fstreams-functional\u002Flambdas-functional-interfaces","Lambdas & Functional Interfaces","Streams & Functional","streams-functional","2026-06-20","D3Nqup9i8dd4bJPaz03ykKMLDyiKfRtLrhT87UWh9iQ",[120,121,124,128],{"subtopic":114,"path":21,"order":20},{"subtopic":122,"path":123,"order":12},"Stream API","\u002Fjava\u002Fstreams-functional\u002Fstreams-api",{"subtopic":125,"path":126,"order":127},"Collectors & Grouping","\u002Fjava\u002Fstreams-functional\u002Fcollectors-grouping",3,{"subtopic":129,"path":130,"order":131},"Optional","\u002Fjava\u002Fstreams-functional\u002Foptional",4,{"path":133,"title":134},"\u002Fblog\u002Fjava-lambdas-functional-interfaces","Java Lambdas & Functional Interfaces — A Practical Guide",1782244116310]