backend
  • README
  • DOCS
    • Java Docs
    • Servlet Docs
    • JSP Docs
    • DB & SQL Docs
    • Spring Boot Docs
    • Spring Security Docs
    • AWS Docs
  • 설치하기
    • Intellij 설정
  • 자바
    • 01 Java란?
    • 02 자바 시작하기
    • 03 자료형과 연산자
    • 04 제어문
    • 05 메소드
    • 06 클래스 기초
      • Static 보충자료
      • 패키지 보충자료
    • 07 객체지향 프로그래밍
    • 08 클래스 더 알아보기
      • 열거형 ENUM 보충자료
    • 09 클래스와 자료형
      • 다형성 보충자료
      • 제네릭 보충자료
    • 10 컬렉션 프레임워크
      • 컬렉션 프레임워크 보충자료
    • 11 람다식과 함수형 프로그래밍
      • 람다식 보충자료
    • 12 오류 대비하기
      • 오류 보충자료
    • 13 멀티태스킹
      • 멀티태스킹 보충자료
    • 교재보충
      • java.lang
  • 스프링
    • 서블릿, JSP
      • 05 Servlet(서블릿)
        • 서블릿 보충자료
        • 서블릿 추가코드
        • XML, YAML, JSON
      • 06 JSP(자바 서버 페이지)
        • JSP 보충자료
      • 07 JSTL(JSP 스탠다드 태그 라이브러리)
        • JSTL 보충자료
      • 08 Cookie(쿠키), Session(세션)
      • 09 서블릿,필터,리스너
        • 서블릿,필터,리스너 보충자료
      • 11 도서관리 프로젝트 실습
    • Spring Boot
      • 01 스프링 등장 배경, 객체지향
        • 스프링 등장 배경, 객체지향 보충자료
      • 02 IOC(제어의 역전), DI(의존성 주입)
        • IOC 보충자료
        • DI 보충자료
      • 03 스프링 구조
        • 스프링 구조 보충설명
      • 04 테스트코드 실습
      • 05 스프링 빈 설정
        • 스프링 빈 설정 보충자료
      • 06 싱글톤
        • 싱글톤 보충 자료
      • 07 스프링 빈 자동설정
        • 스프링 빈 자동설정 보충자료
      • 08 빈 생명주기
        • 빈 생명주기 보충자료
      • 09 빈 스코프
        • 빈 스코프 보충자료
      • 10 스프링 MVC
        • 스프링 MVC 보충자료
        • 데이터베이스 연동에 필요한 부분
      • 11 Validation(검증)
        • Validation(검증) 보충자료
      • 12 Bean Validation(빈검증)
        • Bean Validation(빈검증) 보충자료
      • 13 예외처리
        • 예외처리 보충자료
      • 14 타입변환
      • 15 JDBC(Java Database Connectivity)
      • 16 커넥션풀
      • 17 트랜잭션
        • 트랜잭션 보충자료
      • 18 JDBC 템플릿 활용
      • 19 MyBatis
      • 20 JPA(Java Persistence API)
      • 22 게시판 프로젝트 실습
    • Spring Security
      • 보안(Security)
      • Spring Security
      • 2. Spring Security 알아보기
        • 보안 위협 실제 사례와 방어 전략
      • 3. Spring Security 기본 동작 흐름
      • 4. Spring Security로 인증 권한 추가하기
        • Spring Security의 인증 및 인가
      • 5. Spring Security에서 세션 관리하기
        • 세션(Session)과 쿠키(Cookie) 비교, 토큰(Token)과의 관계
        • 해싱 및 해싱알고리즘
        • base64
      • 6. Spring Security 악용 보호
        • SameSite
      • 7. Spring Security로 인가 권한 추가하기
      • 8. Bcrypt(비크립트) 암호화
      • OAuth2 적용하기
  • 네트워크
    • HTTP
    • OSI 7계층
  • DB&SQL
    • 01 Database(데이터베이스)와 SQL 개요
    • 02 관계형 모델
    • 03 집합
    • 04 JOIN 연산
    • 05 MySQL
      • 세이브포인트
      • DBeaver, Mysql 오토커밋 설정 관련
    • 06 SQL 기초
      • 예시데이터 쿼리문
    • 07 SQL 실습
      • 실습 스키마
    • 08 Join 활용
      • 실습스키마
    • 09 SQL 활용
      • 실습스키마
    • 10 정규화
      • 실습 스키마
    • 데이터타입
    • 예시 프로젝트 스키마 구성
  • AWS
    • SSL 연결하기
    • 보충설명
