orElse vs orElseGet

Java에서 Optional<T>을 사용할 때, orElse와 orElseGet은 Optional이 비어 있을 경우 기본값을 제공하는 메서드이다.
하지만 두 메서드가 작동하는 방식에는 중요한 차이점이 있다.

핵심 차이:

  • orElse(T other): 기본값을 항상 계산하고, Optional이 비어 있으면 반환.
  • orElseGet(Supplier<? extends T> supplier): Optional이 비어 있을 때만 기본값을 계산.

1. orElse 동작 방식

기본값을 "항상" 계산하는 메서드

  • Optional이 값이 있든 없든 항상 orElse에 전달된 값이 평가(계산)된다.
  • 즉, Optional이 값이 있을 때도 불필요한 연산이 실행될 수 있다.

orElse 예제

public class OrElseExample {
    public static String getDefaultValue() {
        System.out.println("getDefaultValue() 호출됨");
        return "기본값";
    }

    public static void main(String[] args) {
        Optional<String> optional = Optional.ofNullable("안녕하세요");

        String result = optional.orElse(getDefaultValue()); // getDefaultValue()가 실행될까?
        System.out.println("결과: " + result);
    }
}

실행 결과

getDefaultValue() 호출됨
결과: 안녕하세요

 

왜 이런 결과가 나왔을까?

  • Optional에는 "안녕하세요"라는 값이 이미 존재한다.
  • 그런데도 getDefaultValue()가 무조건 실행되었다.
  • 즉, 기본값이 필요하지 않더라도 연산이 발생하는 비효율적인 상황이 생길 수 있다.

2. orElseGet 동작 방식

기본값을 "필요할 때만" 계산하는 메서드

  • Optional이 비어 있을 때만 Supplier(람다 함수)를 실행한다.
  • 즉, 값이 존재하면 불필요한 연산을 하지 않는다.

orElseGet 예제

public class OrElseGetExample {
    public static String getDefaultValue() {
        System.out.println("getDefaultValue() 호출됨");
        return "기본값";
    }

    public static void main(String[] args) {
        Optional<String> optional = Optional.ofNullable("안녕하세요");

        String result = optional.orElseGet(() -> getDefaultValue()); // getDefaultValue()가 실행될까?
        System.out.println("결과: " + result);
    }
}

실행 결과

결과: 안녕하세요

 

이번에는 getDefaultValue()가 실행되지 않았다!

  • Optional에 "안녕하세요"라는 값이 있으므로 기본값을 만들 필요가 없기 때문이다.
  • 즉, orElseGet은 연산을 최소화할 수 있도록 도와준다.

 

3. orElse vs orElseGet 비교

비교 표

메서드 기본값 평가 시점 최적화 가능 여  언제 사용해야 할까?
orElse(T other) 항상 평가됨 ❌ 비효율적
(불필요한 연산 가능)
기본값이 가벼운 경우
orElseGet(Supplier<? extends T> supplier) 필요할 때만 평가됨 ✅ 최적화 가능 기본값을 생성하는 연산이 무거운 경우
(DB 조회, 파일 읽기 등)

orElse의 문제점

Optional<String> optional = Optional.ofNullable("데이터 있음");
String result = optional.orElse(getDataFromDatabase()); // DB 조회가 필요할까?
  • Optional에 값이 있음에도 DB 조회가 실행됩니다!
  • 연산 비용이 큰 작업이 불필요하게 실행될 수 있습니다.

해결 방법 → orElseGet 사용

Optional<String> optional = Optional.ofNullable("데이터 있음");
String result = optional.orElseGet(() -> getDataFromDatabase()); // 필요할 때만 실행됨!
  • Optional이 비어 있을 때만 DB 조회가 실행됩니다.
  • 연산 비용이 큰 작업일 경우, 반드시 orElseGet을 사용하세요.

4. 실전 예제: 성능 차이 확인

orElse vs orElseGet 비교 실험

public class OrElseVsOrElseGet {
    public static String expensiveOperation() {
        System.out.println("💰 비용이 큰 연산 실행 중...");
        return "연산 결과";
    }

