1. 스트림 소개, 종류
설명
- 자바8부터 제공
- 배열이나 컬렉션을 가공하여 원하는 결과를 얻을 수 있다.
- Collection 인터페이스의 메서드로 스트림을 제공
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); for (int n: numbers) { if (n % 2 == 0) { System.out.println(n); } }
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); numbers.stream() .filter(n -> n % 2 == 0) .forEach(System.out::println);
- 장점
- 사람이 읽기 쉬운 단어로 나타내어 가독성이 높아진다
- 병렬처리가 가능하다
- 종류
- java.util.stream 패키지에 스트림 인터페이스가 정의되어있고, BaseStream을 부모로 하는 자식 인터페이스들이 상속 구조를 이룬다.
이름 설명 BaseStream 모든 스트림에서 사용할 수 있는 공통 메소드들이 정의되어 있다.
코드에서 직접 사용하지는 않는다.Stream 객체 요소를 처리하는 스트림 IntStream int 형을 처리하는 스트림 LongStream long 형을 처리하는 스트림 DoubleStream double 형을 처리하는 스트림
- 스트림의 3단계
- 생성 : 스트림 인스턴스 생성 (배열이나 컬렉션을 스트림 인스턴스로 변환)
- 컬렉션 : 디폴트 메소드 stream을 이용해 스트림을 생성
List<String> list = Arrays.asList("a", "b", "c", "d", "e"); Stream<String> stream = list.stream(); stream.forEach(System.out::println);
- 배열 : Array.stream 메소드를 사용하여 스트림을 생성
List<String> list = Arrays.asList("a", "b", "c", "d", "e"); Stream<String> stream = list.stream(); stream.forEach(System.out::println);
- 숫자 범위
- range : 두번째 인자인 범위의 끝값이 포함되지 않는다
- rangeClosed : 두번째 인자인 범위의 끝값이 포함된다
IntStream intStream = IntStream.range(1, 5); // [1, 2, 3, 4] LongStream longStream = LongStream.rangeClosed(1, 5); // [1, 2, 3, 4, 5]
- 파일
- 스트림 연결
- 컬렉션 : 디폴트 메소드 stream을 이용해 스트림을 생성
- 가공 : 원하는 결과를 만들어가는 중간 작업
- 여러번 적용 가능하다
- 결과 : 최종 결과를 만들어내는 작업
- 생성 : 스트림 인스턴스 생성 (배열이나 컬렉션을 스트림 인스턴스로 변환)
2. Optional
설명
- Null값을 가진 객체를 참조하려고 했을 때 NPE가 발생
- 자바 8버전부터 NPE를 방지하기위해 Optional 클래스가 도입
- null을 포함한 모든 데이터를 저장할 수 있는 Wrapper 클래스
- 사용 이유
- null을 직접 다루는 것은 위험하다
- null을 체크하기위해 if 문을 사용하면 코드가 지저분해진다.
String str = "abc"; Optional<String> optVal = Optional.of(str); Optional<String> optVal = Optional.of("abc"); Optional<String> optVal = Optional.of(null); // NullPointException 발생 Optional<String> optVal = Optional.ofNullable(null); // OK
Optional<String> optVal = null; // 사용 금지 Optional<String> optVal = Optional.empty();
- Optional 객체 생성 메소드
메소드 설명 static <T> Optional<T> empty() 아무런 값도 가지지 않는 비어있는 Optional 객체를 반환함. static <T> Optional<T> of(T value) null이 아닌 명시된 값을 가지는 Optional 객체를 반환함. static <T> Optional<T> ofNullable(T value) 명시된 값이 null이 아니면 명시된 값을 가지는 Optional 객체를 반환하며, 명시된 값이 null이면 비어있는 Optional 객체를 반환함.
- Optional 객체 반환 메소드
메소드 설명 T get() Optional 객체에 저장된 값을 반환함. (null-safe하지 않아 사용하지 않는다.) T orElse(T other) 저장된 값이 존재하면 그 값을 반환하고, 값이 존재하지 않으면 인수로 전달된 값을 반환함. T orElseGet(Supplier<? extends T> other) 저장된 값이 존재하면 그 값을 반환하고, 값이 존재하지 않으면 인수로 전달된 람다 표현식의 결과값을 반환. <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) 저장된 값이 존재하면 그 값을 반환하고, 값이 존재하지 않으면 인수로 전달된 예외를 발생시킴. boolean isPresent() 저장된 값이 존재하면 true를 반환하고, 값이 존재하지 않으면 false를 반환함.
3. 필터링 - distinct, filter
설명
- 필터링 : 스트림 3단계 중 가공에 해당
- 원하는 결과를 얻기위해 필요한 데이터를 걸러내는 작업
- distinct : 중복을 제거한다.
- Stream은 Object.equals(Object)가 true라면 동일한 객체로 판단
- IntStream, LongStream,DoubleStream은 값이 동일한 경우 중복을 제거
List<String> list = Arrays.asList("a", "b", "b", "c", "d"); // [a, b, c, d] list.stream() .distinct() .forEach(System.out::println);
- filter : 주어진 Predicate 가 true 인 것만 필터링
- Predicate : 매개변수를 받아 boolean 값을 반환하는 함수
List<String> list = Arrays.asList("김밥", "김밥", "김치", "나비", "나방"); // [김밥, 김밥, 김치] list.stream() .filter(str -> str.startsWith("김")) .forEach(System.out::println); // [김밥, 김치] list.stream() .filter(str -> str.startsWith("김")) .distinct() .forEach(System.out::println);
- Predicate : 매개변수를 받아 boolean 값을 반환하는 함수
4. 매핑 - map, flatMap
설명
- map : 스트림의 요소를 하나씩 특정 값으로 변환, 변환된 값은 새로운 스트림이 된다.
List<String> list = Arrays.asList("a", "b", "c", "d", "e"); // [A, B, C, D, E] list.stream() .map(String::toUpperCase) .forEach(System.out::println);
- flatMap : 대체하는 값이 스트림인 경우에 사용
List<String> list = Arrays.asList("Hello World", "Java stream"); // [Hello, World, Java, stream] list.stream() .flatMap(str -> Arrays.stream(str.split(" "))) .forEach(System.out::println);
- map : 스트림의 요소를 하나씩 특정 값으로 변환, 변환된 값은 새로운 스트림이 된다.
5. 정렬 - sorted
설명
- 스트림의 요소들을 정렬하기위해 사용
- 기본 : 오름차순
- Comparator을 통해 원하는 방식으로 정렬가능
List<Integer> list = Arrays.asList(12, 4, 2, 8, 11); // [2, 4, 8, 11, 12] list.stream() .sorted() .forEach(System.out::println);
List<String> list = Arrays.asList("e", "a", "c", "z", "d"); // [z, e, d, c, a] list.stream() .sorted(Comparator.reverseOrder()) // 역순 정렬 .forEach(System.out::println);
6. 루핑 - peek, forEach
설명
- 요소 전체를 반복하여 어떠한 작업을 수행하는 것
- Peek
- 가공 단계에서 사용하는 메소드
- 결과를 반환하지 않고 출력하는 방식
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5); int sum = list.stream() .mapToInt(n -> n) .filter(n -> n % 2 == 0) .peek(n -> System.out.println(n)) // [2, 4] .sum(); // sum을 사용하지 않으면 peek은 동작하지 않음 System.out.println(sum); // 6
- forEach
- peek과는 달리 결과 단계에서 사용하는 메소드
- sum과 같은 결과 메소드와 중복해서 사용할 수 없다.
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5); list.stream() .mapToInt(n -> n) .filter(n -> n % 2 == 0) .forEach(n -> System.out.println(n)); // [2, 4]
7. 수집 - collect()
설명
- 결과 단계에서 사용
- collect
- 스트림의 최종단계에서 사용하는 메소드
- 어떤 요소를 어떤 컬렉션에 수집할 지 결정
- 스트림으로 가공한 데이터를 최종적으로 컬렉션으로 변환한다.
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5); // 짝수만 골라내어 새로운 리스트로 collect List<Integer> newList = list.stream() .filter(n -> n % 2 == 0) .collect(Collectors.toList()); newList.stream().forEach(System.out::println); // [2, 4]
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5); Set<Integer> set = list.stream() .filter(n -> n % 2 == 1) .collect(Collectors.toCollection(HashSet::new)); set.stream().forEach(System.out::println); // {1, 3, 5}
- Collectors 에서 제공하는 메소드
Collectors 정적 메소드 설명 toList 요소를 List에 저장 toSet 요소를 Set에 저장 toCollection 요소를 특정 컬렉션에 저장 toMap 요소를 Map에 저장
- 그룹핑
- groupingBy : 컬렉션의 요소들을 그룹핑해서 Map 객체를 생성
List<Integer> list = Arrays.asList(1, 1, 2, 2, 2, 3, 4, 5, 5, 5); Map<Integer, Long> result = list.stream() .collect( Collectors.groupingBy( n -> n, Collectors.counting() // 그룹핑 후 집계하는 메소드 ) ); /* * 1: 2개 * 2: 3개 * 3: 1개 * 4: 1개 * 5: 3개 */ result.forEach((key, value) -> System.out.println(key + ": " + value + "개"));
- groupingBy의 첫 번째 파라미터 : 그룹핑을 위한 키 값
- 첫 번째 파라미터
n → n
는 요소 값 그 자체를 키로 사용한다는 의미
- 첫 번째 파라미터
- 두 번째 파라미터는 집계 함수
- 그룹핑 후 어떻게 집계할 것인지 정할 수 있다.
- groupingBy의 첫 번째 파라미터 : 그룹핑을 위한 키 값
- groupingBy : 컬렉션의 요소들을 그룹핑해서 Map 객체를 생성
8. Daily Quiz
'Dev > ESTsoft 오르미' 카테고리의 다른 글
SQL과 데이터베이스 (0) | 2024.02.23 |
---|---|
스레드(Thread) (0) | 2024.02.23 |
이팩티브 자바-인터페이스 (0) | 2024.02.23 |
람다식 (0) | 2024.02.23 |
컬렉션 (0) | 2024.02.23 |