Powered by GitBook
On this page
  • 람다식(Lambda Expression)
  • 람다식의 기본 구조
  • 람다식의 구성 요소
  • 함수형 인터페이스
  • 함수형 인터페이스 예시1
  • 함수형 인터페이스 예시2
  • java.util.function 패키지
  • Runnable
  • Supplier<T>
  • Consumer<T>
  • BiConsumer<T, U>
  • Function<T, R>
  • BiFunction<T, U, R>
  • Predicate<T>
  • BiPredicate<T, U>
  • UnaryOperator<T>
  • BinaryOperator<T>
  • 메소드 참조(Method reference)
  • 클래스 메소드 호출
  • 인스턴스 메소드 호출
  • (1) 특정 클래스의 인스턴스 메소드 참조
  • (2) 특정 인스턴스의 인스턴스 메소드 참조
  • 3. 클래스 생성자 호출
  • 정리
  • 스트림(Stream)과 스트림 연산(Stream Operations)
  • 1. 스트림이란?
  • 2. 스트림 연산의 종류
  • 3. 스트림 생성
  • 4. 중간 연산 예시
  • 1. filter(Predicate)
  • 2. map(Function)
  • 3. sorted()
  • 4. distinct()
  • 5. 최종 연산 예시
  • 1. forEach(Consumer)
  • 2. collect()
  • 3. reduce()
  • 6. 스트림의 특징: 지연 연산
  • 정리
  1. 자바

11 람다식과 함수형 프로그래밍

람다식(Lambda Expression)

람다식(Lambda Expression)은 자바 8(Java 8)부터 도입된 기능으로, 자바에서 함수형 프로그래밍을 지원하기 위한 방식입니다.

람다식을 사용하면 간결하게 코드를 작성할 수 있으며, 특히 익명 클래스나 함수형 인터페이스를 구현할 때 유용합니다. 람다식은 메소드의 간결한 표현이자, 익명 메소드를 만드는 데 사용됩니다.

람다식의 기본 구조

람다식의 기본적인 문법은 다음과 같습니다.

(parameters) -> expression

혹은 여러 줄의 코드를 포함할 경우.

(parameters) -> {
    // 여러 줄의 코드
    statements;
}

람다식의 구성 요소

  • 매개변수 목록 (parameters): 메소드에 전달되는 인자 목록과 동일합니다. 여러 개의 인수가 있을 수 있으며, 인수가 없을 때는 빈 괄호 ()를 사용합니다.

  • 화살표 연산자 ->: 매개변수와 람다식의 본문을 구분하는 역할을 합니다.

  • 람다식의 본문 expression: 람다식이 수행할 작업을 정의합니다. 한 줄의 표현식이나 여러 줄의 블록으로 구성될 수 있습니다.

함수형 인터페이스

람다식을 사용하려면 함수형 인터페이스가 필요합니다.

함수형 인터페이스는 추상 메소드가 단 하나만 있는 인터페이스를 말합니다.

자바 8에서는 이러한 인터페이스를 쉽게 구분할 수 있도록 @FunctionalInterface 어노테이션을 제공하고 있습니다.

함수형 인터페이스 예시1

edu.ch11.interfaceExample 패키지

@FunctionalInterface
interface MyFunctionalInterface {
    void doSomething();
}

이제 이 인터페이스를 람다식을 통해 구현할 수 있습니다:

public class Main {
    public static void main(String[] args) {

        // MyFunctionalInterface 사용
        MyFunctionalInterface myFunction = () -> System.out.println("람다식을 사용한 함수형 인터페이스 구현!");
        myFunction.doSomething();

    }
}

함수형 인터페이스 예시2

edu.ch11.interfaceExample 패키지

@FunctionalInterface
public interface TwoParam {
    int func(int a, int b);
}
public class Main {
    public static void main(String[] args) {

        // TwoParam 사용
        TwoParam add = (a, b) -> a + b;
        TwoParam multAndPrint = (a, b) -> {
            int result = a * b;
            System.out.printf("%d * %d = %d%n", a, b, result);
            return result;
        };

				// 아래와 같이 사용
        int added = add.func(2, 3);
        int multiplied = multAndPrint.func(2, 3);

    }
}

java.util.function 패키지

자바는 람다식을 위한 함수형 인터페이스가 정의되어 있어야 해사, 필요할 때마다 정의해야 하므로 번거로움이 있습니다.

