[Java] Lamda & Stream

이지현·2023년 4월 10일
0

Java

목록 보기
33/46
post-thumbnail

✔️ Lamda

  • 람다식은 메서드를 하나의 식으로 표현한 것
  • 객체 지향 언어보다는 함수 지향 언어에 가까움
  • 메서드를 람다식으로 표현하면 메서드의 이름 및 반환 값이 없어지므로 익명 함수라고도 함
  • 람다식의 형태는 매개 변수를 가진 코드 블록이지만 런타임 시에는 익명 구현 객체를 생성함

기본식

(타입 매개변수) -> { 실행문; }

예시

interface ExFunctionInterface {
    public void method();
}

//public class ExFunctionInterfaceTest {
//    public static void main(String[] args) {
//        ExFunctionInterface test = new ExFunctionInterface() {
//            public void method() {
//                System.out.println("test");
//            }
//        };
//        test.method();
//    }
//}

public class ExFunctionInterfaceTest {
    public static void main(String[] args) {
        ExFunctionInterface test = () -> System.out.println("test");
        test.method();
    }
}

1. 함수형 인터페이스

  • 람다식을 다루기 위한 인터페이스, 하나의 추상 메서드만 정의되어 있어야 함
  • static 메서드와 default 메서드의 개수에는 제약이 없음
  • 람다식은 Object 타입으로 형변환 불가
  • 람다식 내에서 참조하는 지역변수는 final 붙어있지 않아도 상수로 간주, 외부 지역변수와 같은 이름의 매개변수를 허용하지 않음
  • 함수형 인터페이스는 @FunctionalInterface라는 어노테이션을 붙일 수 있음

2. Function의 합성과 predicate의 결합

Function의 합성

  • a.andThen(b) : a 함수 적용 후 b 함수 적용
  • a.compose(b) : b 함수 적용 후 a 함수 적용
  • identity : 항등 함수(잘 사용되지 않는 편이나 map()으로 변환 작업 시 변환없이 그대로 처리하고 싶을 때 사용)

predicate의 결합

  • and()
  • or()
  • negate()
  • not isEqual()

✔️ Stream

  • 다양한 데이터 소스를 표준화 된 방법으로 다루기 위한 라이브러리
  • 데이터 소스를 추상화하고, 데이터를 다루는데 자주 사용되는 메서드들을 정의해놓음
  • 스트림 이용 시 배열이나 컬렉션 뿐만 아니라 파일에 저장된 데이터도 모두 같은 방식으로 다룰 수 있음
  • 코드가 더 간결하고 재사용성이 높다는 장점이 있음

1. Stream의 연산

  • 중간연산 : 연산 결과가 스트림, 연속해서 수행 가능
  • 최종연산 : 연산 결과가 스트림이 아님, 스트림의 요소를 소모하기 때문에 단 한 번만 가능
최종연산설명
void forEach(Consumer <? super T> action)각 요소에 지정된 작업 수행
long count()스트림의 요소 개수
Optional < T > max (Comparator <? super T> comparator)스트림의 최댓값
Optional < T > min (Comparator <? super T> comparator)스트림의 최솟값
Optional < T > findAny()아무거나 하나
Optional < T > findFirst()첫번째 요소
boolean allMatch(Pradicate < T > p)모두 만족하는지?
boolean anyMatch(Pradicate < T > p)하나라도 만족하는지?
boolean noneMatch(Pradicate < T > p)모두 만족하지 않는지?
Object[] toArray()스트림의 모든 요소를 배열로 return

reduce() : 스트림의 요소를 하나씩 줄여가면서 계산
collect() : 스트림의 요소를 수집함, 주로 요소를 그룹화하거나 결과를 컬렉션에 담아 반환하는데 사용됨

List<String> sortedList = strStreamList.sorted().collect(Collectors.toList());

2. Stream의 특징

(1) 스트림은 데이터 소스를 변경하지 않음

스트림은 데이터 소스로부터 데이터를 읽기만 함. 정렬된 결과가 필요할 경우, collect를 활용해서 컬렉션이나 배열에 담아 return 할 수 있음

List<String> sortedList = strStreamList.sorted().collect(Collectors.toList());
(2) 스트림은 일회용임

스트림은 한 번 사용하면 닫혀서 다시 사용할 수 없음. 필요하다면 다시 생성해야 함

(3) 스트림은 작업을 내부 반복으로 처리함

내부 반복이란 반복문을 메서드 내부에 숨길 수 있다는 것을 의미. forEach()는 스트림에 정의된 메서드 중의 하나로 매개변수에 대입된 람다식을 데이터 소스의 모든 요소에 적용함. 즉 forEach()는 메서드 안에 for 문을 넣은 것임

strStreamArr.sorted().forEach(System.out::println);
(4) 지연된 연산

최종 연산이 수행되기 전까지는 중간 연산이 수행되지 않음. 중간 연산은 어떤 작업이 수행되어야 하는지 지정해주는 역할일 뿐임.

(5) 기본형 스트림

오토박싱, 언박싱으로 인한 비효율을 줄이기 위해 데이터 소스의 요소를 기본형으로 다루는 IntStream, LongStream, DoubleStream이 제공됨

// 오토 박싱 - Deprecated
int i = 10;
Integer num = i;

// 오토 언박싱 - Deprecated
Integer num = new Integer(10);
int i = num;
(6) 병렬 스트림
  • parallel() 메서드 : 병렬 연산 수행
int sum = strStream.parallel().mapToInt(s -> s.length()).sum;
  • sequential() 메서드 : 병렬 처리 X
profile
2023.09 ~ 티스토리 이전 / 2024.04 ~ 깃허브 블로그 이전

0개의 댓글