'자바 메소드 레퍼런스'에 해당되는 글 1건

728x90

y = f(x) 형태의 함수로 구성된 프로그래밍 기법

Java 8에서 함수형 프로그래밍 방식인 람다식을 지원한다.

객체지향 프로그래밍보다는 함수형 프로그래밍에 가깝다고 할 수 있다.

 

람다식이란? 함수(메서드)를 간단한 ‘식(Expression)’으로 표현하는 방법

 

- 함수는 클래스에 독립적, 메소드는 클래스에 종속적
- 메서드의 이름과 반환타입을 제거하고 ‘->’를 블록{} 앞에 추가한다.
- 반환값이 있는 경우, 식이나 값만 적고 return문 생략 가능(끝에‘;’안 붙임)
- 매개변수의 타입이 추론 가능하면 생략가능(대부분의 경우 생략가능)
- 매개변수가 하나인 경우, 괄호() 생략가능(타입이 없을 때만)
- 블록 안의 문장이 하나뿐 일 때, 괄호{}생략가능(끝에 ‘;’ 안 붙임)
- 단, 하나뿐인 문장이 return문이면 괄호{} 생략불가

 

 

람다식 장점
1. 코드를 간결하게 만들 수 있다.
2. 코드가 간결하고 식에 개발자의 의도가 명확히 드러나므로 가독성이 향상된다.
3. 함수를 만드는 과정없이 한번에 처리할 수 있기에 코딩하는 시간이 줄어든다.
4. 병렬프로그래밍이 용이하다.

람다식 단점
1. 람다를 사용하면서 만드는 익명함수는 재사용이 불가능하다.
2. 디버깅이 다소 까다롭다.
3. 람다를 남발하면 코드가 지저분해질 수 있다.
4. 재귀로 만들경우에는 다소 부적합한면이 있다.

 

 
@FunctionalInterface
interface MyFunction {
    // 함수형 인터페이스 : 단 하나의 추상 메소드만 선언된 인터페이스
    int max(int a, int b);  // public abstract 생략
}
 
public class LambdaEX1 {
    public static void main(String[] args) {
        // 람다식(익명 객체)을 다루기 위한 참조변수의 타입은 함수형 인터페이스로 한다.
        MyFunction f = (a, b) -> a > b ? a : b;
        int value = f.max(3,5);
        System.out.println(value);
    }
}
 

 

@FunctionalInterface
interface MyFunctionalInterface{
    // 함수형 인터페이스 : 단 하나의 추상 메소드만 선언된 인터페이스
    void method();
}
 
public class LambdaEX2 {
    public static void main(String[] args) {
        MyFunctionalInterface fi1 = new MyFunctionalInterface() {
            @Override
            public void method() {
                String str = "직접 익명 객체 구현함";
                System.out.println(str);
            }
        };
        fi1.method();
 
        MyFunctionalInterface fi2 = () -> {
            String str = "람다식 익명 객체 구현함";
            System.out.println(str);
        };
        fi2.method();
    }
}
 

 

 

 

 

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
 
@FunctionalInterface
interface MyFunctionIF {
    // 함수형 인터페이스 : 단 하나의 추상 메소드만 선언된 인터페이스
    int max(int a, int b);  // public abstract 생략
}
 
public class LambdaEX1 {
    public static void main(String[] args) {
        // 람다식(익명 객체)을 다루기 위한 참조변수의 타입은 함수형 인터페이스로 한다.
        MyFunctionIF f = (a, b) -> a > b ? a : b;
        int value = f.max(3,5);
        System.out.println(value);
 
        int result = Integer.parseInt("123");
        System.out.println(result);
 
        System.out.println("===================================");
        ArrayList<Integer> list = new ArrayList<>();
        for(int i=0;i < 20;i++)
            list.add(i);
 
        System.out.println(list);
 
        // list의 모든 요소를 출력
        list.forEach(i->System.out.print(i + ", "));
        System.out.println();
 
        // list에서 2 또는 3의 배수를 제거한다.
        list.removeIf(x -> x%2==0 || x%3==0);
        System.out.println(list);
 
        list.replaceAll(i->i*3); // list의 각 요소에 3을 곱한다.
        System.out.println(list);
 
        System.out.println("===================================");
        Map<StringString> map = new HashMap<>();
        map.put("1""1");
        map.put("2""2");
        map.put("3""3");
        map.put("4""4");
 
        // map의 모든 요소를 {k,v}의 형식으로 출력한다.
        map.forEach((k,v)-> System.out.print("{"+k+","+v+"},"));
        System.out.println();
    }
}
 

 