    public static void main(String[] args) {
        System.out.println("📌 `orElse` 사용:");
        Optional<String> optional1 = Optional.of("값 있음");
        String result1 = optional1.orElse(expensiveOperation());

        System.out.println("\n📌 `orElseGet` 사용:");
        Optional<String> optional2 = Optional.of("값 있음");
        String result2 = optional2.orElseGet(() -> expensiveOperation());
    }
}

실행 결과

📌 `orElse` 사용:
💰 비용이 큰 연산 실행 중...

📌 `orElseGet` 사용:
  • orElse는 값이 있어도 expensiveOperation()이 실행됨. (비효율적❌)
  • orElseGet은 값이 있으면 실행되지 않음. (최적화 가능✅)

 

5. 언제 orElse를 쓰고 언제 orElseGet을 써야 할까?

기본값이 간단한 값이라면 → orElse 사용

String result = optional.orElse("기본값");
  • "기본값"처럼 가벼운 값이라면 orElse가 편리함.

기본값을 생성하는 연산이 무겁다면 → orElseGet 사용

String result = optional.orElseGet(() -> getDataFromDatabase());
  • getDataFromDatabase()처럼 실행 비용이 큰 경우, orElseGet을 사용하여 불필요한 연산을 방지.

 

결론

  • orElse는 기본값 연산이 항상 실행되므로, 연산 비용이 크다면 orElseGet을 사용하는 것이 좋다.
  • orElseGet은 Optional이 비어 있을 때만 연산하므로, 불필요한 연산을 방지할 수 있다.
  • 성능 최적화를 위해 기본값을 미리 계산할 필요가 없는 경우 orElseGet을 적극 활용하자!

 

참조
https://ysjune.github.io/posts/java/orelsenorelseget/

'Web Programming Language > JAVA' 카테고리의 다른 글

BitSet 클래스  (0) 2025.02.17
DTO와 VO  (0) 2025.02.12
Records  (1) 2025.02.12
JAVA) print, printf, println 차이점  (0) 2021.03.11
JAVA) Java 프로그램 실행 구조  (0) 2020.11.18

print : 괄호안 내용을 단순히 출력. 개행문자(=줄바꿈문자=\n) 포함안됨.

printf : C에서의 printf와 동일. %d, %s 등을 쓰기위해 사용. 개행문자 포함X

println : 괄호안 내용을 출력한 후 마지막에 개행문자가 포함되어 있어 출력후 한 줄 띄워짐.

 

<예시>

public class ThreadTest extends Thread{
	public static void main(String[] args) {
		int num = 5;
		System.out.print("print ! " + num + "\n");	//print
		System.out.printf("printf ! %d \n", num);	//printf
		System.out.println("println ! " + num);		//println
	}
}

 

결과화면

println 에는 개행문자가 없는데 밑에 한칸 띄워져 있음 !

 

 

 

 

 

출처 :

moon1226.tistory.com/12

 

 

 

 

자바의 출력문(println, printf)

 

출력 - println()

 

개발자가 열심히 프로그래밍을 하더라도 결과를 볼 수 있는 명령문을 실행하지 않으면 절대 직접 눈으로 볼 수 없다. 결과를 봐야 이 프로그램이 내가 생각한대로 잘 돌아가고 있는지 알 수 있다. println은 자바에서의 기본 출력문으로 가장 많이 사용되며 출력하고 싶은 내용 그대로를 입력하여 출력한다.

 

println()

System.out.println("문자열");

          또는

System.out.println(변수명);

          또는

System.out.println("문자열"+변수명);

  • 문자열을 출력하기 위해서는 큰따옴표로 묶어줘야 한다.

  • 큰 따옴표 없는 것은 모두 변수명으로 인식한다. (입력한 변수명이 없을 경우 에러발생)

  • 문자열과 변수명을 함께 사용할 수 있으나 반드시 '+'로 연결시켜줘야 한다.

  • 가로안의 내용을 출력한 후 자동으로 줄바꾸는 기능이 있다.

Tip) 이클립스에서는 'sysout' 이라고 입력하고 'ctrl+space'를 누르면 System.out.println()이 자동 입력된다.

 

 

