Java Optional

김정훈·2024년 5월 7일

Java

목록 보기
32/48

Optional 클래스

  • JDK8
  • null에 대한 다양한 처리 방법을 제공하는 클래스
  • Wrapper 클래스
class Optional<T> {
	...
	private final T value;
	...
}

1. Optional 객체 생성하기

static Optional<T> of(T t) : t가 null이면 오류 발생
static Optional<T> ofNullable(T t) : t가 null이어도 오류 발생 X

2. Optional 객체의 값 가져오기

T get() : null 이면 오류 발생 // NoSuchElementException 발생
T orElse(T other) : null이 아니면 값 반환, null이면 other 반환
T orElseGet(Supplier<T ... > ) : 메서드(함수)정의 : 복잡한 반환값을 생성해야 하는 경우
T orElseThrow() : null이면 예외 발생 // NoSuchElementException 발생
T orElseThrow(Supplier<T ... > ) : 직접 정의한 예외가 발생

참고)

API문서 : 반환값이 Optional 인경우 : 결과가 null일 가능성이 있는 메서드

3. OptionalInt, OptionalLong, OptionalDouble

  • 기본형을 처리하는 Optional 클래스
  • 오토박싱, 언박싱이 발생 X 👉 성능상의 이점👍

참고) flatMap

중첩된 스트림 👉 일차원적 스트림으로 변환

4. 스트림의 최종 연산

  • 최종 연산이 호출되어야 중간 연산도 수행, 스트림을 소비

1) forEach(Consumer<T>...)

반복 작업 수행

2) allMatch(), anyMatch(), noneMatch()

  • boolean allMatch(Predicate ... ) : 전부 참이면 참
    • 참고) 자바스크립트 배열 객체 every와 비슷
  • boolean anyMatch(Predicate ...) : 어떤 요소든 조건이 참이면 참
    • 참고) 자바스크립트 배열 객체 some과 비슷
  • boolean noneMatch(Predicate ...) : 전부 거짓이면 참
ppublic class Ex01 {
    public static void main(String[] args) {
        int[] nums = {1, 3, 5, 7, 9, 11, 13, 15, 16};
        boolean isOdd = Arrays.stream(nums).allMatch(x -> x % 2 ==1);
        System.out.println(isOdd); //> false

        boolean isEven = Arrays.stream(nums).anyMatch(x -> x % 2 == 0);
        System.out.println(isEven); //> true

        boolean notIncludedEven = Arrays.stream(nums).noneMatch(x -> x % 2 ==0);
        System.out.println(notIncludedEven); //>false
    }
}

3) findFirst(), findAny()

  • T findFirst() : 가장 첫번째 스트림의 요소를 반환
    참고) findAny() : 병렬 스트림인 경우 가장 먼저 나오는 요소

findFirst의 반환값이 OptionalInt이기 때문에 값이 없을 가능성이 있다.
그렇기 때문에 orElse로 반환겂이 없을 때의 기본값을 설정한다.

public class Ex02 {
    public static void main(String[] args) {
        Random rand = new Random();
        int firstOdd = rand.ints(100).filter(x -> x % 2 == 1).findFirst().orElse(-1);
        //findFirst의 반환값이 OptionalInt이기 때문에 값이 없을 가능성이 있다.
        //그렇기 때문에 orElse로 반환겂이 없을 때의 기본값을 설정한다.
        System.out.println(firstOdd);
    }
}

4) count(), sum(), average(), max(), min()

  • long count() : 요소의 갯수
    • 일반 스트림Stream<t>, 기본자료형스트림 IntStream, LongStream, DoubleStream
  • sum() : 합계
    • 기본자료형스트림(IntStream, LongStream, DoubleStream)
  • OptionalDouble average() : 평균
    • 기본자료형스트림(IntStream,LongStream, DoubleStream)
  • max() : 최대값
  • min() : 최소값

5) reduce()

반환값을 n1으로 함으로써 중첩시킬수있다.

import java.util.Arrays;
public class Ex03 {
    public static void main(String[] args) {
        int[] scores = { 67, 80, 100, 98, 76, 56};
        int total = Arrays.stream(scores).reduce(0, (n1, n2) -> n1 + n2);
        //reduce 원리
        int total1 = Arrays.stream(scores).reduce(0, (n1, n2) ->{
            System.out.printf("n1 : %d, n2 : %d\n",n1,n2);
            n1 += n2;
            return n1;
        });
        System.out.println(total);
    }
}
n1 : 0, n2 : 67
n1 : 67, n2 : 80
n1 : 147, n2 : 100
n1 : 247, n2 : 98
n1 : 345, n2 : 76
n1 : 421, n2 : 56
public class Ex04 {
    public static void main(String[] args) {
        int[] scores = { 67, 80, 100, 98, 76, 56};
        int max = Arrays.stream(scores).reduce((a,b) -> a > b ? a : b).getAsInt();
        int max1 = Arrays.stream(scores).reduce((a,b) -> {
            System.out.printf("a=%d, b=%d\n",a,b);
            int m = a > b ? a : b;
            return m;
        }).getAsInt();
        System.out.println(max);
    }
}
a=67, b=80
a=80, b=100
a=100, b=98
a=100, b=76
a=100, b=56