자주 사용하는 인터페이스가 java.util.function 패키지에 제공합니다.

함수형 인터페이스
메서드
인자(들) 타입
반환값 타입

Runnable (java.lang 패키지)

run

Supplier<T>

get

T

Consumer<T>

accept

T

BiConsumer<T, U>

accept

T, U

Function<T, R>

apply

T

R

BiFunction<T, U, R>

apply

T, U

R

Predicate<T>

test

T

boolean

BiPredicate<T, U>

test

T, U

boolean

UnaryOperator<T>

apply

T

T

BinaryOperator<T>

apply

T, T

T

(T 와 U는 서로 다른 자료형을 받을 수 있다는 것을 의미하며 같아도 상관없음)

Runnable

  • 메소드 이름: run

  • 인자 타입: 없음

  • 반환값 타입: 없음

  • 설명: 매개변수를 받지 않고 아무 값도 반환하지 않는 함수형 인터페이스입니다. 일반적으로 스레드를 실행할 때 사용됩니다.

public class RunnableExample {
    public static void main(String[] args) {
        Runnable runnable = () -> System.out.println("Running a thread!");
        Thread thread = new Thread(runnable);
        thread.start();
    }
}

바로 실행하는 로직

public class RunnableExample {
    public static void main(String[] args) {
        // Runnable로 단순 로직 정의
        Runnable task = () -> System.out.println("Executing some logic...");

        // 실행
        task.run(); // 그냥 함수 호출하듯 실행
    }
}

실행 결과:

Executing some logic...

Supplier<T>

  • 메소드 이름: get

  • 인자 타입: 없음

  • 반환값 타입: T

  • 설명: 입력 매개변수 없이 값을 반환하는 함수형 인터페이스입니다. 값을 공급하는 역할을 합니다.

import java.util.function.Supplier;

public class SupplierExample {
    public static void main(String[] args) {
        Supplier<String> supplier = () -> "Hello, Supplier!";
        System.out.println(supplier.get());
    }
}

Consumer<T>

  • 메소드 이름: accept

  • 인자 타입: T

  • 반환값 타입: 없음

  • 설명: 입력된 매개변수(T)를 받아서 처리하고, 결과를 반환하지 않는 함수형 인터페이스입니다.

import java.util.function.Consumer;

public class ConsumerExample {
    public static void main(String[] args) {
        Consumer<String> consumer = message -> System.out.println("Consumed: " + message);
        consumer.accept("Hello, Consumer!");
    }
}

BiConsumer<T, U>

  • 메소드 이름: accept

  • 인자 타입: T, U

  • 반환값 타입: 없음

  • 설명: 두 개의 매개변수(T, U)를 받아서 처리하고, 결과를 반환하지 않는 함수형 인터페이스입니다.

import java.util.function.BiConsumer;

public class BiConsumerExample {
    public static void main(String[] args) {
        BiConsumer<String, Integer> biConsumer = (name, age) ->
                System.out.println("Name: " + name + ", Age: " + age);
        biConsumer.accept("John", 25);
    }
}

Function<T, R>

  • 메소드 이름: apply

  • 인자 타입: T

  • 반환값 타입: R

  • 설명: 입력값(T)을 받아서, 결과값(R)을 반환하는 함수형 인터페이스입니다. 주로 입력을 변환하여 출력하는 역할을 합니다.

import java.util.function.Function;

public class FunctionExample {
    public static void main(String[] args) {
        Function<Integer, String> function = number -> "Number: " + number;
        System.out.println(function.apply(10));
    }
}

BiFunction<T, U, R>

  • 메소드 이름: apply

  • 인자 타입: T, U

  • 반환값 타입: R

  • 설명: 두 개의 입력값(T, U)을 받아서, 결과값(R)을 반환하는 함수형 인터페이스입니다.

import java.util.function.BiFunction;

public class BiFunctionExample {
    public static void main(String[] args) {
        BiFunction<Integer, Integer, Integer> biFunction = (a, b) -> a + b;
        System.out.println("Sum: " + biFunction.apply(10, 20));
    }
}

Predicate<T>

  • 메소드 이름: test

  • 인자 타입: T

  • 반환값 타입: boolean

  • 설명: 입력값을 받아 조건을 검사하여 참 또는 거짓을 반환하는 함수형 인터페이스입니다.

import java.util.function.Predicate;