◈ 예제

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

public class Println {

 

    public static void main(String[] args) {

        //기본 출력문 println()        

        //sysout + 자동완성(ctrl + space)

        

        int number = 10;

        String str = "안녕, 자바";

        

        System.out.println("Hello, World."); //문자열 출력

        System.out.println(number); //int형 변수 출력

        System.out.println(str); // String형 변수 출력

        System.out.println("내 나이는 "+number+"살 입니다."); // 문자열 + 변수 출력        

        

    }//main

 

}//class

                                                                             Colored By Color Scripter

 

실행 결과

Hello, World.

10

안녕, 자바

내 나이는 10살 입니다.

 

· String과 기본형은 저장된 값 그대로 출력된다.

· 변수와 문자열을 '+'로만 이어주면 같이 사용할 수 있다.

· 실행 결과를 보면 자동으로 내용을 출력 후 줄바꿈 기능이 있는걸 볼 수 있다. 절대로 명령문을 한줄에 하나씩 써서 줄바꿈이 된 것이 아니다.

 

 

 

No. 02

 

 

형식화된 출력 - printf()

 

기본 출력문은 println()은 변수의 값을 그대로 출력하므로, 값을 변환하지 않고는 다른 형식으로 출력할 수 없다.

반면에 printf()는 지시자를 통해 변수의 값을 여러 가지 형식으로 변환하여 출력할 수 있다.

 

printf()

System.out.printf("출력 서식",출력할 내용);

  • 출력 후 줄바꿈을 하지 않는다. 줄바꿈을 하려면 지시자 '%n'을 넣어줘야 한다.

  • 출력하려는 값의 수만큼 지시자도 사용해야 한다.

  • 출력될 값과 지시자의 순서는 일치해야 한다.

  • 지시자를 제외한 문자는 입력한 그대로 출력된다.

 

출력 서식

%[-][0][n][.m]지시자

  • 출력 서식의 지시자를 제외한 나머지는 생략 가능하다. 예) %d 식으로 사용 가능.

  • n : 출력할 전체 자리수 지정(오른쪽 정렬).  예) %3d, 전체자리수가 3인 정수

  • 0 : 전체 자리수가 지정된 경우 왼쪽의 남는 자리에 0을 출력.  예) %03d

  • - : 전체 자리수가 지정된 경우 왼쪽 정렬하고 빈칸에 공백 출력.

  • .m : 소수점 아래 자리수 지정. 잘리는 소수점 자리수는 반올림 시켜서 표시.  예)3.2f

 

 지시자

설명 

 %b

 boolean 형식으로 출력 

 %d

 정수 형식으로 출력

 %o

 8진수 정수의 형식으로 출력

 %x 또는 %X

 16진수 정수의 형식으로 출력

 %f

 소수점 형식으로 출력

 %c

 문자형식으로 출력 

 %s

 문자열 형식으로 출력

 %n  줄바꿈 기능

 %e 또는 %E

 지수 표현식의 형식으로 출력

 

 

◈ 예제1

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

public class Printf {

 

    public static void main(String[] args) {

        

        int age = 10;        

        String addr = "경기도";

        

        //'%n'지시자를 사용 안 했을 경우

        System.out.printf("줄바꿈 기능");

        System.out.printf("없음.");

        

        //'%n'지시자를 사용한 경우

        System.out.printf("줄바꾸기%n");

        System.out.printf("성공!%n");

        

        System.out.printf("내 나이는 %d살 입니다.%n",age);

        System.out.printf("내 나이는 %d살 이고 %s에 살고 있습니다.%n",age,addr);

        

    }//main

 

}//class

                                                                  Colored By Color Scripter

 

실행 결과

줄바꾸기 기능없음.줄바꾸기

성공!

내 나이는 10살 입니다.

내 나이는 10살이고 경기도에 살고 있습니다.

 

· 기본적으로 줄바꿈 기능이 없고 '%n'지시자를 사용한 곳에서 줄바꾸는 기능을 하는 것을 볼 수 있다.

· 지시자의 수와 출력하려는 값의 수는 같아야 하며 출력하려는 값은 콤마(',')로 구분한다.

