자바8 - accidentlywoo/java GitHub Wiki

Java 8 lambda

lambda expression?

함수를 단일식으로 표현한것

int min(int x, int y){
  return x<y?x:y;
}

→ lambda

(x,y)-> x<y?x:y;

클래스를 작성하고 객체를 생성하지 않아도 메소드를 사용할 수 있다.

자바에서 클래스의 선언과 공시에 객체를 생성하므로, 단 하나의 객체만을 생성할 수 있는 클래스를 익명 클래스라고 한다. 따라서 람다 표현식은 익명 클래스와 같다고 할 수 있다.

→ 익명 클래스

new Object(){
  int min(int x, int y) {
    return x<y?x:y;
  }
}

람다 표현식은 메서드의 매개변수로 전달될 수도 있으며, 메서드의 결과값으로 반환될 수도 있다.

따라서 람다 표현식을 사용하면, 기존의 불필요한 코드를 줄여주고, 작성된 코드의 가독성을 높여준다.

Java SE8부터는 이러한 람다 표현식을 사용하여 자바에서도 함수향 프로그래밍을 할 수 있게 되었다.

람다 표현식 작성 (매개변수목록)-> {함수몸체} 람다표현식을 작성할 때 유의점

매개변수의 타입을 추론할 수 있는 경우에는 타입을 생략할 수 있다. 매개변수가 하나인 경우에는 괄호(())를 생략할 수 있다. 항수의 몸체가 하나의 명령문만으로 이루어진 경우에는 중괄호({})를 생략할 수 있다.;생략 함수의 몸체가 하나의 return문으로만 이루어진 경우에는 중괄호({})를 생략할 수 없다. return문 대신 표햔식을 사용할 수 있으며, 이때 반환값은 표현식의 결과값이 된다.

스레드 생성과 람다 표현식을 사용한 스레드 생성

new Thread(new Runnable(){ public void run(){ sysout("전통적인 방식의 일회용 스레드 생성"); } }).start();

new Thread(()->{ sysout("람다 표현식을 사용한 일회용 스레드 생성"); })

함수형 인터페이스(Functional interface) 람다 표현식을 사용할 때는 람다 표현식을 저장하기 위한 참조 변수의 타입을 결정해야만 한다.

참조변수의타입 참조변수의이름 = 람다 표현식 람다 표현식을 하나의 변수에 대입할 때 사용하는 참조 변수의 타입을 함수형 인터페이스라 부른다.

함수형 인터페이스는 추상 클래스와는 달리 단 하나의 추상 메소드만을 가져야 한다.

또한, 다음과 같은 annotation을 사용하여 함수형 인터페이스임을 명시할 수 있다.

@FunctionalInterface 위와 같은 어노테이션을 인터페이스의 선언 앞에 붙이면, 컴파일러는 해당 인터페이스를 함수형 인터페이스로 인식한다. 자바 컴파일러는 이렇게 명시된 함수형 인터페이스에 두 개 이상의 메소드가 선언되면 오류를 발생시킨다.

@FunctionalInterface
interface Calc{ //함수형 인터페이스의 선언
  public int min(int x, int y); 
}

public class Lambda02{
  main{
    Calc minNum = (x,y)->x<y?x:y;// 추상 메소드의 구현
    sysout(minNum.min(3,4)); //함수형 인터페이스의 사용
  }
}

자바는 java.util.function패키지를 통해 여러 상황에서 사용할 수 있는 다양한 함수형 인터페이스를 미리 정의하여 제공합니다.

메서드 참조(Method reference) 메서드 참조는 람다 표현식이 단 하나의 메소드만을 호출하는 경우에 해당 람다 표현식에서 불필요한 매개변수를 제거하고 사용할 수 있도록 해줍니다.

메서드 참조를 사용하면 불필요한 매개변수를 제거하고 다음과 같이"::"기호를 사용하여 표현할 수 있다.

클래스이름::메서드이름 또는 참조변수이름::메소드이름

ex)

(base, exponent)-> Math.pow(base, exponent); 위의 예제는 단순히 Math클래스의 pow()메소드로 인수를 전달하는 역할만 하므로, 메서드 참조를 사용하여 다음과 같이 간단히 표현할 수 있다.

Math::pow; 또한, 특정 인스턴스의 메서드를 참조할 때에도 참조 변수의 이름을 통해 메서드 참조를 사용할 수 있다.

MyClass obj = new MyClass; Function<String, Boolean> func = (a)->obj.equals(a);//람다 표현식 Function<String, Boolean> func = obj::equals(a);//메서드 참조

