Your lambda is just x -> x.toString(). Method reference Object::toString is cleaner. When lambda only calls an existing method, use method reference instead. Same result, more readable.

Static method reference

Reference a static method.

numericInput
Static.java
Replay: real traced execution (multi-file project)
import java.util.*;
import java.util.function.*;

public class Static {

    private static int parseIntSafe(String s) {
        return Integer.parseInt(s.trim());
    }

    public static void main(String[] args) {
        Function<String, Integer> a = s -> Integer.parseInt(s);
        Function<String, Integer> b = Integer::parseInt;

        String numericInput = "42";
        System.out.println("a('" + numericInput + "') = " + a.apply(numericInput));
        System.out.println("b('" + numericInput + "') = " + b.apply(numericInput));

        Function<String, Integer> safe = Static::parseIntSafe;
        System.out.println("safe(' 7 ') = " + safe.apply(" 7 "));

        List<String> nums = new ArrayList<>(Arrays.asList("10", "2", "30"));
        nums.sort(Comparator.comparingInt(Integer::parseInt));
        System.out.println("sorted numeric strings: " + nums);

    }
}
import java.util.*;
import java.util.function.*;

public class Static {

    private static int parseIntSafe(String s) {
        return Integer.parseInt(s.trim());
    }

    public static void main(String[] args) {
        Function<String, Integer> a = s -> Integer.parseInt(s);
        Function<String, Integer> b = Integer::parseInt;

        String numericInput = "007";
        System.out.println("a('" + numericInput + "') = " + a.apply(numericInput));
        System.out.println("b('" + numericInput + "') = " + b.apply(numericInput));

        Function<String, Integer> safe = Static::parseIntSafe;
        System.out.println("safe(' 7 ') = " + safe.apply(" 7 "));

        List<String> nums = new ArrayList<>(Arrays.asList("10", "2", "30"));
        nums.sort(Comparator.comparingInt(Integer::parseInt));
        System.out.println("sorted numeric strings: " + nums);

    }
}
import java.util.*;
import java.util.function.*;

public class Static {

    private static int parseIntSafe(String s) {
        return Integer.parseInt(s.trim());
    }

