Functional Programming
Method References
Shorthand for Lambdas
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.
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);
}
}
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') = 42private static int parseIntSafe(String s)
6private static int parseIntSafe(String s 7 ) {7 return Integer.parseInt(s.trim());8}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]
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') = 7private static int parseIntSafe(String s)
6private static int parseIntSafe(String s 7 ) {7 return Integer.parseInt(s.trim());8}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]
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') = 100private static int parseIntSafe(String s)
6private static int parseIntSafe(String s 7 ) {7 return Integer.parseInt(s.trim());8}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).
Instance method reference
Reference an instance method.
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() + "'");
}
}
prefix ← Hello,
17public static void main(String[] args) {18 String prefix→ Hello, = "Hello, "; //@prefix="Hello, ", "Hi, ", "Welcome, "19 Prefixer p = new Prefixer(prefix);this.prefix ← Hello,
8Prefixer(String prefixHello, ) {9 this.prefix→ Hello, = prefixHello, ;10}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"));String addPrefix(String s)
pass 1 of 212String addPrefix(String sAlice) {13 return prefixHello, + sAlice;14}System.out.println(f1.apply("Alice"));
24System.out.println(f1.apply("Alice"));25System.out.println(f2.apply("Bob"));outputHello, AliceString addPrefix(String s)
pass 2 of 212String addPrefix(String sBob) {13 return prefixHello, + sBob;14}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'
prefix ← Hi,
17public static void main(String[] args) {18 String prefix→ Hi, = "Hi, ";19 Prefixer p = new Prefixer(prefix);this.prefix ← Hi,
8Prefixer(String prefixHi, ) {9 this.prefix→ Hi, = prefixHi, ;10}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"));String addPrefix(String s)
pass 1 of 212String addPrefix(String sAlice) {13 return prefixHi, + sAlice;14}System.out.println(f1.apply("Alice"));
24System.out.println(f1.apply("Alice"));25System.out.println(f2.apply("Bob"));outputHi, AliceString addPrefix(String s)
pass 2 of 212String addPrefix(String sBob) {13 return prefixHi, + sBob;14}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'
prefix ← Welcome,
17public static void main(String[] args) {18 String prefix→ Welcome, = "Welcome, ";19 Prefixer p = new Prefixer(prefix);this.prefix ← Welcome,
8Prefixer(String prefixWelcome, ) {9 this.prefix→ Welcome, = prefixWelcome, ;10}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"));String addPrefix(String s)
pass 1 of 212String addPrefix(String sAlice) {13 return prefixWelcome, + sAlice;14}System.out.println(f1.apply("Alice"));
24System.out.println(f1.apply("Alice"));25System.out.println(f2.apply("Bob"));outputWelcome, AliceString addPrefix(String s)
pass 2 of 212String addPrefix(String sBob) {13 return prefixWelcome, + sBob;14}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.
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);
}
}
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]
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]
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.
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);
}
}
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"));this.name ← Alice
pass 1 of 29User(String nameAlice) {10 this.name→ Alice = nameAlice;11}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)this.name ← Bob
pass 2 of 29User(String nameBob) {10 this.name→ Bob = nameBob;11}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}
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"));this.name ← Bob
pass 1 of 29User(String nameBob) {10 this.name→ Bob = nameBob;11}System.out.println(makeUser1.apply(userName));
23String userName = "Bob";24System.out.println(makeUser1.apply(userNameBob));25System.out.println(makeUser2.apply("Bob"));outputUser(Bob)this.name ← Bob
pass 2 of 29User(String nameBob) {10 this.name→ Bob = nameBob;11}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}
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"));this.name ← Charlie
pass 1 of 29User(String nameCharlie) {10 this.name→ Charlie = nameCharlie;11}System.out.println(makeUser1.apply(userName));
23String userName = "Charlie";24System.out.println(makeUser1.apply(userNameCharlie));25System.out.println(makeUser2.apply("Bob"));outputUser(Charlie)this.name ← Bob
pass 2 of 29User(String nameBob) {10 this.name→ Bob = nameBob;11}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).
Method references with collections
Common patterns in collection operations.
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);
}
}
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);out ← []
pass 1 of 212private 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) {for (T item : items)
pass 1 of 613List<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 pass itemitems1 Alice [ Alice , Bob, CHARLIE ] 2 Bob [ Alice , Bob, CHARLIE ] 3 CHARLIE [ Alice , Bob, CHARLIE ] 4 Alice [Alice, Bob, CHARLIE] 5 Bob [Alice, Bob, CHARLIE] 6 CHARLIE [Alice, Bob, CHARLIE] return out;
16 }17 return out[Alice, Bob, CHARLIE];18}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]out ← []
pass 2 of 212private 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) {return out;
16 }17 return out[alice, bob, charlie];18}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]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) {for (T item : items)
pass 1 of 36private 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 pass item1 alice 2 bob 3 charlie 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