람다 표현식과 메서드 참조 비교 ex)

DoubleUnaryOperator oper;

oper = (n) -> Math.abs(n); //람다 표현식 sysout(oper.applyAsDouble(-5));

oper = Math::abs; //메소드 참조//메서드 참조 sysout(oper.applyAsDouble(-5)); DoubleUnaryOperator 인터페이스는 한 개의 double형 매개변수를 전달받아 한 개의 double형 값을 반환하는 java.util.function패키지에서 제공하는 함수형 인터페이스입니다.

생성자 참조 생성자를 호출하는 람다 표현식도 메서드 참조를 이용할 수 있다.

즉, 단순히 객체를 생성하고 반환하는 람다 표현식은 생성자 참조로 변환할 수 있다.

ex) 단순 객체생성 및 반환하는 람다 표현식

(a) -> {return new Object(a);}}; → 생성자 참조 사용

Object::new; 이때 해당 생성자가 존재하지 않으면 컴파일 시 오류가 발생한다.

또한, 배열을 생성할 때에도 다음과 같이 생성자 참조를 사용할 수 있다.

Function<Integer, double[]> func1 = a-> new double[a];//람다 표현식 Function<Integer, doublep[> func2 = double[]::new;//생성자 참조

Java 8 Stream API

Java SE 8부터 추가된 스트림 API는 앞서 입력과 출력 수업에서 살펴본 스트림과는 전혀 다른 개념.

자바에서 많은 양의 데이터를 저장하기 위해서 배열이나 컬렉션을 사용한다.

이렇게 저장된 데이터에 접근하기 위해서는 반복문이나 iterator를 사용하여 매번 새로운 코드를 작성해야 한다.

하지만 이렇게 작성된 코드는 길이가 너무 길고 가독성도 떨어지며, 코드의 재사용이 거의 불가능하다. 즉, 데이터베이스의 쿼리와 같이 정형화된 처리 패턴을 가지지 못했기에 데이터마다 다른 방법으로 접근해야만 했다.

이러한 문제점을 극복하기 위해 Java SE8부터 스트림(stream) API를 도입한다.

스트림API는 데이터를 추상화하여 다루므로, 다양한 방식으로 저장된 데이터를 읽고 쓰기 위한 공통된 방법을 제공한다. 따라서 스트림 API를 이용하면 배열이나 컬렉션 뿐만 아니라 저장된 데이터도 모두 같은 방법으로 다룰 수 있게 된다.

스트림 API의 특징 스트림은 외부 반복을 통해 작업하는 컬렉션과 달리 internal iteration을 통해 작업을 수행한다. 스트림은 재사용이 가능한 컬렉션과는 달리 단 한 번만 사용할 수 있다. 스트림은 원본 데이터를 변경하지 않는다.immutable 스트임의 연산은 필터-맵(filter-map) 기반의 API를 사용하여 lazy연산을 통해 성능을 최적화한다. 스트림은 parallelStream() 메소드를 통한 손쉬운 병렬 처리를 지원한다.

  • 스트림 API의 동작 흐름 스트림의 생성 스트림의 중개 연산(스트림의 변환) 스트림의 최종 연산(스트림의 사용) 데이터 소스 → 중개 연산(필터) → 중개 연산(맵) → 최종 연산

스트림 생성 스트림 API는 다음과 같은 다양한 데이터 소스에서 생성할 수 있다.

컬렉션 배열 가변 매개변수 지정된 범위의 연속된 정수 특정 타입의 난수들 람다 표현식 파일 빈 스트림

컬렉션 자바에서 제공하는 모든 컬렉션의 최고 상위 조상인 Collection 인터페이스에는 stream() 메소드가 정의되어있다.

따라서 Collection인터페이스를 구현한 모든 List와 Set 컬렉션 클래스에서도 stream() 메소드로 스트림을 생성할 수 있다. 또한, paeallelStream() 메소드를 사용하면 병렬 처리가 가능한 스트림을 생성할 수 있다.

ArrayList<Integer> list = new ArrayList<Integer>();

list.add(4);
list.add(2);
list.add(3);
list.add(1);

//컬렉션에서 스트림 생성 Stream stream = list.stream(); //forEach() 메소드를 이용한 스트림 요소의 순차 접근 stream.forEach(System.out::println); Stream 클래스의 forEach() 메소드는 해당 스트림의 요소를 하나씩 소모해가며 순차적으로 요소에 접근하는 메서드이다.

