자바

 

1. 함수형 프로그래밍 소개

  • 함수형 프로그래밍은 기존 사고방식에서 벗어나 새로운 패러다임으로 문제를 해결하는 방식.
  • 이 강의의 목표:
    1. 함수형 프로그래밍의 차이를 이해하기.
    2. 함수형 프로그래밍의 기본 개념 학습.

 

 

2. 첫 번째 섹션 목표

  • 주요 학습 개념:
    • 스트림(Stream)
    • 람다식(Lambda Expression)
    • 메서드 참조(Method Reference)

 

 

3. 첫 번째 실습: 숫자 리스트 출력

전통적인 접근법 (구조적 프로그래밍)

  1. 문제 정의: 숫자 리스트를 생성하고 리스트의 각 숫자를 한 줄씩 출력.

  2. 구현 단계:

    • 프로젝트 생성: Eclipse에서 Java 프로젝트 생성.
      • 프로젝트 이름: functional programming with java
      •  
    • 클래스 생성: FP01Structured 클래스 생성.
      • 메서드: printAllNumbersInListStructured

 

숫자 리스트 생성:

List<Integer> numbers = List.of(12, 9, 13, 4, 6, 2, 4, 12, 15);

 

향상된 for 루프 사용:

for (int number : numbers) {
    System.out.println(number);
}

 

  • 출력 결과:

    • 숫자 리스트의 각 요소가 콘솔에 한 줄씩 출력됨.

 

  • 구조적 프로그래밍의 특징:

    • 문제 해결 시 "방법"에 초점을 맞춤.
    • 루프 방식 결정 후 작업 수행.

 

5. 다음 단원 예고

  • 함수형 프로그래밍으로 동일한 문제를 해결하는 방법 소개.

 

 

 

 

 

2.숫자 리스트를 함수형 접근법으로 출력하기

 

1. 목표

  • 숫자 리스트의 모든 숫자를 함수형 접근법으로 출력합니다.

2. 주요 단계

  1. )메서드 이름 변경

    • 메서드 이름을 printAllNumbersInListFunctional로 수정합니다.
    • Refactor → Rename 기능을 사용.
  2. )리스트를 스트림으로 변환

    • numbers.stream()을 호출하여 리스트를 스트림(Stream)으로 변환.
    • 스트림은 리스트 요소를 순차적으로 처리할 수 있는 데이터 시퀀스를 생성.
  3. )각 숫자에 수행할 작업 정의

    • 각 숫자에 대해 수행할 작업을 지정:
      • 여기서는 숫자를 출력.
  4. )출력을 담당할 메서드 작성

 

print 메서드 생성

private static void print(int number) {
    System.out.println(number);
}

 

5.메서드 참조를 사용한 동작 정의

  • 스트림의 각 요소에 대해 print 메서드를 호출
numbers.stream().forEach(FP01Functional::print);


메서드 참조 문법:

  • 클래스명::메서드명
  • 여기서는 FP01Functional::print.

 

6.출력 결과

  • 스트림으로 변환된 각 숫자가 print 메서드에 의해 출력.

 

3.코드 설명

  • 리스트를 스트림으로 변환: numbers.stream()
  • 동작 정의: forEach 메서드와 메서드 참조(::)를 사용해 동작을 지정.
  • 출력 구현: print 메서드로 스트림의 각 요소를 출력.

 

4. 최종 코드

import java.util.List;

public class FP01Functional {
    public static void main(String[] args) {
        List<Integer> numbers = List.of(12, 9, 13, 4);
        printAllNumbersInListFunctional(numbers);
    }

    private static void printAllNumbersInListFunctional(List<Integer> numbers) {
        numbers.stream().forEach(FP01Functional::print);
    }

    private static void print(int number) {
        System.out.println(number);
    }
}

 

numbers.stream().forEach(number->System.out.println(number));



 

5. 실행 결과

  • 숫자 리스트가 순서대로 출력:
12
9
13
4

 

 

 

 

 

3.함수형 접근법과 구조적 접근법 비교 및 코드 간소화

 

1. 구조적 접근법 (FPStructured)

  • 리스트의 숫자 출력:
    • 루프를 통해 숫자를 하나씩 출력.
  •  
    • 짝수만 출력하려면 조건 추가

 