public class PredicateExample {
    public static void main(String[] args) {
        Predicate<Integer> isEven = number -> number % 2 == 0;
        System.out.println("Is 4 even? " + isEven.test(4));
    }
}

BiPredicate<T, U>

  • 메소드 이름: test

  • 인자 타입: T, U

  • 반환값 타입: boolean

  • 설명: 두 개의 입력값을 받아 조건을 검사하여 참 또는 거짓을 반환하는 함수형 인터페이스입니다.

import java.util.function.BiPredicate;

public class BiPredicateExample {
    public static void main(String[] args) {
        BiPredicate<Integer, Integer> isSumEven = (a, b) -> (a + b) % 2 == 0;
        System.out.println("Is the sum of 3 and 5 even? " + isSumEven.test(3, 5));
    }
}

UnaryOperator<T>

  • 메소드 이름: apply

  • 인자 타입: T

  • 반환값 타입: T

  • 설명: 동일한 타입의 값을 입력받아 같은 타입의 값을 반환하는 함수형 인터페이스입니다. Function<T, R>의 특수한 형태로, 입력과 출력 타입이 동일할 때 사용합니다.

import java.util.function.UnaryOperator;

public class UnaryOperatorExample {
    public static void main(String[] args) {
        UnaryOperator<String> toUpperCase = str -> str.toUpperCase();
        System.out.println(toUpperCase.apply("hello"));
    }
}

BinaryOperator<T>

  • 메소드 이름: apply

  • 인자 타입: T, T

  • 반환값 타입: T

  • 설명: 두 개의 동일한 타입의 값을 입력받아 같은 타입의 값을 반환하는 함수형 인터페이스입니다. BiFunction<T, U, R>의 특수한 형태로, 두 입력값과 결과값이 모두 같은 타입일 때 사용합니다.

import java.util.function.BinaryOperator;

public class BinaryOperatorExample {
    public static void main(String[] args) {
        BinaryOperator<Integer> multiply = (a, b) -> a * b;
        System.out.println("Product: " + multiply.apply(3, 4));
    }
}

메소드 참조(Method reference)

람다식이 어떤 메소드 하나만 호출할 때(해당 람다식과 메소드의 의미가 사실상 같을 때) 코드를 간편화하는 방법입니다.

클래스 메소드 호출

{클래스명}::{클래스 메소드명}
  • 설명: 클래스의 정적 메소드(static method)를 참조할 때 사용합니다.

  • 예시: Integer 클래스의 parseInt 메소드를 참조하는 예시.

edu.ch11.methodReference 패키지

import java.util.function.Function;

public class Example {
    public static void main(String[] args) {
        // 람다식: (String s) -> Integer.parseInt(s)
        Function<String, Integer> func = Integer::parseInt;

        // 메소드 참조로 사용
        Integer number = func.apply("123");
        System.out.println(number);  // 출력: 123
    }
}

인스턴스 메소드 호출

(1) 특정 클래스의 인스턴스 메소드 참조

{클래스명}::{인스턴스메소드명}
  • 설명: 클래스의 인스턴스 메소드를 참조할 때 사용합니다. 이 경우 첫 번째 매개변수는 해당 클래스의 인스턴스가 됩니다.

  • 예시: String 클래스의 toUpperCase 메소드를 참조하는 예시.

edu.ch11.methodReference 패키지

import java.util.function.Function;

public class ClassMethodExample {
    public static void main(String[] args) {
        // 람다식: (String s) -> s.toUpperCase()
        Function<String, String> func = String::toUpperCase;

        // 메소드 참조로 사용
        String result = func.apply("hello");
        System.out.println(result);  // 출력: HELLO
    }
}

(2) 특정 인스턴스의 인스턴스 메소드 참조

{인스턴스}::{인스턴스메소드명}
  • 설명: 특정 인스턴스의 메소드를 참조할 때 사용합니다.

  • 예시: 특정 Example 인스턴스의 메소드를 참조하는 예시.

edu.ch11.methodReference 패키지

import java.util.function.Consumer;

public class InstanceMethodExample {
    public void printMessage(String message) {
        System.out.println(message);
    }

    public static void main(String[] args) {
        InstanceMethodExample instanceMethodExample
                = new InstanceMethodExample();

        // 람다식: (String s) -> example.printMessage(s)
        Consumer<String> consumer = instanceMethodExample::printMessage;

        // 메소드 참조로 사용
        consumer.accept("Hello, World!");  // 출력: Hello, World!
    }
}