따라서 같은 스트림으로는 forEach() 메소드를 한 번밖에 호출할 수 없다.

단, 원본 데이터의 요소를 소모하는 것은 아니므로, 같은 데이터에서 또 다른 스트림을 생성하여 forEach()메서드를 호출하는 것은 가능하다.

배열 배열에 관한 스트림을 생성하기 위해 Arrays 클래스에는 다양한 형태의 stream() 메서드가 클래스 메소드로 정의되어 있다.또한, 기본 타입인 int, long, double 형을 저장할 수 있는 배열에 관한 스트림이 별도로 정의되어 있다. 이러한 스트림은 java.util.stream 패키지의 intStream, LongStream, DoubleStream 인터페이스로 각각 제공된다.

String[] arr = new String[]{"넷","둘","셋","하나"};

//배열에서 스트림 생성
Stream<String> stream1 = Arrays.stream(arr);
stream1.forEach(e->Sysout(e+" "));
sysout();

//배열의 특정 부분만을 이용한 스트림 생성
Stream<String> stream2 = Arrays.stream(arr, 1, 3);
stream2.forEach(e-> sysout(e+" ");

Arrays클래스의 stream() 메소드는 전체 배열뿐만 아니라 배열의 특정 부분만을 이용하여 스트림을 생성할 수 도 있다.

가변 매개변수 Stream 클래스의 of()메소드를 사용하면 가변 매개변수(variable parameter)를 전달받아 스트림을 생성할 수 있다.

// 가변 매개변수에서 스트림 생성
Stream<Double> stream = Stream.of(4,2,2.5,3.1,1.9);
stream.forEach(System.out::println);

지정된 범위의 연속된 정수 지정된 범위의 연속된 정수를 스트림으로 생성하기 위해 IntStream나 LongStream인터페이스에는 range()와 rangeClosed() 메소드가 정의되어 있다.

range() 메소드는 명시된 시작 정수를 포함하지만, 명시된 마지막 정수는 포함하지 않는 스트림을 생성한다.rangeClosed() 메소드는 명시된 시작 정수뿐만 아니라 명시된 마지막 정수까지도 포함하는 스트림을 생성한다.

// 지정된 범위의 연속된 정수에서 스트림 생성
IntStream stream1 = IntStream.range(1,4);
stream1.forEach(e-> sysout(e+" ");
sysout();

IntStream stream2 = IntStream.rangeClosed(1,4);
stream2.forEach(e->sysout(e+" "));

특정 타입의 난수들 특정 타입의 난수로 이루어진 스트림을 생성하기 위해 Random 클래스에는 ints(), longs(), doubles() 와 같은 메서드가 정의되어 있다.

이 메서드들은 매개변수로 스트림의 크기를 long타입으로 전달받을 수 있다.

이 메서드들은 만약 매개변수를 전달받지 않으면 크기가 정해지지 않은 무한 스트림(infinite stream)을 반환한다.

이때에 limit() 메서드를 사용하여 따로 스트림의 크기를 제한해야 한다.

// 특정 타입의 난수로 이루어진 스트림 생성 IntStream stream = new Random().ints(4); stream.forEach(System.out::println);

람다 표현식 람다 표현식을 매개변수로 전달받아 해당 람다 표현식에 의해 반환되는 값을 요소로 하는 무한 스트림을 생성하기 위해 Stream 클래스에는 iterate()와 generate() 메소드가 정의되어 있다.

iterate()메서드는 시드(seed)로 명시된 값을 람다 표현식에 사용하여 반환된 값을 다시 시드로 사용하는 방식으로 무한 스트림을 생성한다. 반면에 generate() 메서드는 매개변수가 없는 람다 표현식을 사용하여 반환된 값으로 무한 스트림을 생성한다.

ex) iterate() 메소드를 이용해 홀수만으로 이루어진 무한 스트림을 생성하는 예

IntStream stream = Stream.iterate(2,n->n+2); //2, 4, 6, 8, 10

파일 파일의 한 행(line)을 요소로 하는 스트림을 생성하기 위해 java.nio.file.Files 클래스에는 lines() 메서드가 정의되어 있다.또한 java.io.BufferedReader 클래스의 lines() 메서드를 사용하면 파일뿐만 아니라 다른 입력으로부터도 데이터를 행(line) 단위로 읽어 올 수 있다.

String stream = File.lines(Path path);

빈 스트림 아무 요소도 가지지 않는 빈 스트림은 Stream 클래스의 empty() 메서드를 사용하여 생성할 수 있다.

//빈 스트림 생성 Stream stream = Stream.empty(); sysout(stream.count());//스트림의 요소의 총 개수를 출력함

스트림의 중개 연산(intermediate operation)

스트림 API에 의해 생성된 초기 스트림은 중개 연산을 통해 또 다른 스트림으로 변환된다.

이러한 중개 연산은 스트림을 전달받아 스트림을 반환하므로, 중개 연산은 연속으로 연결해서 사용할 수 있다.

또한, 스트림의 중개 연산은 필터-맵(filter-map) 기반의 API를 사용함으로 지연(lazy) 연산을 통해 성능을 최적화할 수 있다.

스트림 API에서 사용할 수 있는 대표적인 중개 연산과 그에 따른 메소드는 다음과 같다.

스트림 필터링 : filter(), distinct() 스트림 변환 : map(), flatMap() 스트림 제한 : sorted() 스트림 연산 결과 확인 : peek() 스트림 필터링 filter() 메서드는 해당 스트림에서 주어진 조건(predicate)에 맞는 요소만으로 구성된 새로운 스트림을 반환한다. 또한, distinct() 메서드는 해당 스트림에서 중복된 요소가 제거된 새로운 스트림을 반환한다.distinct() 메서드는 내부적으로 Object 클래스의 equals() 메서드를 사용하여 요소의 중복을 비교한다.

IntStream stream1 = IntStream.of(7,5,5,2,1,2,3,5,4,6); IntStream stream2 = IntStream.of(7,5,5,2,1,2,3,5,4,6);

//스트림에서 중복된 요소를 제거함. stream1.distinct().forEach(e->sysout(e+" "); sysout();

//스트림에서 홀수만을 골라냄 stream2.filter(n->n%2!=0).forEach(e->sysout(e+" "));

스트림 변환 map()메소드는 해당 스트림의 요소들을 주어진 함수에 인수로 전달하여, 그 반환값들로 이루어진 새로운 스트림을 반환한다. 만약 해당 스트림의 요소가 배열이라면, flatMap() 메서드를 사용하여 각 배열의 각 요소의 반환값을 하나로 합친 새로운 스트림을 얻을 수 있다.

ex) 문자열로 이루어진 스트림은 map() 메소드를 이용하여 각 문자열의 길이로 이루어진 스트림으로 변환하는 예