if (number % 2 == 0) { 
    System.out.println(number); 
}

 

리스트를 지역 변수로 추출해 코드 재사용성 향상.

 

2. 함수형 접근법 (FP01Functional)

  • 기본 코드

    • 스트림의 각 요소에 작업을 수행.
    • System.out::println으로 출력 간소화

 

numbers.stream().forEach(System.out::println);

 

짝수 필터링

  • .filter 메서드를 활용해 조건 추가

 

numbers.stream()
       .filter(FP01Functional::isEven)
       .forEach(System.out::println);

 

스태틱 메서드 활용: isEven 정의

private static boolean isEven(int number) {
    return number % 2 == 0;
}

 

3. 메서드 참조 및 함수형 스타일의 간소화

  • 메서드 참조를 통해 더 간결하게 작성:
    • FP01Functional::isEven으로 조건 전달.
    • 스트림에서 숫자 필터링 후 출력 작업.

 

 

4. 향후 개선 방향

  • 람다 표현식 사용:
    • isEven 메서드 없이 조건을 바로 작성
numbers.stream()
       .filter(number -> number % 2 == 0)
       .forEach(System.out::println);

메서드 정의 없이 코드 단순화 가능.

 

 

 

 

 

1)어진 문자열 리스트(교육 과정)를 한 줄씩 출력

List<String> courses = Arrays.asList(
    "Spring", "Spring Boot", "API", "Microservices", 
    "AWS", "PCF", "Azure", "Docker", "Kubernetes"
);

2)스트림으로 변환 후 각 요소 출력

courses.stream()
       .forEach(System.out::println);

 

 

필터 추가

courses.stream()
       .filter(course -> course.contains("Spring"))
       .forEach(System.out::println);

 

 

필터 조건 추가:

courses.stream()
       .filter(course -> course.length() >= 4)
       .forEach(System.out::println);

 

Spring,        Spring Boot,    API, Azure,     Docker,       Kubernetes만 출력.

 

 

 

 

 

4. 함수형 프로그램에서 map 사용하기 

 

1. 짝수 숫자의 제곱 출력

private static void printSquareOfEvenNumbers(List<Integer> numbers) {
    numbers.stream() // 스트림 생성
           .filter(number -> number % 2 == 0) // 짝수 필터링
           .map(number -> number * number) // 제곱 계산
           .forEach(System.out::println); // 결과 출력
}

 

동작

  • stream(): 리스트를 스트림으로 변환합니다. 스트림은 데이터의 흐름을 처리하는 추상화 도구입니다.
  • filter(number -> number % 2 == 0): 각 숫자 중 짝수만 필터링합니다.
  • map(number -> number * number): 필터링된 짝수 숫자를 제곱합니다.
  • forEach(System.out::println): 최종 결과를 출력합니다.

출력 예시

입력 리스트가 [12, 34, 34, 33, 54, 5]라면 짝수는 [12, 34, 34, 54]이고, 제곱값은 다음과 같습니다:

144
1156
1156
2916

 

2. 4자 이상 문자열 필터링

List<String> courses = List.of(
    "spring", "spring boot", "api", "Microseverice",
    "AWS", "PCF", "azure", "docker", "kubernetes"
);

courses.stream()
       .filter(course -> course.length() >= 4) // 문자열 길이가 4 이상인 것만 필터링
       .forEach(System.out::println); // 결과 출력

 

동작

  • filter(course -> course.length() >= 4): 각 문자열의 길이가 4 이상인 항목만 필터링합니다.
  • forEach(System.out::println): 필터링된 문자열을 출력합니다.

출력 예시

List.of(...)에서 길이가 4 이상인 문자열은 [spring, spring boot, Microseverice, azure, docker, kubernetes]입니다:

spring
spring boot
Microseverice
azure
docker
kubernetes

 

3. 문자열과 길이를 함께 출력

courses.stream()
       .map(course -> course + " " + course.length()) // 각 문자열에 길이를 추가
       .forEach(System.out::println); // 결과 출력

 

동작

  • map(course -> course + " " + course.length()): 각 문자열에 해당 문자열의 길이를 결합합니다. 예: "spring" -> "spring 6"
  • forEach(System.out::println): 변환된 결과를 출력합니다.

출력 예시