· 출력하려는 값은 지시자의 순서와 같아야 한다.

· 지시자의 형식과 출력하려는 값의 형식이 같지 않으면 에러가 발생한다.

 

 

◈ 예제2

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

public class Printf {

 

    public static void main(String[] args) {

        //자리수 지정은 안 했을 경우 왼쪽으로 정렬된다.

        System.out.printf("자리수 미지정 :%d%n",1);

        System.out.printf("자리수 미지정 :%d%n",10);

        System.out.printf("자리수 미지정 :%d%n",100);

        System.out.printf("자리수 미지정 :%d%n",1000);

        

        //자리수 지정했을 경우  오른쪽으로 정렬된다.(남는 자리수는 공백)

        System.out.printf("자리수 지정 :%4d%n",1);

        System.out.printf("자리수 지정 :%4d%n",10);

        System.out.printf("자리수 지정 :%4d%n",100);

        System.out.printf("자리수 지정 :%4d%n",1000);

        

        //자리수 지정 후 '-'사용하면 왼쪽으로 정렬된다.

        System.out.printf("자리수 지정('-'사용) :%-4d%n",1);

        System.out.printf("자리수 지정('-'사용) :%-4d%n",10);

 

        System.out.printf("자리수 지정('-'사용) :%-4d%n",100);

 

        System.out.printf("자리수 지정('-'사용) :%-4d%n",1000);

 

        

        //자리수 지정 후 '0'사용하면 오른쪽으로 정렬된다. (왼쪽 자리수는 0으로 채운다)

        System.out.printf("자리수 지정('0'사용) :%04d%n",1);

        System.out.printf("자리수 지정('0'사용) :%04d%n",10);

        System.out.printf("자리수 지정('0'사용) :%04d%n",100);

        System.out.printf("자리수 지정('0'사용) :%04d%n",1000);

        

    }//main

 

}//class

                                                                       Colored By Color Scripter

 

실행 결과

자리수 미지정 :1

자리수 미지정 :10

자리수 미지정 :100

자리수 미지정 :1000

자리수 지정 :    1 

자리수 지정 :  10

자리수 지정 : 100

자리수 지정 :1000

자리수 지정('-'사용) :1

자리수 지정('-'사용) :10

자리수 지정('-'사용) :100

자리수 지정('-'사용) :1000

자리수 지정('0'사용) :0001

자리수 지정('0'사용) :0010

자리수 지정('0'사용) :0100

자리수 지정('0'사용) :1000

 

 

◈ 예제3

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

public class Printf {

 

    public static void main(String[] args) {

        

        float f = 1.2345f;

        

        //소수점 자리수 미지정시

        System.out.printf("소수점 자리수 미지정 : %f%n",f);

        //소수점 자리 지정시

        System.out.printf("소수점 자리수 지정 : %.3f%n",f);    

        

    }//main

 

}//class

                                           Colored By Color Scripter 

 

실행 결과

소수점 자리수 미지정 : 1.234500

소수점 자리 지정 : 1.235

 

· 소수점 자리를 3자리로 지정했기 때문에 4번째 자리에서 반올림한 결과를 출력한다.

 

 

 

출처 :

keep-cool.tistory.com/15

'Web Programming Language > JAVA' 카테고리의 다른 글

BitSet 클래스  (0) 2025.02.17
DTO와 VO  (0) 2025.02.12
Records  (1) 2025.02.12
orElse vs orElseGet 차이점  (0) 2025.02.12
JAVA) Java 프로그램 실행 구조  (0) 2020.11.18

Java 프로그램 실행 구조

(Java 소스 작성부터 프로그램 실행까지의 순서)

 

 

 

 

출처

: 인프런 - 자바 프로그래밍 입문

'Web Programming Language > JAVA' 카테고리의 다른 글

BitSet 클래스  (0) 2025.02.17
DTO와 VO  (0) 2025.02.12
Records  (1) 2025.02.12
orElse vs orElseGet 차이점  (0) 2025.02.12
JAVA) print, printf, println 차이점  (0) 2021.03.11

+ Recent posts