Steram stream = Stream.of("HTML","CSS","JAVA","JAVASCRIPT");

stream.map(s→s.length()).forEach(System.out::println);

ex) 여러 문자열이 저장된 배열을 각 문자열에 포함된 단어로 이루어진 스트림으로 변환하는 예

String[] arr = {"I study hard","You study JAVA","I am hungry"};

Stream stream = Arrays.stream(arr); stream.flatMap(s->Stream.of(s.split(" +"))).forEach(System.out::println);

스트림 제한 limit() 메소드는 해당 스트림의 첫 번쨰 요소부터 전달된 개수만큼의 요소만으로 이루어진 새로운 스트림을 반환한다.

skip() 메소드는 해당 스트림의 첫 번째 요소부터 전달된 요소를 제외한 나머지 요소만으로 이루어진 새로운 스트림을 반환한다.

IntStream stream1 = IntStream.range(0, 10); IntStream stream2 = IntStream.range(0, 10); IntStream stream3 = IntStream.range(0, 10);

stream1.skip(4).forEach(n-> sysout(n+" ")); sysout();

stream2.limit(5).forEach(n->sysout(n+" ")); sysout();

stream3.skip(3).limit(5).forEach(n->sysout(n+" ")); → 결과

456789 01234 34567 스트림 정렬 sorted() 메소드는 해당 스트림을 주어진 비교자(comparator)를 이용하여 정렬한다. 이때 비교자를 전달하지 않으면 기본적으로 사전 편찬 순(natural order) 으로 정렬하게 된다.

Stream stream1 = Stream.of("JAVA","HTML","JAVASCRIPT","CSS"); Stream stream2 = Stream.of("JAVA","HTML","JAVASCRIPT","CSS");

stream1.sorted().forEach(s->sysout(s+" ")); sysout();

stream2.sorted(Comparator.reverseOrder()).forEach(s->sysout(s+" "));

스트림 연산 결과 확인 peek() 메소드는 결과 스트림으로부터 요소를 소모하여 추가로 명시된 동작을 수행한다. 이 메서드는 원본 스트림에서 요소를 소모하지 않으므로, 주로 연산과 연산 사이에 결과를 확인하고 싶을 때 사용한다. 

