-
JAVA 함수형 프로그래밍 (1) - Functional InterfaceJAVA/자바공부 2024. 8. 16. 03:31
- 자바에서 제공하는 함수형 프로그래밍 도구 java.util.function 패키지에 위치한 대표적인 인터페이스 사용법을 정리한다.
- 아래의 기능을 적재적소에서 활용하면 가독성, 유지보수, 확장성이 좋은 코드를 작성할 수 있다.
- 엄청 많은데 큰 분류로, Function, Functional Interface, Consumer, Supplier, Predicate, Comparator의 사용법을 알면 원시타입용도 인터페이스(박싱 안해서 메모리 덜 사용), 추가 매개변수용도 인터페이스와 같이 구분할 수 있다.
1. Function<T, R> 인터페이스
- 매개변수를 조작해서 반환값을 얻는 용도
@Test @DisplayName("Function interface 테스트 - 매개변수가 1개") void step1() { // Function<T, R> - T를 받아서 R을 리턴하는 함수형 인터페이스 Function<Integer, Integer> adder = new Adder(); assertThat(adder.apply(10)).isEqualTo(20); } class Adder implements Function<Integer, Integer> { @Override public Integer apply(Integer integer) { return integer + 10; } }
2. Lambda Expression
- 익명함수를 사용하면 가독성 있고 확장성 있게 쓸 수 있다.
@Test @DisplayName("Lambda expression 테스트") void step2() { Function<Integer, Integer> adder = (Integer x) -> x + 10; assertThat(adder.apply(10)).isEqualTo(20); }
4. BiFunction<T, U , R> 인터페이스
- 매개변수가 2개인 경우 반환값 처리할때 활용
@Test @DisplayName("BiFunction 테스트 - 매개변수가 2개") void step3() { // 매개변수가 2개인 경우 - BiFunction<T, U, R> - T, U를 받아서 R을 리턴하는 함수형 인터페이스 BiFunction<Integer, Integer, Integer> adder = (x, y) -> x + y; assertThat(adder.apply(10, 10)).isEqualTo(20); }
4. Functional Interface
- 매개변수가 2개 이상인 경우 Functional Interface를 만들어 함수형 프로그래밍을 할 수 있다.
- @FunctionalInterface란 단 1개의 abstract method를 가진 인터페이스를 말한다.
- 아래는 매개변수 3개의 Functional Interface의 예시
@Test @DisplayName("Functional interface 테스트 - 매개변수가 3개") void step4() { TriFunction<Integer, Integer, Integer, Integer> adder = (x, y, z) -> x + y + z; assertThat(adder.apply(10, 10, 10)).isEqualTo(30); } @FunctionalInterface // 단 1개의 abstract method 만 가지는 인터페이스 public interface TriFunction<T, U, V, R> { R apply(T t, U u, V v); }
5. Supplier
- 매개변수 1개를 받아서 아무것도 리턴하지 않는 void 타입의 함수형 인터페이스
@Test @DisplayName("Functional interface 테스트 - Supplier") void step5() { // Supplier<T> - T를 리턴하는 함수형 인터페이스 Supplier<String> supplier = () -> "Hello, World!"; assertThat(supplier.get()).isEqualTo("Hello, World!"); }
6. Consumer
- 매개변수 1개를 받아서 아무것도 리턴하지 않는 void 타입의 함수형 인터페이스
- 앞서 언급한 함수형 인터페이스는 매개변수로 전달하여 추가 작업을 해, 확장성 좋은 코드를 짤 수 있다.
@Test @DisplayName("Functional interface 테스트 - Consumer") void step6() { // Consumer<T> - T를 받아서 아무것도 리턴하지 않는 함수형 인터페이스 Consumer<String> helloConsumer = (String s) -> System.out.println(s); helloConsumer.accept("Hello, World!"); Consumer<Integer> integerPrinter = (Integer i) -> System.out.println("input: " + i); Consumer<Integer> temMultiplyPrinter = (Integer i) -> System.out.println(i * 10); // 다형성 활용 - Consumer<Integer> 전달해서 확장성 있는 코드 작성 가능 process(List.of(1, 2, 3), temMultiplyPrinter); } static <T> void process(List<T> inputs, Consumer<T> processor) { for (T input : inputs) { processor.accept(input); } }
7. BiConsumer
- 매개변수 2개를 받아서 아무것도 리턴하지 않는 void 타입의 함수형 인터페이스
@Test @DisplayName("Functional interface 테스트 - BiConsumer") void step7() { // BiConsumer<T, U> - T, U를 받아서 아무것도 리턴하지 않는 함수형 인터페이스 BiConsumer<Integer, Double> printer = (x, y) -> System.out.println("x: " + x + ", y: " + y); printer.accept(10, 10.0); }
8. Predicate
- 매개변수 2개를 받아서 boolean 값을 리턴하는 함수형 인터페이스.
- QueryDsl의 BooleanBuiler를 쓸때의 그것
@Test @DisplayName("Functional interface 테스트 - Predicate") void step8() { // Predicate<T> - T를 받아서 boolean 을 리턴하는 함수형 인터페이스 Predicate<Integer> isEven = (Integer x) -> x % 2 == 0; assertThat(isEven.test(10)).isTrue(); assertThat(isEven.test(11)).isFalse(); // Predicate 기본 함수 사용 Predicate<Integer> isPositive = (Integer x) -> x > 0; Predicate<Integer> isNegative = (Integer x) -> x < 0; Predicate<Integer> isZero = (Integer x) -> x == 0; assertThat(isPositive.and(isNegative).test(10)).isFalse(); assertThat(isPositive.and(isNegative).test(-10)).isFalse(); assertThat(isPositive.and(isNegative).test(0)).isFalse(); assertThat(isPositive.or(isNegative).test(10)).isTrue(); assertThat(isPositive.or(isNegative).test(-10)).isTrue(); assertThat(isPositive.or(isNegative).test(0)).isFalse(); assertThat(isPositive.negate().test(10)).isFalse(); assertThat(isPositive.negate().test(-10)).isTrue(); assertThat(isPositive.negate().test(0)).isTrue(); assertThat(isZero.negate().test(10)).isTrue(); assertThat(isZero.negate().test(-10)).isTrue(); assertThat(isZero.negate().test(0)).isFalse(); }
9. Comparator
- 매개변수를 받아서 int를 리턴하는 함수형 인터페이스이다.
- a와 b 2개의 값을 비교해서 작으면 음수, 크면 양수를 리턴한다.
- 아래는 이름 비교를 사용한 정렬 구현이다.
@Test @DisplayName("Functional interface 테스트 - Comparator") void step9() { // Comparator<T> - T를 받아서 int 를 리턴하는 함수형 인터페이스 // compare(T o1, T o2) - o1이 o2보다 작으면 음수, 같으면 0, 크면 양수 리턴 // given User user1 = User.create("hello@hello.com", "hello12", "def"); User user2 = User.create("hello@hello.com", "hello123", "abc"); List<User> userList = Arrays.asList(user1, user2); assertThat(userList.get(0)).isEqualTo(user1); // when Collections.sort(userList, (u1, u2) -> u1.getName().compareTo(u2.getName())); // then assertThat(userList.get(0)).isEqualTo(user2); assertThat(userList.get(1)).isEqualTo(user1); }
반응형'JAVA > 자바공부' 카테고리의 다른 글
Java Exception Handling (e.printStackTrace()) (0) 2023.10.20 자바 LocalDateTime 요일, 오전/오후 한국어로 변경 (0) 2023.08.03 (다시 보는) SOLID 원칙이란? (0) 2023.05.29 DB의 시간, Java의 시간, Javascript의 시간 (Data, LocalDate, LocalDateTime, Y2K38 Problem) (2) 2023.03.07 자바 (0) 2023.02.20