메서드 이름이 보다 읽기 쉽다면 -> 메서드 레퍼런스
매개변수 이름이 보다 읽기 쉽고 의미를 잘 표현한다면 -> 람다
메서드와 람다가 같은 클래스에 있을 때는 -> 람다
람다로 작성할 코드를 새로운 메서드로 담은 다음, 람다 대신 메서드 참조를 사용 하기.
// map.merge를 이용해 구현한 빈도표 - 람다 방식과 메서드 참조 방식을 비교해보자. (259쪽)
public class Freq {
public static void main(String[] args) {
args = new String[] {"hello", "keesun"};
Map<String, Integer> frequencyTable = new TreeMap<>();
for (String s : args)
// 값이 없으면 1 값이 있으면 +1 씩 증가하는 코드
**frequencyTable.merge(s, 1, (count, incr) -> sum(count, incr)); // 람다**
System.out.println(frequencyTable);
frequencyTable.clear();
for (String s : args)
**frequencyTable.merge(s, 1, Integer::sum); // 메서드 참조**
System.out.println(frequencyTable);
}
// 람다로 작성할 코드를 새로운 메서드로 담은 다음, 람다 대신 메서드 참조를 사용
**private static Integer sum(Integer count, Integer incr) {
return count + incr;
}**
}

정적 메서드 참조 예제
public class **StaticMethodReference** {
public static void main(String[] args) {
List<String> words = new ArrayList<>(Arrays.asList("aaa", "bbbbb", "c"));
System.out.println("Before sorting: " + words);
// 정적 메서드 참조
Collections.sort(words, **StaticMethodReference::compareByLength);**
System.out.println("After sorting: " + words);
}
public static int **compareByLength**(String s1, String s2) {
return Integer.compare(s1.length(), s2.length());
}
}
한정적인 메서드 참조 예제
public class BoundedMethodReference {
public static void main(String[] args) {
List<Instant> instants = new ArrayList<>();
instants.add(Instant.now().minusSeconds(10));
instants.add(Instant.now().plusSeconds(10));
instants.add(Instant.now().minusSeconds(20));
instants.add(Instant.now().plusSeconds(20));
**Instant now = Instant.now();**
// 한정적 메서드 참조
List<Instant> futureInstants = instants.stream()
**.filter(now::isAfter)**
// .filter(t -> now.isAfter(t))
.toList();
System.out.println("Future instants: " + futureInstants);
}
}
비한정적인 메서드 참조 예제
public class UnboundedMethodReference {
public static void main(String[] args) {
List<String> words = new ArrayList<>(Arrays.asList("Banana", "Apple", "Cherry"));
System.out.println("Before conversion: " + words);
// 비한정적 메서드 참조 1
List<String> lowerCaseWords = words.stream()
**.map(String::toLowerCase)**
// .map(s -> s.toLowerCase())
.toList();
System.out.println("After conversion: " + lowerCaseWords);
words = new ArrayList<>(Arrays.asList("banana", "apple", "cherry"));
System.out.println("Before sorting: " + words);
// 비한정적 메서드 참조 2
**Collections.sort(words, String::compareTo);**
// Collections.sort(words, (s1, s2) -> s1.compareTo(s2));
System.out.println("After sorting: " + words);
}
}
클래스 생성자 예제
public class ConstructorMethodReference {
public static void main(String[] args) {
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
System.out.println("Names: " + names);
// 생성자 참조
List<Person> people = names.stream()
**.map(Person::new)**
// .map(name -> new Person(name))
.toList();
System.out.println("People: " + people);
}
}
배열 생성자 예제
public class ArrayConstructorMethodReference {
public static void main(String[] args) {
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
System.out.println("Names: " + names);
// 배열 생성자 참조
String[] namesArray = names.toArray(String[]::new);
System.out.println("Names array: " + Arrays.toString(namesArray));
}
}