IntStream stream = IntStream.of(7,5,5,2,1,2,3,5,4,6);

stream.peek(s-> sysout("원본 스트림 : " + s)).skip(2) .peek(s-> sysout("skip(2) 실행 후 : " + s)).limit(5) .peek(s-> sysout("limit(5) 실행 후 : " + s)).sorted() .peek(s-> sysout("sort() 실행 후 : + s)).forEach(n-> sysout(n)); → 해보기

대표적인 중개 연산 메서드 스트림 API에서 사용할 수 있는 대표적인 중개 연산을 위한 메서드

Stream filter(Predicate<? super T> predicate) : 해당 스트림에서 주어진 조건(predicate)에 맞는 요소만으로 구성된 새로운 스트림을 반환함 Stream map(Function<? super T, ? extends R> mapper) : 해당 스트림의 요소들을 주어진 함수에 인수로 전달하여, 그 반환값으로 이루어진 새로운 스트림을 반환함 Stream flatMap(Function<? super T, ? extends Stream<? extends R>>mapper) : 해당 스트림의 요소가 배열일 경우, 배열의 각 요소를 주어진 함수에 인수로 전달하여, 그 반환값으로 이루어진 새로운 스트림을 반환함 Stream distinct() : 해당 스트림에서 중복된 요소가 제거된 새로운 스트림을 반환함. 내부적으로 Object 클래스의 equals() 메서드를 사용함 Stream limit(long maxSize) : 해당 스트림에서 전달된 개수만큼의 요소만으로 이루어진 새로운 스트림을 반환함. Stream limit(long maxSize) : 해당 스트림에서 전달된 개수만큼의 요소만으로 이루어진 새로운 스트림을 반환함 Stream peek(Consumer<? super T> action) : 결과 스트림으로부터 각 요소를 소모하여 추가로 명시된 동작을 수행하여 새로운 스트림을 생성하여 반환함 Stream skip(long n) : 해당 스트림의 첫 번쨰 요소부터 전달된 개수만큼의 요소를 제외한 나머지 요소만으로 이루어진 새로운 스트림을 반환함 Stream sortes()/Stream sorted(Comparator<? super T> comparator) : 해당 스트림을 주어진 비교자(comparator)를 이용하여 정렬함. 비교자를 전달하지 않으면 natural order으로 정렬함 

스트림의 최종 연산(terminal operation) 스트림 API에서 중개 연산을 통해 변환된 스트림은 마지막으로 최종 연산을 통해 각 요소를 소모하여 결과를 표시한다. 즉, 지연(lazy)되었던 모든 중개 연산들이 최종 연산 시에 모두 수행되는 것이다. 이렇게 최종 연산 시에 모든 요소를 소모한 해당 스트림은 더는 사용할 수 없게 된다.

→ ?

스트림 API에서 사용할 수 있는 대표적인 최종 연산과 그에 따른 메서드는 다음과 같다.

  1. 출력 : forEach()
  2. 요소의 소모 : reduce()
  3. 요소의 검색 : findFirst(), findAny()
  4. 요소의 검사 : anyMatch(), allMatch(), noneMatch()
  5. 요소의 통계 : count(), min(), max()
  6. 요소의 연산 : sum(), average()
  7. 요소의 수집 : collect()
  8. 요소의 출력 앞선 예에서 forEach() 메서드는 스트림의 각 요소를 소모하여 명시된 동작을 수행한다. 반환 타입이 void이므로 보통 스트림의 모든 요소를 출력하는 용도로 많이 사용한다. 
Stream<String> stream = Stream.of("넷","둘","셋","하나");
stream.forEach(System.out::println);

// 스트림 최종연산 공부 덜끝남


Optional 클래스

java.util.Optional 클래스

optional 클래스는 Integer나 Double 클래스처럼 'T' 타입의 객체를 포장해 주는 래퍼 클래스(Wrapper class) 따라서 Optional인스턴스는 모든 타입의 참조 변수를 저장할 수 있다.

이러한, Optional 객체를 사용하면 예상치 못한 NullPointerException 예외를 제공되는 메소드로 간단히 회피할 수 있다. 즉, 복잡한 조건문 없이도 널(null) 값으로 인해 발생하는 예외를 처리할 수 있게 된다.

Optional 객체의 생성

of() 메소드나 ofNullable() 메소드를 사용하여 Optional 객체를 생성할 수 있다.

of() 메소드는 null이 아닌 명시된 값을 가지는 Optional 객체를 반환한다. 만약 of() 메소드를 통해 생성된 Optional객체에 null이 저장되면 NullPointerException예외가 발생한다.

따라서 만약 참조 변수의 값이 만에 하나 null이 될 가능성이 있다면, ofNullable()메소드를 사용하여 Optional객체를 생성하는 것이 좋다.ofNullable() 메서드는 명시된 값이 null이 아니면 명시된 값을 가지는 Optional 객체를 반환하며, 명시된 값이 null이면 비어있는 Optional 객체를 반환한다.

Optional<String> opt = Optional.ofNullable("자바 Optional 객체");
System.out.println(opt.get());

Optional 객체에 접근

get() 메서드를 사용하면 Optional 객체에 저장된 값에 접근할 수 있다. 만약 Optional 객체에 저장된 값이 null이면, NoSuchElementException 예외가 발생한다. 따라서 get() 메서드를 호출하기 전에 isPresent() 메서드를 사용하여 Optional 객체에 저장된 값이 null인지 아닌지를 먼저 확인한 후 호출하는 것이 좋다.

ex) isPresent() 메서드를 이용하여 좀 더 안전하게 Optional 객체에 저장된 값에 접근하는 예

Optional<String> opt = Optional.ofNullable("자바 Optional 객체");

if(opt.isPresent()){
  System.out.s-println(opt.get());
}

또한, 다음과 같은 메서드를 사용하여 null 대신에 대체할 값을 지정할 수도 있다.

  1. orElse() 메서드 : 저장된 값이 존재하면 그 값을 반환하고, 값이 존재하지 않으면 인수로 전달된 값을 반환함.
  2. orElseGet() 메서드 : 저장된 값이 존재하면 그 값을 반환하고, 값이 존재하지 않으면 인수로 전달된 람다 표현식의 결과값을 반환함
  3. orElseThrow() 메서드 : 저장된 값이 존재하면 그 값을 반환하고, 값이 존재하지 않으면 인수로 전달된 예외를 발생시킴
Optional<String> opt = Optional.empty() // Optional를 null로 초기화함.

sysout(opt.orElse("빈 Optional 객체"));
sysout(opt.orElseGet(String::new));

기본 타입의 Optional 클래스

자바에서는 IntStream 클래스와 같이 기본 타입 스트림을 위한 별도의 Optional 클래스를 제공하고 있다.

  1. OptionalInt 클래스
  2. OptionalLong 클래스
  3. OptionalDouble 클래스 이러한 클래스는 반환 타입이 Optional타입이 아니라 해당 기본 타입이라는 사실만 제외라면 거의 모든 면에서 비슷하다.

또한, Optional객체에서 get() 메서드를 사용하여 저장된 값에 접근할 수 있는 것처럼 클래스별로 저장된 값에 접근할 수 있는 다음과 같은 메서드를 제공하고 있다. 클래스 : 저장된 값에 접근하는 메서드

  • Optional : T get()
  • OptionalInt : int getAsInt()
  • OptionalLong : long getAsLong()
  • OptionalDouble : double getAsDouble()
IntStream stream = IntStream.of(4,2,1,3);
OptionalInt result = stream.findFirst();

System.out.printlm(result.getAsInt());

Optional 메서드

Optional클래스의 메서드는 다음과 같다.

  • static Optional empty() : 아무런 값도 가지지 않는 비어있는 Optional 객체를 반환함.
  • T get() : Optional 객체에 저장된 값을 반환함
  • boolean isPresent() : 저장된 값이 존재하면 true를 반환하고, 값이 존재하지 않으면 false를 반환함.
  • static Optional of(T value) : null이 아닌 명시된 값을 가지는 Optionl 객체를 반환함
  • static Optional ofNullable(T value) : 명시된 값이 null이 아니면 명시된 값을 가지는 Optional 객체를 반환하며, 명시된 값이 null이면 비어있는 Optional객체를 반환함.
  • T orElse(T other) : 저장된 값이 존재하면 그 값을 반환하고, 값이 존재하지 않으면 이수로 전달된 값을 반환함.
  • T orElseGet(Supplier<? extends T> other) : 저장된 값이 존재하면 그 값을 반환하고, 값이 존재하지 않으면 인수로 전달된 람다 표현식의 결과값을 반환함
  • T orElseThrow(Supplier<? extends X> exceptionSupplier) : 저장된 값이 존재하면 그 값을 반환하고, 값이 존재하지 않으면 인수로 전달된 예외를 발생시킴.
⚠️ **GitHub.com Fallback** ⚠️