    public static void main(String[] args) {
        Function<String, Integer> a = s -> Integer.parseInt(s);
        Function<String, Integer> b = Integer::parseInt;

        String numericInput = "100";
        System.out.println("a('" + numericInput + "') = " + a.apply(numericInput));
        System.out.println("b('" + numericInput + "') = " + b.apply(numericInput));

        Function<String, Integer> safe = Static::parseIntSafe;
        System.out.println("safe(' 7 ') = " + safe.apply(" 7 "));

        List<String> nums = new ArrayList<>(Arrays.asList("10", "2", "30"));
        nums.sort(Comparator.comparingInt(Integer::parseInt));
        System.out.println("sorted numeric strings: " + nums);

    }
}
  1. a ← ⟨Static lambda A⟩, b ← ⟨Static lambda B⟩, numericInput ← 42

    10public static void main(String[] args) {11    Function<String, Integer> a→ ⟨Static lambda A⟩ = s -> Integer.parseInt(s);12    Function<String, Integer> b→ ⟨Static lambda B⟩ = Integer::parseInt;1314    String numericInput→ 42 = "42"; //@numericInput="42", "007", "100"15    System.out.println("a('" + numericInput42 + "') = " + a.apply(numericInput));16    System.out.println("b('" + numericInput42 + "') = " + b.apply(numericInput));1718    Function<String, Integer> safe→ ⟨Static lambda C⟩ = Static::parseIntSafe;19    System.out.println("safe(' 7 ') = " + safe.apply(" 7 "));
    outputa('42') = 42
    b('42') = 42
  2. private static int parseIntSafe(String s)

    6private static int parseIntSafe(String s 7 ) {7    return Integer.parseInt(s.trim());8}
  3. nums ← [10, 2, 30]

    18Function<String, Integer> safe = Static::parseIntSafe;19System.out.println("safe(' 7 ') = " + safe.apply(" 7 "));2021List<String> nums→ [10, 2, 30] = new ArrayList<>(Arrays.asList("10", "2", "30"));22nums.sort(Comparator.comparingInt(Integer::parseInt));23System.out.println("sorted numeric strings: " + nums[2, 10, 30]);
    outputsafe(' 7 ') = 7
    sorted numeric strings: [2, 10, 30]
  1. a ← ⟨Static lambda A⟩, b ← ⟨Static lambda B⟩, numericInput ← 007

    10public static void main(String[] args) {11    Function<String, Integer> a→ ⟨Static lambda A⟩ = s -> Integer.parseInt(s);12    Function<String, Integer> b→ ⟨Static lambda B⟩ = Integer::parseInt;1314    String numericInput→ 007 = "007";15    System.out.println("a('" + numericInput007 + "') = " + a.apply(numericInput));16    System.out.println("b('" + numericInput007 + "') = " + b.apply(numericInput));1718    Function<String, Integer> safe→ ⟨Static lambda C⟩ = Static::parseIntSafe;19    System.out.println("safe(' 7 ') = " + safe.apply(" 7 "));
    outputa('007') = 7
    b('007') = 7
  2. private static int parseIntSafe(String s)

    6private static int parseIntSafe(String s 7 ) {7    return Integer.parseInt(s.trim());8}
  3. nums ← [10, 2, 30]

    18Function<String, Integer> safe = Static::parseIntSafe;19System.out.println("safe(' 7 ') = " + safe.apply(" 7 "));2021List<String> nums→ [10, 2, 30] = new ArrayList<>(Arrays.asList("10", "2", "30"));22nums.sort(Comparator.comparingInt(Integer::parseInt));23System.out.println("sorted numeric strings: " + nums[2, 10, 30]);
    outputsafe(' 7 ') = 7
    sorted numeric strings: [2, 10, 30]
  1. a ← ⟨Static lambda A⟩, b ← ⟨Static lambda B⟩, numericInput ← 100

    10public static void main(String[] args) {11    Function<String, Integer> a→ ⟨Static lambda A⟩ = s -> Integer.parseInt(s);12    Function<String, Integer> b→ ⟨Static lambda B⟩ = Integer::parseInt;1314    String numericInput→ 100 = "100";15    System.out.println("a('" + numericInput100 + "') = " + a.apply(numericInput));16    System.out.println("b('" + numericInput100 + "') = " + b.apply(numericInput));1718    Function<String, Integer> safe→ ⟨Static lambda C⟩ = Static::parseIntSafe;19    System.out.println("safe(' 7 ') = " + safe.apply(" 7 "));
    outputa('100') = 100
    b('100') = 100
  2. private static int parseIntSafe(String s)

    6private static int parseIntSafe(String s 7 ) {7    return Integer.parseInt(s.trim());8}
  3. nums ← [10, 2, 30]

    18Function<String, Integer> safe = Static::parseIntSafe;19System.out.println("safe(' 7 ') = " + safe.apply(" 7 "));2021List<String> nums→ [10, 2, 30] = new ArrayList<>(Arrays.asList("10", "2", "30"));22nums.sort(Comparator.comparingInt(Integer::parseInt));23System.out.println("sorted numeric strings: " + nums[2, 10, 30]);
    outputsafe(' 7 ') = 7
    sorted numeric strings: [2, 10, 30]

ClassName::staticMethod - equivalent to x -> ClassName.staticMethod(x).

method reference Shorthand for lambdas: `String::valueOf` instead of `x -> String.valueOf(x)`.

Instance method reference

Reference an instance method.

prefix
Instance.java
Replay: real traced execution (multi-file project)
import java.util.function.*;

public class Instance {

    static class Prefixer {
        private final String prefix;

        Prefixer(String prefix) {
            this.prefix = prefix;
        }

        String addPrefix(String s) {
            return prefix + s;
        }
    }

    public static void main(String[] args) {
        String prefix = "Hello, ";
        Prefixer p = new Prefixer(prefix);

        Function<String, String> f1 = s -> p.addPrefix(s);
        Function<String, String> f2 = p::addPrefix;

        System.out.println(f1.apply("Alice"));
        System.out.println(f2.apply("Bob"));

        Supplier<String> supplier1 = () -> "  hi  ".trim();
        Supplier<String> supplier2 = "  hi  "::trim;

        System.out.println("supplier1 = '" + supplier1.get() + "'");
        System.out.println("supplier2 = '" + supplier2.get() + "'");

    }
}
import java.util.function.*;

public class Instance {

    static class Prefixer {
        private final String prefix;

        Prefixer(String prefix) {
            this.prefix = prefix;
        }

        String addPrefix(String s) {
            return prefix + s;
        }
    }

    public static void main(String[] args) {
        String prefix = "Hi, ";
        Prefixer p = new Prefixer(prefix);

        Function<String, String> f1 = s -> p.addPrefix(s);
        Function<String, String> f2 = p::addPrefix;

        System.out.println(f1.apply("Alice"));
        System.out.println(f2.apply("Bob"));

        Supplier<String> supplier1 = () -> "  hi  ".trim();
        Supplier<String> supplier2 = "  hi  "::trim;

        System.out.println("supplier1 = '" + supplier1.get() + "'");
        System.out.println("supplier2 = '" + supplier2.get() + "'");

    }
}
import java.util.function.*;

public class Instance {

    static class Prefixer {
        private final String prefix;

        Prefixer(String prefix) {
            this.prefix = prefix;
        }

        String addPrefix(String s) {
            return prefix + s;
        }
    }

    public static void main(String[] args) {
        String prefix = "Welcome, ";
        Prefixer p = new Prefixer(prefix);

        Function<String, String> f1 = s -> p.addPrefix(s);
        Function<String, String> f2 = p::addPrefix;

        System.out.println(f1.apply("Alice"));
        System.out.println(f2.apply("Bob"));

        Supplier<String> supplier1 = () -> "  hi  ".trim();
        Supplier<String> supplier2 = "  hi  "::trim;

        System.out.println("supplier1 = '" + supplier1.get() + "'");
        System.out.println("supplier2 = '" + supplier2.get() + "'");

    }
}
  1. prefix ← Hello,

    17public static void main(String[] args) {18    String prefix→ Hello,  = "Hello, "; //@prefix="Hello, ", "Hi, ", "Welcome, "19    Prefixer p = new Prefixer(prefix);
  2. this.prefix ← Hello,

    8Prefixer(String prefixHello, ) {9    this.prefix→ Hello,  = prefixHello, ;10}
  3. p ← ⟨Instance$Prefixer A⟩, f1 ← ⟨Instance lambda B⟩, f2 ← ⟨Instance lambda C⟩

    18String prefix = "Hello, "; //@prefix="Hello, ", "Hi, ", "Welcome, "19Prefixer p→ ⟨Instance$Prefixer A⟩ = new Prefixer(prefix);2021Function<String, String> f1→ ⟨Instance lambda B⟩ = s -> p.addPrefix(s);22Function<String, String> f2→ ⟨Instance lambda C⟩ = p::addPrefix;2324System.out.println(f1.apply("Alice"));25System.out.println(f2.apply("Bob"));
  4. String addPrefix(String s)

    pass 1 of 2
    12String addPrefix(String sAlice) {13    return prefixHello,  + sAlice;14}
  5. System.out.println(f1.apply("Alice"));

    24System.out.println(f1.apply("Alice"));25System.out.println(f2.apply("Bob"));
    outputHello, Alice
  6. String addPrefix(String s)

    pass 2 of 2
    12String addPrefix(String sBob) {13    return prefixHello,  + sBob;14}
  7. supplier1 ← ⟨Instance lambda D⟩, supplier2 ← ⟨Instance lambda E⟩

    24System.out.println(f1.apply("Alice"));25System.out.println(f2.apply("Bob"));2627Supplier<String> supplier1→ ⟨Instance lambda D⟩ = () -> "  hi  ".trim();28Supplier<String> supplier2→ ⟨Instance lambda E⟩ = "  hi  "::trim;2930System.out.println("supplier1 = '" + supplier1.get() + "'");31System.out.println("supplier2 = '" + supplier2.get() + "'");
    outputHello, Bob
    supplier1 = 'hi'
    supplier2 = 'hi'
  1. prefix ← Hi,

    17public static void main(String[] args) {18    String prefix→ Hi,  = "Hi, ";19    Prefixer p = new Prefixer(prefix);
  2. this.prefix ← Hi,

    8Prefixer(String prefixHi, ) {9    this.prefix→ Hi,  = prefixHi, ;10}
  3. p ← ⟨Instance$Prefixer A⟩, f1 ← ⟨Instance lambda B⟩, f2 ← ⟨Instance lambda C⟩

    18String prefix = "Hi, ";19Prefixer p→ ⟨Instance$Prefixer A⟩ = new Prefixer(prefix);2021Function<String, String> f1→ ⟨Instance lambda B⟩ = s -> p.addPrefix(s);22Function<String, String> f2→ ⟨Instance lambda C⟩ = p::addPrefix;2324System.out.println(f1.apply("Alice"));25System.out.println(f2.apply("Bob"));
  4. String addPrefix(String s)

    pass 1 of 2
    12String addPrefix(String sAlice) {13    return prefixHi,  + sAlice;14}
  5. System.out.println(f1.apply("Alice"));

    24System.out.println(f1.apply("Alice"));25System.out.println(f2.apply("Bob"));
    outputHi, Alice
  6. String addPrefix(String s)

    pass 2 of 2
    12String addPrefix(String sBob) {13    return prefixHi,  + sBob;14}
  7. supplier1 ← ⟨Instance lambda D⟩, supplier2 ← ⟨Instance lambda E⟩

    24System.out.println(f1.apply("Alice"));25System.out.println(f2.apply("Bob"));2627Supplier<String> supplier1→ ⟨Instance lambda D⟩ = () -> "  hi  ".trim();28Supplier<String> supplier2→ ⟨Instance lambda E⟩ = "  hi  "::trim;2930System.out.println("supplier1 = '" + supplier1.get() + "'");31System.out.println("supplier2 = '" + supplier2.get() + "'");
    outputHi, Bob
    supplier1 = 'hi'
    supplier2 = 'hi'
  1. prefix ← Welcome,

    17public static void main(String[] args) {18    String prefix→ Welcome,  = "Welcome, ";19    Prefixer p = new Prefixer(prefix);
  2. this.prefix ← Welcome,

    8Prefixer(String prefixWelcome, ) {9    this.prefix→ Welcome,  = prefixWelcome, ;10}
  3. p ← ⟨Instance$Prefixer A⟩, f1 ← ⟨Instance lambda B⟩, f2 ← ⟨Instance lambda C⟩

    18String prefix = "Welcome, ";19Prefixer p→ ⟨Instance$Prefixer A⟩ = new Prefixer(prefix);2021Function<String, String> f1→ ⟨Instance lambda B⟩ = s -> p.addPrefix(s);22Function<String, String> f2→ ⟨Instance lambda C⟩ = p::addPrefix;2324System.out.println(f1.apply("Alice"));25System.out.println(f2.apply("Bob"));
  4. String addPrefix(String s)

    pass 1 of 2
    12String addPrefix(String sAlice) {13    return prefixWelcome,  + sAlice;14}
  5. System.out.println(f1.apply("Alice"));

    24System.out.println(f1.apply("Alice"));25System.out.println(f2.apply("Bob"));
    outputWelcome, Alice
  6. String addPrefix(String s)

    pass 2 of 2
    12String addPrefix(String sBob) {13    return prefixWelcome,  + sBob;14}
  7. supplier1 ← ⟨Instance lambda D⟩, supplier2 ← ⟨Instance lambda E⟩

    24System.out.println(f1.apply("Alice"));25System.out.println(f2.apply("Bob"));2627Supplier<String> supplier1→ ⟨Instance lambda D⟩ = () -> "  hi  ".trim();28Supplier<String> supplier2→ ⟨Instance lambda E⟩ = "  hi  "::trim;2930System.out.println("supplier1 = '" + supplier1.get() + "'");31System.out.println("supplier2 = '" + supplier2.get() + "'");
    outputWelcome, Bob
    supplier1 = 'hi'
    supplier2 = 'hi'

object::method - equivalent to x -> object.method(x).

Unbound instance method

Reference method on parameter object.

prefixToCheck
Unbound.java
Replay: real traced execution (multi-file project)
import java.util.*;
import java.util.function.*;

public class Unbound {
    public static void main(String[] args) {
        BiFunction<String, String, Boolean> startsWith1 = (s, prefix) -> s.startsWith(prefix);
        BiFunction<String, String, Boolean> startsWith2 = String::startsWith;

        String prefixToCheck = "A";
        System.out.println("startsWith2('Alice','" + prefixToCheck + "') = " +
                           startsWith2.apply("Alice", prefixToCheck));
        System.out.println("startsWith2('Bob','" + prefixToCheck + "') = " +
                           startsWith2.apply("Bob", prefixToCheck));

        List<String> names = new ArrayList<>(Arrays.asList("Charlie", "alice", "Bob"));
        names.sort(String::compareToIgnoreCase);
        System.out.println("sorted ignore-case: " + names);

        List<String> raw = Arrays.asList("  a ", " b", "c  ");
        List<String> trimmed = new ArrayList<>();
        raw.forEach(s -> trimmed.add(s.trim()));
        System.out.println("trimmed via lambda: " + trimmed);

        trimmed.clear();
        raw.forEach(s -> trimmed.add(s.trim()));
        System.out.println("trimmed again: " + trimmed);

    }
}
import java.util.*;
import java.util.function.*;

public class Unbound {
    public static void main(String[] args) {
        BiFunction<String, String, Boolean> startsWith1 = (s, prefix) -> s.startsWith(prefix);
        BiFunction<String, String, Boolean> startsWith2 = String::startsWith;

        String prefixToCheck = "B";
        System.out.println("startsWith2('Alice','" + prefixToCheck + "') = " +
                           startsWith2.apply("Alice", prefixToCheck));
        System.out.println("startsWith2('Bob','" + prefixToCheck + "') = " +
                           startsWith2.apply("Bob", prefixToCheck));

        List<String> names = new ArrayList<>(Arrays.asList("Charlie", "alice", "Bob"));
        names.sort(String::compareToIgnoreCase);
        System.out.println("sorted ignore-case: " + names);

        List<String> raw = Arrays.asList("  a ", " b", "c  ");
        List<String> trimmed = new ArrayList<>();
        raw.forEach(s -> trimmed.add(s.trim()));
        System.out.println("trimmed via lambda: " + trimmed);

        trimmed.clear();
        raw.forEach(s -> trimmed.add(s.trim()));
        System.out.println("trimmed again: " + trimmed);

    }
}
import java.util.*;
import java.util.function.*;

public class Unbound {
    public static void main(String[] args) {
        BiFunction<String, String, Boolean> startsWith1 = (s, prefix) -> s.startsWith(prefix);
        BiFunction<String, String, Boolean> startsWith2 = String::startsWith;

        String prefixToCheck = "Ch";
        System.out.println("startsWith2('Alice','" + prefixToCheck + "') = " +
                           startsWith2.apply("Alice", prefixToCheck));
        System.out.println("startsWith2('Bob','" + prefixToCheck + "') = " +
                           startsWith2.apply("Bob", prefixToCheck));

        List<String> names = new ArrayList<>(Arrays.asList("Charlie", "alice", "Bob"));
        names.sort(String::compareToIgnoreCase);
        System.out.println("sorted ignore-case: " + names);

        List<String> raw = Arrays.asList("  a ", " b", "c  ");
        List<String> trimmed = new ArrayList<>();
        raw.forEach(s -> trimmed.add(s.trim()));
        System.out.println("trimmed via lambda: " + trimmed);

        trimmed.clear();
        raw.forEach(s -> trimmed.add(s.trim()));
        System.out.println("trimmed again: " + trimmed);

    }
}
  1. startsWith1 ← ⟨Unbound lambda A⟩, startsWith2 ← ⟨Unbound lambda B⟩

    4public class Unbound {5    public static void main(String[] args) {6        BiFunction<String, String, Boolean> startsWith1→ ⟨Unbound lambda A⟩ = (s, prefix) -> s.startsWith(prefix);7        BiFunction<String, String, Boolean> startsWith2→ ⟨Unbound lambda B⟩ = String::startsWith;89        String prefixToCheck→ A = "A"; //@prefixToCheck="A", "B", "Ch"10        System.out.println("startsWith2('Alice','" + prefixToCheckA + "') = " +11                           startsWith2.apply("Alice", prefixToCheckA));12        System.out.println("startsWith2('Bob','" + prefixToCheckA + "') = " +13                           startsWith2.apply("Bob", prefixToCheckA));1415        List<String> names→ [Charlie, alice, Bob] = new ArrayList<>(Arrays.asList("Charlie", "alice", "Bob"));16        names.sort(String::compareToIgnoreCase);17        System.out.println("sorted ignore-case: " + names[alice, Bob, Charlie]);1819        List<String> raw→ [  a ,  b, c  ] = Arrays.asList("  a ", " b", "c  ");20        List<String> trimmed→ [] = new ArrayList<>();21        raw.forEach(s -> trimmed.add(s.trim()));22        System.out.println("trimmed via lambda: " + trimmed[a, b, c]);2324        trimmed.clear();25        raw.forEach(s -> trimmed.add(s.trim()));26        System.out.println("trimmed again: " + trimmed[a, b, c]);
    outputstartsWith2('Alice','A') = true
    startsWith2('Bob','A') = false
    sorted ignore-case: [alice, Bob, Charlie]
    trimmed via lambda: [a, b, c]
    trimmed again: [a, b, c]
  1. startsWith1 ← ⟨Unbound lambda A⟩, startsWith2 ← ⟨Unbound lambda B⟩

    4public class Unbound {5    public static void main(String[] args) {6        BiFunction<String, String, Boolean> startsWith1→ ⟨Unbound lambda A⟩ = (s, prefix) -> s.startsWith(prefix);7        BiFunction<String, String, Boolean> startsWith2→ ⟨Unbound lambda B⟩ = String::startsWith;89        String prefixToCheck→ B = "B";10        System.out.println("startsWith2('Alice','" + prefixToCheckB + "') = " +11                           startsWith2.apply("Alice", prefixToCheckB));12        System.out.println("startsWith2('Bob','" + prefixToCheckB + "') = " +13                           startsWith2.apply("Bob", prefixToCheckB));1415        List<String> names→ [Charlie, alice, Bob] = new ArrayList<>(Arrays.asList("Charlie", "alice", "Bob"));16        names.sort(String::compareToIgnoreCase);17        System.out.println("sorted ignore-case: " + names[alice, Bob, Charlie]);1819        List<String> raw→ [  a ,  b, c  ] = Arrays.asList("  a ", " b", "c  ");20        List<String> trimmed→ [] = new ArrayList<>();21        raw.forEach(s -> trimmed.add(s.trim()));22        System.out.println("trimmed via lambda: " + trimmed[a, b, c]);2324        trimmed.clear();25        raw.forEach(s -> trimmed.add(s.trim()));26        System.out.println("trimmed again: " + trimmed[a, b, c]);
    outputstartsWith2('Alice','B') = false
    startsWith2('Bob','B') = true
    sorted ignore-case: [alice, Bob, Charlie]
    trimmed via lambda: [a, b, c]
    trimmed again: [a, b, c]
  1. startsWith1 ← ⟨Unbound lambda A⟩, startsWith2 ← ⟨Unbound lambda B⟩

    4public class Unbound {5    public static void main(String[] args) {6        BiFunction<String, String, Boolean> startsWith1→ ⟨Unbound lambda A⟩ = (s, prefix) -> s.startsWith(prefix);7        BiFunction<String, String, Boolean> startsWith2→ ⟨Unbound lambda B⟩ = String::startsWith;89        String prefixToCheck→ Ch = "Ch";10        System.out.println("startsWith2('Alice','" + prefixToCheckCh + "') = " +11                           startsWith2.apply("Alice", prefixToCheckCh));12        System.out.println("startsWith2('Bob','" + prefixToCheckCh + "') = " +13                           startsWith2.apply("Bob", prefixToCheckCh));1415        List<String> names→ [Charlie, alice, Bob] = new ArrayList<>(Arrays.asList("Charlie", "alice", "Bob"));16        names.sort(String::compareToIgnoreCase);17        System.out.println("sorted ignore-case: " + names[alice, Bob, Charlie]);1819        List<String> raw→ [  a ,  b, c  ] = Arrays.asList("  a ", " b", "c  ");20        List<String> trimmed→ [] = new ArrayList<>();21        raw.forEach(s -> trimmed.add(s.trim()));22        System.out.println("trimmed via lambda: " + trimmed[a, b, c]);2324        trimmed.clear();25        raw.forEach(s -> trimmed.add(s.trim()));26        System.out.println("trimmed again: " + trimmed[a, b, c]);
    outputstartsWith2('Alice','Ch') = false
    startsWith2('Bob','Ch') = false
    sorted ignore-case: [alice, Bob, Charlie]
    trimmed via lambda: [a, b, c]
    trimmed again: [a, b, c]

String::length - equivalent to s -> s.length(). First param becomes receiver.

Constructor reference

Reference a constructor.

userName
Constructor.java
Replay: real traced execution (multi-file project)
import java.util.*;
import java.util.function.*;

public class Constructor {

    static class User {
        final String name;

        User(String name) {
            this.name = name;
        }

        @Override
        public String toString() {
            return "User(" + name + ")";
        }
    }

    public static void main(String[] args) {
        Function<String, User> makeUser1 = name -> new User(name);
        Function<String, User> makeUser2 = User::new;

        String userName = "Alice";
        System.out.println(makeUser1.apply(userName));
        System.out.println(makeUser2.apply("Bob"));

        Supplier<List<String>> listSupplier = ArrayList::new;
        List<String> list = listSupplier.get();
        list.add("x");
        list.add("y");
        System.out.println("list: " + list);

        Supplier<Map<String, Integer>> mapSupplier = LinkedHashMap::new;
        Map<String, Integer> map = mapSupplier.get();
        map.put("a", 1);
        System.out.println("map: " + map);

    }
}
import java.util.*;
import java.util.function.*;

public class Constructor {

    static class User {
        final String name;

        User(String name) {
            this.name = name;
        }

        @Override
        public String toString() {
            return "User(" + name + ")";
        }
    }

    public static void main(String[] args) {
        Function<String, User> makeUser1 = name -> new User(name);
        Function<String, User> makeUser2 = User::new;

        String userName = "Bob";
        System.out.println(makeUser1.apply(userName));
        System.out.println(makeUser2.apply("Bob"));

        Supplier<List<String>> listSupplier = ArrayList::new;
        List<String> list = listSupplier.get();
        list.add("x");
        list.add("y");
        System.out.println("list: " + list);

        Supplier<Map<String, Integer>> mapSupplier = LinkedHashMap::new;
        Map<String, Integer> map = mapSupplier.get();
        map.put("a", 1);
        System.out.println("map: " + map);

    }
}
import java.util.*;
import java.util.function.*;

public class Constructor {

    static class User {
        final String name;

        User(String name) {
            this.name = name;
        }

        @Override
        public String toString() {
            return "User(" + name + ")";
        }
    }

    public static void main(String[] args) {
        Function<String, User> makeUser1 = name -> new User(name);
        Function<String, User> makeUser2 = User::new;

        String userName = "Charlie";
        System.out.println(makeUser1.apply(userName));
        System.out.println(makeUser2.apply("Bob"));

        Supplier<List<String>> listSupplier = ArrayList::new;
        List<String> list = listSupplier.get();
        list.add("x");
        list.add("y");
        System.out.println("list: " + list);

        Supplier<Map<String, Integer>> mapSupplier = LinkedHashMap::new;
        Map<String, Integer> map = mapSupplier.get();
        map.put("a", 1);
        System.out.println("map: " + map);

    }
}
  1. makeUser1 ← ⟨Constructor lambda A⟩, makeUser2 ← ⟨Constructor lambda B⟩

    19public static void main(String[] args) {20    Function<String, User> makeUser1→ ⟨Constructor lambda A⟩ = name -> new User(name);21    Function<String, User> makeUser2→ ⟨Constructor lambda B⟩ = User::new;2223    String userName→ Alice = "Alice"; //@userName="Alice", "Bob", "Charlie"24    System.out.println(makeUser1.apply(userNameAlice));25    System.out.println(makeUser2.apply("Bob"));
  2. this.name ← Alice

    pass 1 of 2
    9User(String nameAlice) {10    this.name→ Alice = nameAlice;11}
  3. System.out.println(makeUser1.apply(userName));

    23String userName = "Alice"; //@userName="Alice", "Bob", "Charlie"24System.out.println(makeUser1.apply(userNameAlice));25System.out.println(makeUser2.apply("Bob"));
    outputUser(Alice)
  4. this.name ← Bob

    pass 2 of 2
    9User(String nameBob) {10    this.name→ Bob = nameBob;11}
  5. listSupplier ← ⟨Constructor lambda C⟩, list ← [], mapSupplier ← ⟨Constructor lambda D⟩

    24System.out.println(makeUser1.apply(userName));25System.out.println(makeUser2.apply("Bob"));2627Supplier<List<String>> listSupplier→ ⟨Constructor lambda C⟩ = ArrayList::new;28List<String> list→ [] = listSupplier.get();29list.add("x");30list.add("y");31System.out.println("list: " + list[x, y]);3233Supplier<Map<String, Integer>> mapSupplier→ ⟨Constructor lambda D⟩ = LinkedHashMap::new;34Map<String, Integer> map→ {} = mapSupplier.get();35map.put("a", 1);36System.out.println("map: " + map{a=1});
    outputUser(Bob)
    list: [x, y]
    map: {a=1}
  1. makeUser1 ← ⟨Constructor lambda A⟩, makeUser2 ← ⟨Constructor lambda B⟩

    19public static void main(String[] args) {20    Function<String, User> makeUser1→ ⟨Constructor lambda A⟩ = name -> new User(name);21    Function<String, User> makeUser2→ ⟨Constructor lambda B⟩ = User::new;2223    String userName→ Bob = "Bob";24    System.out.println(makeUser1.apply(userNameBob));25    System.out.println(makeUser2.apply("Bob"));
  2. this.name ← Bob

    pass 1 of 2
    9User(String nameBob) {10    this.name→ Bob = nameBob;11}
  3. System.out.println(makeUser1.apply(userName));

    23String userName = "Bob";24System.out.println(makeUser1.apply(userNameBob));25System.out.println(makeUser2.apply("Bob"));
    outputUser(Bob)
  4. this.name ← Bob

    pass 2 of 2
    9User(String nameBob) {10    this.name→ Bob = nameBob;11}
  5. listSupplier ← ⟨Constructor lambda C⟩, list ← [], mapSupplier ← ⟨Constructor lambda D⟩

    24System.out.println(makeUser1.apply(userName));25System.out.println(makeUser2.apply("Bob"));2627Supplier<List<String>> listSupplier→ ⟨Constructor lambda C⟩ = ArrayList::new;28List<String> list→ [] = listSupplier.get();29list.add("x");30list.add("y");31System.out.println("list: " + list[x, y]);3233Supplier<Map<String, Integer>> mapSupplier→ ⟨Constructor lambda D⟩ = LinkedHashMap::new;34Map<String, Integer> map→ {} = mapSupplier.get();35map.put("a", 1);36System.out.println("map: " + map{a=1});
    outputUser(Bob)
    list: [x, y]
    map: {a=1}
  1. makeUser1 ← ⟨Constructor lambda A⟩, makeUser2 ← ⟨Constructor lambda B⟩

    19public static void main(String[] args) {20    Function<String, User> makeUser1→ ⟨Constructor lambda A⟩ = name -> new User(name);21    Function<String, User> makeUser2→ ⟨Constructor lambda B⟩ = User::new;2223    String userName→ Charlie = "Charlie";24    System.out.println(makeUser1.apply(userNameCharlie));25    System.out.println(makeUser2.apply("Bob"));
  2. this.name ← Charlie

    pass 1 of 2
    9User(String nameCharlie) {10    this.name→ Charlie = nameCharlie;11}
  3. System.out.println(makeUser1.apply(userName));

    23String userName = "Charlie";24System.out.println(makeUser1.apply(userNameCharlie));25System.out.println(makeUser2.apply("Bob"));
    outputUser(Charlie)
  4. this.name ← Bob

    pass 2 of 2
    9User(String nameBob) {10    this.name→ Bob = nameBob;11}
  5. listSupplier ← ⟨Constructor lambda C⟩, list ← [], mapSupplier ← ⟨Constructor lambda D⟩

    24System.out.println(makeUser1.apply(userName));25System.out.println(makeUser2.apply("Bob"));2627Supplier<List<String>> listSupplier→ ⟨Constructor lambda C⟩ = ArrayList::new;28List<String> list→ [] = listSupplier.get();29list.add("x");30list.add("y");31System.out.println("list: " + list[x, y]);3233Supplier<Map<String, Integer>> mapSupplier→ ⟨Constructor lambda D⟩ = LinkedHashMap::new;34Map<String, Integer> map→ {} = mapSupplier.get();35map.put("a", 1);36System.out.println("map: " + map{a=1});
    outputUser(Bob)
    list: [x, y]
    map: {a=1}

ClassName::new - equivalent to () -> new ClassName() or x -> new ClassName(x).

constructor reference `ArrayList::new` creates new ArrayList. Used with `Supplier` or `Function`.

Method references with collections

Common patterns in collection operations.

Collections.java
Replay: real traced execution (multi-file project)
import java.util.*;
import java.util.function.*;

public class Collections {

    private static <T> void forEach(List<T> items, Consumer<T> action) {
        for (T item : items) {
            action.accept(item);
        }
    }

    private static <T, R> List<R> map(List<T> items, Function<T, R> fn) {
        List<R> out = new ArrayList<>();
        for (T item : items) {
            out.add(fn.apply(item));
        }
        return out;
    }

    public static void main(String[] args) {
        List<String> raw = Arrays.asList("  Alice ", " Bob", "CHARLIE  ");

        List<String> trimmed = map(raw, String::trim);
        System.out.println("trimmed: " + trimmed);

        List<String> lowered = map(trimmed, String::toLowerCase);
        System.out.println("lowered: " + lowered);

        forEach(lowered, System.out::println);

        List<String> sorted = new ArrayList<>(lowered);
        sorted.sort(String::compareTo);
        System.out.println("sorted: " + sorted);

    }
}
  1. raw ← [ Alice , Bob, CHARLIE ]

    20public static void main(String[] args) {21    List<String> raw→ [  Alice ,  Bob, CHARLIE  ] = Arrays.asList("  Alice ", " Bob", "CHARLIE  ");2223    List<String> trimmed = map(raw[  Alice ,  Bob, CHARLIE  ], String::trim);24    System.out.println("trimmed: " + trimmed);
  2. out ← []

    pass 1 of 2
    12private static <T, R> List<R> map(List<T> items[  Alice ,  Bob, CHARLIE  ], Function<T, R> fn⟨Collections lambda A⟩) {13    List<R> out→ [] = new ArrayList<>();14    for (T item : items) {
  3. for (T item : items)

    pass 1 of 6
    13List<R> out = new ArrayList<>();14for (T item  Alice  : items[  Alice ,  Bob, CHARLIE  ]) {15    out.add(fn.apply(item  Alice ));16}
    All 6 passes — pass 1 is the card above
    passitemitems
    1 Alice [ Alice , Bob, CHARLIE ]
    2 Bob[ Alice , Bob, CHARLIE ]
    3CHARLIE [ Alice , Bob, CHARLIE ]
    4Alice[Alice, Bob, CHARLIE]
    5Bob[Alice, Bob, CHARLIE]
    6CHARLIE[Alice, Bob, CHARLIE]
  4. return out;

    16    }17    return out[Alice, Bob, CHARLIE];18}
  5. trimmed ← [Alice, Bob, CHARLIE]

    23List<String> trimmed→ [Alice, Bob, CHARLIE] = map(raw[  Alice ,  Bob, CHARLIE  ], String::trim);24System.out.println("trimmed: " + trimmed[Alice, Bob, CHARLIE]);2526List<String> lowered = map(trimmed[Alice, Bob, CHARLIE], String::toLowerCase);27System.out.println("lowered: " + lowered);
    outputtrimmed: [Alice, Bob, CHARLIE]
  6. out ← []

    pass 2 of 2
    12private static <T, R> List<R> map(List<T> items[Alice, Bob, CHARLIE], Function<T, R> fn⟨Collections lambda B⟩) {13    List<R> out→ [] = new ArrayList<>();14    for (T item : items) {
  7. return out;

    16    }17    return out[alice, bob, charlie];18}
  8. lowered ← [alice, bob, charlie]

    26List<String> lowered→ [alice, bob, charlie] = map(trimmed[Alice, Bob, CHARLIE], String::toLowerCase);27System.out.println("lowered: " + lowered[alice, bob, charlie]);2829forEach(lowered[alice, bob, charlie], System.out::println);
    outputlowered: [alice, bob, charlie]
  9. private static <T> void forEach(List<T> items, Consumer<T> action)

    6private static <T> void forEach(List<T> items[alice, bob, charlie], Consumer<T> action⟨Collections lambda C⟩) {7    for (T item : items) {
  10. for (T item : items)

    pass 1 of 3
    6private static <T> void forEach(List<T> items, Consumer<T> action) {7    for (T itemalice : items[alice, bob, charlie]) {8        action.accept(itemalice);9    }
    All 3 passes — pass 1 is the card above
    passitem
    1alice
    2bob
    3charlie
  11. sorted ← [alice, bob, charlie]

    29forEach(lowered[alice, bob, charlie], System.out::println);3031List<String> sorted→ [alice, bob, charlie] = new ArrayList<>(lowered);32sorted.sort(String::compareTo);33System.out.println("sorted: " + sorted[alice, bob, charlie]);
    outputsorted: [alice, bob, charlie]

list.forEach(System.out::println) - clean iteration with method reference.

Exercise: Practical.java

Refactor lambdas to method references