Comparator<Apple> comparator1 = new Comparator<>() {
@Override
public int compare(Apple o1, Apple o2) {
return o1.getWeight() - o2.getWeight();
}
};
// 람다를 사용하면 훨씬 더 간결해진다.
Comparator<Apple> comparator2 =
(Apple a1, Apple a2) -> a1.getWeight() - a2.getWeight();
람다 표현식 사용법은 파라미터, 화살표, 바디로 이루어진다.
(Apple a1, Apple a2) : 람다 파라미터
-> : 화살표
a1.getWeight() - a2.getWeighte(); : 람다 바디
// 불리언 표현식
(List<String> list) -> list.isEmpty();
// 객체 생성
() -> new Apple(10);
// 객체에서 소비
(Apple a) -> {
System.out.println(a.getWeight());
}
// 객체에서 선택 / 추출
(String s) -> s.length();
// 두 값을 조합
(int a1, int a2) -> a1 * a2;
// 두 객체 비교
(Apple a1, Apple a2) -> a1.getWeight() > a2.getWeight();
public interface Predicate<T> {
boolean test(T t);
}
@FunctionalInterface
public interface BufferedReaderProcessor {
String process(BufferedReader br) throws IOException;
}
// 기존
public String processFile1() throws IOException {
try (BufferedReader br = new BufferedReader(new FileReader("data.txt"))) {
return br.readLine();
}
}
// 람다 사용
public String processFile2(BufferedReaderProcessor p) throws IOException {
try (BufferedReader br = new BufferedReader(new FileReader("data.txt"))) {
return p.process(br);
}
}
public void execute() throws IOException{
processFile2((BufferedReader br) -> br.readLine());
processFile2((BufferedReader br) -> br.readLine()+br.readLine());
}
public <T> List<T> filter(List<T> list, Predicate<T> p) {
List<T> results = new ArrayList<>();
for (T t : list) {
if (p.test(t)) {
results.add(t);
}
}
return results;
}
public static void main(String[] args) {
Predicate<String> predicate = (String s) -> !s.isEmpty();
List<String> list = new ArrayList<>();
List<String> nonEmpty = filter(list, predicate);
}
public static <T> void forEach(List<T> list, Consumer<T> consumer) {
for (T t : list) {
consumer.accept(t);
}
}
public static void main(String[] args) {
forEach(Arrays.asList(1, 2, 3, 4, 5), (Integer i) -> System.out.println(i));
}
static public <T, R> List<R> map(List<T> list, Function<T, R> f) {
List<R> result = new ArrayList<>();
for (T t : list) {
result.add(f.apply(t));
}
return result;
}
public static void main(String[] args) {
List<Integer> result = map(Arrays.asList("lambda", "TTT", "RRRR"),
(String s) -> s.length()
);
System.out.println(result);
}
List<Integer> list = new ArrayList<>();
for(int i=300; i<400; i++) {
list.add(i)
}
하지만 이런 변환 과정은 비용이 소모된다. 박싱한 값은 기본형을 감싸는 래퍼며 힙에 저장된다. 따라서 박싱한 값은 메모리를 더 소비하며 기본형을 가져올 때도 메모리를 탐색하는 과정이 필요하다.
자바8 에서는 기본형을 입출력으로 사용하는 상황에서 오토박싱 동작을 피할 수 있도록 특별한 버전의 함수형 인터페이스를 제공한다. 예를들어 아래 예제에서 IntPredicate는 1000이라는 값을 박싱하지 않지만 Predicate는 1000이라는 값을 Integer 객체로 박싱한다.
public interface IntPredicate {
boolean test(int t);
}
IntPredicate evenNumbers = (int i) -> i % 2 == 0;
evenNumbers.test(1000); // 참 (박싱없음)
Predicate<Integer> oddNumbers = (Integer i) -> i % 2 != 0;
oddNumbers.test(1000) // 거짓(박싱)