[Java] 람다와 스트림 (Lambda / Stream)

bagt13·2022년 5월 20일
0

JAVA

목록 보기
5/7
post-thumbnail

📘 람다 (Lambda)

람다식은 함수지향언어에 가까우며, 코드가 간결해지고 컬렉션의 요소를 필터링하거나 매핑해서 원하는 결과를 쉽게 집계할 수 있다.

  • 람다식은 (매개변수) -> {실행코드} 형태로 작성되는데, 마치 함수 정의 형태를 띠고 있지만 런타임에 인터페이스의 익명 구현 객체로 생성된다. 어떤 인터페이스를 구현할 것인가는 대입되는 인터페이스가 무엇이냐에 달려있다.

  • 매개변수의 타입은 런타임에 대입되는 값에 따라 자동으로 인식될 수 있기 때문에 람다식에서는
    매개변수의 타입을 일반적으로 언급하지 않는다.

  • 매개변수가 1개라면 ()를 생략할 수 있고, 하나의 실행문만 있다면 {}도 생략가능하고,
    return문만 존재하면 return도 생략 가능하다. 하지만 매개변수가 없다면 ()괄호를 반드시 사용해야한다.



📒 함수형 인터페이스 (Functional Interface)

함수형 인터페이스(functional interface) : 하나의 추상 메서드가 선언된 인터페이스

  • @FunctionalInterface 애너테이션은 해당 인터페이스를 함수형 인터페이스로 선언하는데, 두 개 이상의 추상메서드가 선언되면 컴파일 오류를 발생시킨다.

  • 함수형 인터페이스만이 람다식의 타겟 타입이 될 수 있다.

  • 추상메서드의 매개변수와 리턴타입에 따라 람다식을 작성한다.



📘 스트림

스트림(Stream) : 배열, 컬렉션의 저장 요소를 하나씩 참조해서 람다식으로 처리할 수 있도록 해주는 반복자.

Stream이 제공하는 대부분의 메서드는 함수형 인터페이스 매개타입을 가지기 때문에 람다식 또는 메서드 참조를 이용해서 요소 처리 내용을 매개값으로 전달할 수 있다.



📒 스트림의 특징

  1. 내부 반복자를 사용하므로 병렬처리가 쉽다.

    병렬 처리는 한 가지 작업을 여러개로 분리하여 작업들을 분리된 스레드에서 병렬적으로 처리하는 것을 의미한다.

    내부 반복자병렬 작업을 할 수 있게 도와주기 때문에 순차적으로 처리하는 외부 반복자보다 효율적으로 요소를 반복할 수 있다.

  1. 데이터 소스로부터 읽기만 할 뿐 값을 변경하지 않으며, 일회용이다



📒 스트림의 생성

stream() : 컬렉션(Collection)으로부터 스트림 생성

Stream.of 또는 Arrays.stream : 배열을 소스로하는 스트림 생성



📒 중간연산( filter(),map(), match() )

map() : 기존의 Stream 요소들을 대체하는 요소로 구성된 새로운 Stream을 형성한다

  • 데이터를 특정한 형태로 변환하는데 주로 사용되며, map함수의 인자로 함수형 인터페이스를 받는다.

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 방식대용량 데이터를 처리할 때 성능적인 측면에서 뚜렷한 이점이 있다.

profile
주니어 백엔드 개발자입니다😄

0개의 댓글