메소드 참조

메소드 레퍼런스(Method Reference)는 Lambda 표현식을 더 간단하게 표현하는 방법이다.

메소드 레퍼런스는 ClassName::MethodName 형식으로 입력한다. 
메소드를 호출하는 것이지만 괄호()는 써주지 않고 생략한다.

import java.util.Arrays;
import java.util.List;
import java.util.function.BinaryOperator;
import java.util.function.IntBinaryOperator;
 
class MathBox {
    // 클래스::메소드 --> 정적(static) 메소드 참조
    public static int staticPlus(int x, int y){
        return x+y;
    }
 
    // 참조변수::메소드 --> 인스턴스 메소드 참조
    public int sum(int x, int y){
        return x+y;
    }
 
    // 정수 빼기
    public int sub(int x, int y){
        return x-y;
    }
 
    // 정수 나누기
    public int division(int x, int y){
        return x / y;
    }
 
    // 실수 나누기
    public Float float_div(Float x, Float y){
        return x / y;
    }
 
}
 
public class Method_References {
    public static void main(String[] args) {
        List<String> strList = Arrays.asList("안녕""하세요");
        strList.stream().forEach(System.out::println);
 
        // static 메소드 참조
        IntBinaryOperator operator1;
        // 메소드 참조해서 매개변수 리턴타입 알아내 람다식에서 불필요한 매개변수 제거 목적
        operator1 = MathBox::staticPlus; // 메소드 참조
        System.out.println(operator1.applyAsInt(53));
 
        operator1 = (x, y) -> MathBox.staticPlus(x, y);
        System.out.println(operator1.applyAsInt(35));
 
        // instance 메소드 참조
        MathBox calculator = new MathBox();
        IntBinaryOperator operator2 = calculator::sum; // 메소드 참조
        System.out.println("더하기 : " + operator2.applyAsInt(1132));
 
        operator1 = (x, y) -> calculator.sum(x, y);
        System.out.println(operator1.applyAsInt(1132));
 
        operator2 = calculator::sub; // 메소드 참조
        System.out.println("빼기 : " + operator2.applyAsInt(1130));
 
        operator2 = calculator::division; // 메소드 참조
        System.out.println("나누기 : " + operator2.applyAsInt(154));
 
        BinaryOperator<Integer> operator3 = (n1, n2) -> n1 + n2; // 타입 추론
        Integer sum = operator3.apply(10100);
        System.out.println(sum);
 
        BinaryOperator<Float> operator4 = calculator::float_div;
        System.out.println("나누기 : " + operator4.apply(15.0f, 4.0f));
 
        BinaryOperator<Float> operator5 = (n1, n2) -> n1 / n2; // 타입 추론
        Float div = operator5.apply(15.0f, 4.0f);
        System.out.println(div);
    }
}
 

 

 

자바에서 제공하는 함수형 인터페이스를 이용하면 인터페이스를 만들지 않고 간단하게 코드 구현 가능하다.

import java.util.function.Consumer;
 
interface Printable {
    void doSomething(String text);
}
 
public class MethodReferencesEX2 {
    public static class Printer {
        static void printSomething(String text) {
            System.out.println(text);
        }
    }
 
    public static void main(String[] args) {
        Printable printable = text -> Printer.printSomething(text);
        printable.doSomething("do something");
 
        Printable printable2 = Printer::printSomething;
        printable2.doSomething("do something");
 
        // Consumer<클래스>는 자바에서 제공하는 함수형 인터페이스
        // String 1개를 인자로 받아 void를 리턴하는 메소드를 갖고 있는 인터페이스
        Consumer<String> consumer = Printer::printSomething;
        consumer.accept("do something"); // Printable 인터페이스를 만들 필요가 없다.
    }
}
 

 

블로그 이미지

Link2Me

,