3. 클래스 생성자 호출

{클래스}::new
  • 설명: 해당 클래스의 생성자를 참조하여 객체를 생성할 때 사용합니다.

  • 예시: Person 객체를 생성하는 생성자 참조 예시.

edu.ch11.methodReference 패키지

import java.util.function.Supplier;

class Person {
    public Person() {
        System.out.println("Person 객체가 생성되었습니다.");
    }
}

public class ConstructMethodExample {
    public static void main(String[] args) {
        // 람다식: () -> new Person()
        Supplier<Person> supplier = Person::new;

        // 생성자 참조로 사용
        Person person = supplier.get();  // 출력: Person 객체가 생성되었습니다.
    }
}

정리

  • 클래스 메소드 호출: {클래스명}::{클래스 메소드명}을 사용하여 정적 메소드를 참조할 수 있습니다.

  • 인스턴스 메소드 호출:

    • 특정 클래스의 인스턴스 메소드를 참조하려면 {클래스명}::{인스턴스메소드명}을 사용합니다.

    • 특정 인스턴스의 메소드를 참조하려면 {인스턴스}::{인스턴스메소드명}을 사용합니다.

  • 생성자 호출: {클래스}::new를 사용하여 생성자를 참조하고 객체를 생성할 수 있습니다.

메소드 참조를 사용하면 람다식을 더욱 간결하고 가독성 좋게 표현할 수 있습니다.

스트림(Stream)과 스트림 연산(Stream Operations)

스트림(Stream)은 자바 8(Java 8)에서 도입된 기능으로, 컬렉션이나 배열의 요소를 처리하는 선언적이고 간결한 방법을 제공합니다.

스트림을 통해 데이터의 필터링, 매핑, 정렬, 집계 등의 다양한 연산을 할 수 있으며, 이를 스트림 연산(Stream Operations)이라고 합니다.

1. 스트림이란?

  • 데이터의 연속적인 흐름: 스트림은 컬렉션, 배열 등의 데이터를 다루기 위한 데이터의 연속적인 흐름입니다.

  • 데이터 소스로부터 추상화: 스트림은 데이터 소스(예: 컬렉션, 배열)로부터 데이터를 추상화하여 처리할 수 있습니다.

  • 한 번만 소비 가능: 스트림은 일회용이며, 한 번 사용한 스트림은 재사용할 수 없습니다.

  • 데이터를 변경하지 않음: 스트림은 원본 데이터를 변경하지 않고, 데이터의 복사본을 처리합니다.

  • 지연 연산: 스트림 연산은 지연 평가(Lazy Evaluation) 방식을 사용하여 필요한 때까지 연산을 수행하지 않습니다.

2. 스트림 연산의 종류

스트림 연산은 크게 중간 연산과 최종 연산으로 나눌 수 있습니다.

  • 중간 연산: 스트림을 가공하여 새로운 스트림을 반환하는 연산입니다. 여러 개의 중간 연산을 체인(chain)으로 연결할 수 있습니다. 예를 들어, filter(), map(), sorted() 등이 중간 연산에 해당합니다.

  • 최종 연산: 스트림을 소비하여 결과를 반환하는 연산입니다. 최종 연산이 호출되면 스트림이 종료되고 더 이상 사용할 수 없습니다. 예를 들어, forEach(), collect(), reduce() 등이 최종 연산에 해당합니다.

3. 스트림 생성

스트림은 다양한 소스(배열, 값, 컬렉션, 빌더, concat 메소드 등)로부터 생성할 수 있습니다. 대표적으로 컬렉션이나 배열에서 스트림을 생성하는 방법은 다음과 같습니다:

  • 컬렉션에서 스트림 생성:

edu.ch11.stream 패키지

import java.util.Arrays;
import java.util.List;

public class CollectionStreamExample {
    public static void main(String[] args) {
        List<String> list = Arrays.asList("Apple", "Banana", "Cherry");

        // 컬렉션에서 스트림 생성
        list.stream()
                .forEach(System.out::println);
    }
}
  • 배열에서 스트림 생성:

edu.ch11.stream 패키지

import java.util.Arrays;

public class ArrayStreamExample {
    public static void main(String[] args) {
        String[] fruits = {"Apple", "Banana", "Cherry"};

        // 배열에서 스트림 생성
        Arrays.stream(fruits)
                .forEach(System.out::println);
    }
}

4. 중간 연산 예시

