함수형 프로그래밍
일단 함수형 프로그래밍의 등장 배경을 보겠습니다.
일단 명령형 프로그래밍 기반에서 소프트웨어의 크기가 커졌습니다. 그래서 스파게티 코드를 유지 보수할 수가 없어졌습니다. 그래서 순수 함수로 문제를 해결하는 기법인 함수형 프로그래밍이라는 패러다임에 관심을 가지게 되었습니다.
하지만 함수형 프로그래밍은 객체지향이 유행하기 전부터 존재했었지만 최근 들어서야 함수형 프로그래밍이 유행하고 있다.
→ 현대 컴퓨터 시스템은 과거에 비해 컴퓨터 자원들의 가격이 저렴해지고 멀티코어가 기본적으로 장착되어 있고 성능이 좋게 나온다.
그리고 최근에는 머신러닝, 데이터 분석 등 무겁고 시간이 오래 걸리는 작업들이 많이 있다. 그리고 이 작업들을 효과적으로 시간을 단축시켜 수행하기 위해 컴퓨터 멀티코어라는 점을 이용해서 병렬성을 이용하는데 함수형 프로그래밍은 병렬성 처리가 쉬워서 유행하는것도 있다.
그래서 동시성과 병렬성이란?
이것도 나중에 블로그로 쓰겠습니다~
이제 람다를 알아볼게요. 그전에 함수형 인터페이스부터 알아야 합니다.
함수형 인터페이스
- 추상 메서드가 오로지 단 한 개만 있는 인터페이스
- SAM(single abstract method)
- @FuncationInterface 어노테이션을 가지고 있음
@FunctionalInterface
public interface CustomInterface<T> {
T Call();
default void printDefault() {
System.out.println("hello");
}
static void printStatic() {
System.out.println("Hello Static");
}
}
익명 클래스로 사용가능
// 익명 클래스
CustomInterface customInterface1 = new CustomInterface() {
@Override
public String Call() {
return "hello";
}
};
자바 8 부터는 함수형 인터페이스라서 람다식으로도 표현 가능
CustomInterface<String> customInterface = () -> "helll";
customInterface.Call();
customInterface.printDefault();
람다
일단 람다 함수란 익명함수를 뜻합니다. 여기서 익명함수란 말 그대로 이름이 없는 함수입니다. 익명함수들은 공통으로 일급객체라는 특징을 가지고 있습니다.
그러면 람다를 사용하는 이유는 뭘까요?
코드의 간결성, 불필요한 연산과 코드 최소화, 병렬처리 가능 때문입니다.
그러면 일단 특징부터 볼게요.
- 익명 메소드만 전달하여 인터페이스를 구현한 익명 클래스의 인스턴스를 생성 => 익명 구현 객체 생성
- 람다식이 구현할 인터페이스는 단 1개의 추상 메서드를 가지고 있어야 함 -> 이것 때문에 알아야 합니다~
- @functionalInterface 즉 함수형 인터페이스
- 익명 메서드를 전달하면, 단 1개의 추상 메소드를 구현한 익명 인스턴스를 생성
list.sort((o1, o2) -> {
return Integer.compare(o1.length(), o2.length());
});
매개변수 타입은 String 리턴타입은 Int 컴파일러가 타입을 추론 가능 그래서 아래 처럼 가능
list.sort(Comparator.comparingInt(String::length));
=> comparator, runnable, callable 이 람다로 만들수 있는것들 대표적입니다.
-> 하지만 추상 클래스의 인스턴스를 만들 때 람다를 사용할 수 없습니다.
메서드 참조
- 람다 표현식이 단 하나의 메서드만을 호출하는 경우
inventory.sort(comparing(Apple::getWeight));
Apple 클래스에 정의된 getWeight의 메서드 참조
(Apple a) -> a.getWeight()를 축약
정적 메소드 참조
- Integer::parseInt
다양한 형식의 인스턴스 메서드 참조
- String::length
세 가지 종류의 람다 표현식을 메서드 참조로 바꾸는 방법
람다 (args) -> ClassName.staticMethod(args)
메서드 참조 ClassName::staticMethod
람다 (arg0, rest) -> arg0.instanceMethod(rest)
메서드 참조 ClassName::instanceMethod
람다 (args) -> expr.instanceMethod(args)
메서드 참조 expr::instanceMethod
List<String> names = Arrays.asList("홍길동","홍가가");
names.sort(String::compareTo);
메서드 참조는 콘텍스트의 형식과 일치해야 함
생성자 참조
ClassName::new
Supplier<Apple> c1 = Apple::new;
Supplier<Apple> c2 = () -> new Apple();
Function<Integer, Apple> c3 = Apple::new;
Function<Integer, Apple> c4 = (weight) -> new Apple(weight);
전체적인 변환 과정입니다
1. List<Apple> weights = Arrays.asList(apple1, apple2);
2. weights.sort(new Comparator<Apple>() {
@Override
public int compare(Apple a1, Apple a2) {
Integer weight = a1.getWeight();
return weight.compareTo(a2.getWeight());
}
});
3. weights.sort((a1, a2) -> a1.getWeight().compareTo(a2.getWeight()));
Comparator<Apple> c = Comparator.comparing((Apple apple4) -> apple4.getWeight());
4. weights.sort(Comparator.comparing(apple -> apple.getWeight()));
5. weights.sort(Comparator.comparing(Apple::getWeight));
'언어 > 자바' 카테고리의 다른 글
자바 컬렉션(List, Map, Set) (0) | 2021.09.10 |
---|---|
동시성(Concurrency)과 병렬성(Parallelism) (0) | 2021.09.08 |
java의 스트림이란?? (0) | 2021.09.06 |
JAVA - 추상클래스와 인터페이스 (0) | 2021.09.03 |
자바의 JVM메모리 구조 (0) | 2021.09.01 |