람다식
은 함수지향언어에 가까우며, 코드가 간결해지고 컬렉션의 요소를 필터링하거나 매핑해서 원하는 결과를 쉽게 집계할 수 있다.
람다식은 (매개변수) -> {실행코드}
형태로 작성되는데, 마치 함수 정의 형태를 띠고 있지만 런타임에 인터페이스의 익명 구현 객체로 생성된다. 어떤 인터페이스를 구현할 것인가는 대입되는 인터페이스가 무엇이냐에 달려있다.
매개변수의 타입은 런타임에 대입되는 값에 따라 자동으로 인식될 수 있기 때문에 람다식에서는
매개변수의 타입을 일반적으로 언급하지 않는다.
매개변수가 1개라면 ()를 생략할 수 있고, 하나의 실행문만 있다면 {}도 생략가능하고,
return문만 존재하면 return도 생략 가능하다. 하지만 매개변수가 없다면 ()괄호를 반드시 사용해야한다.
함수형 인터페이스(functional interface)
: 하나의 추상 메서드가 선언된 인터페이스
@FunctionalInterface
애너테이션은 해당 인터페이스를 함수형 인터페이스로 선언하는데, 두 개 이상의 추상메서드가 선언되면 컴파일 오류를 발생시킨다.
함수형 인터페이스만이 람다식의 타겟 타입이 될 수 있다.
추상메서드의 매개변수와 리턴타입에 따라 람다식을 작성한다.
스트림(Stream)
: 배열, 컬렉션의 저장 요소를 하나씩 참조해서 람다식으로 처리할 수 있도록 해주는 반복자.
Stream이 제공하는 대부분의 메서드는 함수형 인터페이스 매개타입을 가지기 때문에 람다식 또는 메서드 참조를 이용해서 요소 처리 내용을 매개값으로 전달할 수 있다.
내부 반복자를 사용하므로 병렬처리가 쉽다.
병렬 처리
는 한 가지 작업을 여러개로 분리하여 작업들을 분리된 스레드에서 병렬적으로 처리하는 것을 의미한다.
내부 반복자
는 병렬 작업을 할 수 있게 도와주기 때문에 순차적으로 처리하는 외부 반복자보다 효율적으로 요소를 반복할 수 있다.
stream()
: 컬렉션(Collection)으로부터 스트림 생성
Stream.of
또는 Arrays.stream
: 배열을 소스로하는 스트림 생성
map()
: 기존의 Stream 요소들을 대체하는 요소로 구성된 새로운 Stream을 형성한다
map 이외에도 mapToInt(), mapToLong(), mapToDouble()
등의 메서드가 존재하는데,
이 메서드들은 일반적인 Stream 객체를 원시 Stream(ex. IntStream)으로 바꾸는 작업이 필요한 경우에 쓰인다.
반대로 원시 객체는 mapToObject
를 통해 일반적인 Stream 객체로 바꿀 수 있다.
또한 flatMap()
메서드도 존재하는데, map()과의 차이점은 map()은 스트림의 스트림을 반환
하는 반면, flatMap()은 스트림을 반환
한다는 것이다.
map()의 리턴 타입이 Stream<Stream>이라면, flatMap()의 리턴 타입은 Stream인 것이다.
match()
: Stream의 요소들이 특정한 조건을 충족하는지 검사하는 메서드이다
match()
는 함수형 인터페이스 Predicate를 받아서 해당 조건을 만족하는지 검사하고, 검사 결과를 boolean으로 반환한다.reduce
: 누적하여 값을 산출하며, 최대 3개의 매개변수를 받는다
Arrays.stream(arr).reduce(0, (a,b) -> a+b);
sum(), count()
등은 모두 내부적으로 reduce()를 사용한다.collect
: Stream의 요소들을 List, Map 등 다른 형태로 반환하고 싶을 때 사용한다.
Arrays.stream(arr).collect(Collecters.toList());
Stream의 요소들을 어떻게 수집할 것인가를 정의한 Collector 타입을 인자로 받으며, 이는 Collector 인터페이스를 구현한 클래스이다.
자주 사용하는 작업은 Collectors 객체에서 static 메서드로 제공하며, 필요한 경우 Collector 인터페이스를 직접 구현하여 사용할 수도 있다.
컬렉션은 Eager(메모리에 전체를 한 번에 올려서 처리)
방식으로 데이터를 처리하고, 스트림은 Lazy(필요할 때에만 조금씩 올리면서 처리) and Short-circuit
방식으로 처리한다.
=> 따라서 Lazy 방식
은 대용량 데이터를 처리할 때 성능적인 측면에서 뚜렷한 이점이 있다.