spring 6
spring boot 11
api 3
Microseverice 13
AWS 3
PCF 3
azure 5
docker 6
kubernetes 10

 

4. 전체 코드 흐름

List<Integer> numbers = List.of(12, 34, 34, 33, 54, 5);
// 짝수 숫자의 제곱 출력
printSquareOfEvenNumbers(numbers);

List<String> courses = List.of("spring", "spring boot", "api", "Microseverice", "AWS", "PCF", "azure", "docker", "kubernetes");

// 문자열 길이가 4 이상인 항목 출력
courses.stream()
       .filter(course -> course.length() >= 4)
       .forEach(System.out::println);

// 각 문자열과 해당 문자열의 길이 출력
courses.stream()
       .map(course -> course + " " + course.length())
       .forEach(System.out::println);

요약

  • Stream API를 활용하여 데이터 처리를 효율적으로 수행.
  • filter: 조건에 맞는 데이터만 추출.
  • map: 데이터를 변환.
  • forEach: 최종 결과 출력.

 

 

 

 

 

 

 

 

 

 

 

5. Optional 클래스 개요

 

Optional 클래스는 NullPointerException(NPE) 문제를 줄이기 위해 Java 8에서 도입된 컨테이너 클래스입니다.

이는 값이 존재할 수도, 존재하지 않을 수도 있는 상황을 처리하는 데 유용합니다.

 

 

배경과 필요성

  • NullPointerException은 Java 애플리케이션에서 가장 흔하고 까다로운 예외 중 하나입니다.
  • 널 참조는 토니 호어가 ALGOL 언어에서 도입했으며, 이를 "십억 달러짜리 실수"라고 부를 정도로 많은 문제를 일으켰습니다.
  • Java에서는 널 사용의 문제를 해결하기 위해 Optional 클래스를 도입했습니다.

 

Optional의 주요 특징

  1. 값의 존재 여부 표현:
    • 값이 존재하면 해당 값을 포함하고, 값이 없으면 Optional.empty()를 반환합니다.
  2. 널 대신 Optional 사용:
    • Optional은 null을 직접 사용하지 않고, 안전하게 값의 존재 여부를 처리할 수 있습니다.

 

 

실습 코드 설명

과일 리스트 생성 및 Optional 활용

  1. 리스트 생성

 

List<String> fruits = List.of("apple", "banana", "mango");

 

   2. b로 시작하는 과일 찾기

Optional<String> optional = fruits.stream()
                                  .filter(fruit -> fruit.startsWith("b"))
                                  .findFirst();

  • stream() 메서드로 리스트를 스트림으로 변환.
  • filter로 조건에 맞는 값을 필터링.
  • findFirst로 조건에 맞는 첫 번째 값을 가져옴.

 

3.Optional 상태 확인

System.out.println(optional);          // 값이 있으면 Optional[값], 없으면 Optional.empty
System.out.println(optional.isEmpty());  // 값이 없으면 true, 있으면 false
System.out.println(optional.isPresent()); // 값이 있으면 true, 없으면 false
System.out.println(optional.get());     // 값이 있으면 해당 값 반환, 없으면 예외 발생

 

요 결과

  1. 조건을 만족하는 값이 있을 경우:

    • Optional[banana] 출력.
    • isEmpty(): false.
    • isPresent(): true.
    • get(): banana.
  2. 조건을 만족하는 값이 없을 경우:

    • Optional.empty 출력.
    • isEmpty(): true.
    • isPresent(): false.
    • get(): 예외 발생 (NoSuchElementException).

 

 

Optional 생성 예시

  1. 값이 있는 Optional 생성:

Optional<String> fruit = Optional.of("banana");


 

2.빈 Optional 생성:

Optional<String> empty = Optional.empty();


 

Optional 사용의 장점

  • NullPointerException 예방: 값이 없을 때 null 대신 Optional.empty()를 반환.
  • 명시적 처리: 값을 다룰 때, 존재 여부를 명확히 확인할 수 있음.
  • 안정성과 가독성: 코드의 안정성을 높이고, null 체크 로직을 간소화.

 

 

 

 

 

about author

PHRASE

Level 60  라이트

양고기 국이 비록 맛이 좋다지만, 여러 사람의 입을 다 맞추기는 어렵다. -명심보감

댓글 ( 0)

댓글 남기기

작성