6) collect()

Collector

public class Ex05 {
    public static void main(String[] args) {
        String[] names = {"이름1", "이름1", "이름2", "이름3", "이름4", "이름5"};
        List<String> namesList = Arrays.stream(names)
                                //.collect(Collectors.toList());
                                .toList();
        System.out.println(namesList);
        Set<String> nameSet = Arrays.stream(names).collect(Collectors.toSet());
        System.out.println(nameSet); //중복제거
    }
}

java.util.stream.Collectors

7) toList(), toSet(), toMap(), toCollection(), toArray()

  • toMap() : 키, 값
  • toCollection() : List, Set의 하위 클래스 객체, 만약 ArrayList변환, HashSet, TreeSet변환 할 때 사용.
public class Ex07 {
    public static void main(String[] args) {
        String[] names = {"이름1", "이름1", "이름2", "이름3", "이름4", "이름5"};
        ArrayList<String> items = Arrays.stream(names)
                .collect(Collectors.toCollection(ArrayList::new));
                //.collect(Collectors.toCollection(() -> new ArrayList<>()));
    }
}
//>[이름1, 이름1, 이름2, 이름3, 이름4, 이름5]

8) joining()

joining(결합문자,맨앞문자,맨뒤문자)
스트림 요소를 특정 문자로 결합해서 문자열로 생성

public class Ex06 {
    public static void main(String[] args) {
        List<String> fruits = Arrays.asList("Apple","Orange","Melon","Mango");
        String str = fruits.stream().collect(Collectors.joining(","));
        System.out.println(str);

        String str2 = fruits.stream().collect(Collectors.joining("#","**","^^"));
        System.out.println(str2);
    }
}
//> Apple,Orange,Melon,Mango
//>**Apple#Orange#Melon#Mango^^

9) groupingBy(), partitioningBy()

  • groupingBy() : 특정 값을 가지고 그룹
public class Ex08 {
    public static void main(String[] args) {
        Student[] students = {
                new Student(1,"이이름"),
                new Student(1,"김이름"),
                new Student(1,"박이름"),

                new Student(2,"이이름"),
                new Student(2,"김이름"),
                new Student(2,"박이름"),

                new Student(3,"이이름"),
                new Student(3,"김이름"),
                new Student(3,"박이름"),

        };
/*
        Map<Integer, String> data = Arrays.stream(students)
                .collect(toMap(Student::getBan,Student::getName));

        System.out.println(data);

 */
        Map<Integer, List<Student>> data = Arrays.stream(students)
                .collect(Collectors.groupingBy(Student::getBan));

        List<Student> students2 = data.get(2);
        students2.forEach(System.out::println);
    }
}
  • partitioningBy : 양분(참 ,거짓)
    -Map<Boolean, List<...>
public class Ex09 {
    public static void main(String[] args) {
        Student[] students = {
                new Student(1,"이이름",80),
                new Student(1,"김이름",60),
                new Student(1,"박이름",55),

                new Student(2,"이이름",100),
                new Student(2,"김이름",90),
                new Student(2,"박이름",30),

                new Student(3,"이이름",60),
                new Student(3,"김이름",90),
                new Student(3,"박이름",50),

        };

        Map<Boolean, List<Student>> data = Arrays.stream(students)
                .collect(Collectors.partitioningBy(s -> s.getScore() >= 70));

        List<Student> students1 = data.get(true);
        students1.forEach(System.out::println);
    }
}
//> Student{ban=1, name='이이름'}
Student{ban=2, name='이이름'}
Student{ban=2, name='김이름'}
Student{ban=3, name='김이름'}

10) flatMap()

중첩된 stream을 평탄화시킴

public class Ex10 {
    public static void main(String[] args) {
        List<String> names = Arrays.asList("이름1","이름2","이름3");
        List<String> fruits = Arrays.asList("Apple","Orange","Melon");

        Stream<Stream<String>> stm = Stream.of(names.stream(), fruits.stream());
        //stream이 중첩 되어있음

        /*
        stm.forEach(st ->{
            st.forEach(System.out::println);
        });
         */
        //stm.flatMap(s -> s).forEach(System.out::println);
        String[] strs = stm.flatMap(s -> s).toArray(String[] :: new);
        System.out.println(Arrays.toString(strs));


    }
}
profile
안녕하세요!

0개의 댓글