1. filter(Predicate)

  • 요소를 걸러내는 연산으로, 조건에 맞는 요소만 포함하는 새로운 스트림을 반환합니다.

edu.ch11.streamOperations 패키지

import java.util.Arrays;
import java.util.List;

public class FilterExample {
    public static void main(String[] args) {
        List<String> list = Arrays.asList("Apple", "Banana", "Cherry", "Avocado");

        // 'A'로 시작하는 문자열만 필터링
        list.stream()
                .filter(s -> s.startsWith("A"))
                .forEach(System.out::println);  // 출력: Apple, Avocado
    }
}

2. map(Function)

  • 각 요소를 주어진 함수에 의해 매핑하여 새로운 요소로 변환하는 연산입니다.

edu.ch11.streamOperations 패키지

import java.util.Arrays;
import java.util.List;

public class MapExample {
    public static void main(String[] args) {
        List<String> list = Arrays.asList("Apple", "Banana", "Cherry");

        // 문자열의 길이를 반환하는 스트림
        list.stream()
                .map(String::length)
                .forEach(System.out::println);  // 출력: 5, 6, 6
    }
}

3. sorted()

  • 스트림의 요소를 정렬하는 연산입니다.

edu.ch11.streamOperations 패키지

import java.util.Arrays;
import java.util.List;

public class SortedExample {
    public static void main(String[] args) {
        List<String> list = Arrays.asList("Banana", "Apple", "Cherry");

        // 문자열을 알파벳 순서로 정렬
        list.stream()
                .sorted()
                .forEach(System.out::println);  // 출력: Apple, Banana, Cherry
    }
}

4. distinct()

  • 스트림의 요소 중 중복된 요소를 제거합니다.

edu.ch11.streamOperations 패키지

import java.util.Arrays;
import java.util.List;

public class DistinctExample {
    public static void main(String[] args) {
        List<String> list = Arrays.asList("Apple", "Banana", "Apple", "Cherry");

        // 중복된 요소 제거
        list.stream()
                .distinct()
                .forEach(System.out::println);  // 출력: Apple, Banana, Cherry
    }
}

5. 최종 연산 예시

1. forEach(Consumer)

  • 각 요소에 대해 주어진 동작을 수행하는 연산입니다.

edu.ch11.streamOperations 패키지

import java.util.Arrays;
import java.util.List;

public class ForEachExample {
    public static void main(String[] args) {
        List<String> list = Arrays.asList("Apple", "Banana", "Cherry");

        // 각 요소를 출력
        list.stream()
                .forEach(System.out::println);  // 출력: Apple, Banana, Cherry
    }
}

2. collect()

  • 스트림의 요소를 컬렉션으로 수집하는 연산입니다. 주로 Collectors 유틸리티 클래스를 함께 사용합니다.

edu.ch11.streamOperations 패키지

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class CollectExample {
    public static void main(String[] args) {
        List<String> list = Arrays.asList("Apple", "Banana", "Cherry");

        // 스트림을 리스트로 수집
        List<String> result = list.stream()
                .filter(s -> s.startsWith("A"))
                .collect(Collectors.toList());

        System.out.println(result);  // 출력: [Apple]
    }
}

3. reduce()

  • 스트림의 모든 요소를 결합하여 하나의 값을 생성하는 연산입니다.

edu.ch11.streamOperations 패키지

import java.util.Arrays;
import java.util.List;

public class ReduceExample {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);

        // 모든 요소의 합 계산
        int sum = numbers.stream()
                .reduce(0, (a, b) -> a + b);

        System.out.println(sum);  // 출력: 15
    }
}

6. 스트림의 특징: 지연 연산

  • 지연 연산(Lazy Evaluation): 스트림의 중간 연산은 최종 연산이 호출될 때까지 실제로 수행되지 않습니다. 이로 인해 불필요한 연산을 방지하고, 성능을 최적화할 수 있습니다.

정리

  • 스트림(Stream)은 자바의 컬렉션, 배열 등의 요소를 효율적으로 처리하기 위한 기능으로, 데이터의 필터링, 매핑, 정렬, 집계 등의 다양한 연산을 제공합니다.

  • 스트림 연산은 중간 연산과 최종 연산으로 나뉘며, 중간 연산은 새로운 스트림을 반환하고 최종 연산은 스트림을 소비하여 결과를 반환합니다.

Previous컬렉션 프레임워크 보충자료Next람다식 보충자료

Last updated 5 months ago