728x90
안녕하세요. 오늘은 자바의 스트림에 대해서 알아보도록 하겠습니다.
저는 요즘 알고리즘을 공부하고 있는데요, 사람들이 짠 알고리즘 코드를 보면 스트림을 굉장히 많이 쓰고 있는 것을 볼 수 있더라구요. 뭔진 모르겠지만 저렇게 간결하고 멋진 코드를 나도 짜고 싶다! 생각하여ㅎㅎㅎ 정리해보았습니다.
스트림(Stream)이란?
- 자바에서 데이터를 쉽게 다루기 위해 제공하는 데이터 처리 흐름
- 배열, 리스트 같은 데이터를 일일이 반복문으로 다루기보다는 스트림을 사용해 데이터를 변환, 필터링, 합산 등의 작업을 간단하게 할 수 있음
스트림 핵심 개념
1. 데이터 흐름
- 데이터를 처리하는 흐름을 제공하여 데이터 자체가 아니라 데이터의 흐름을 처리함
2. 변경 불가능
- 스트림을 이용해 데이터를 가공하더라도 원본 데이터를 변경되지 않음. 가공된 결과는 새로운 데이터로 만들어짐
3. 지연 연산(Lazy Evaluation)
- 스트림의 중간 연산(변환, 필터링 등)은 실제로 최종 연산이 호출될 때까지 수행되지 않으므로 필요 없는 연산을 피할 수 있음
4. 재사용 불가
- 한 번 사용한 스트림은 다시 사용할 수 없으며, 재사용하려면 새로 생성해야 함
스트림 사용의 장점
- 간결한 코드 : 반복문 없이 데이터를 간단히 필터링, 변환, 집계할 수 있음
- 병렬 처리 지원 : 데이터를 병렬로 처리할 수 있어 성능을 높임
- 가독성 향상 : 코드가 일긱 쉽고 직관적임
스트림의 3가지 주요 단계
1. 스트림 생성
배열/컬렉션에서 생성
- Arrays.stream() - 배열을 스트림으로 변환
int[] numbers = {1, 2, 3, 4};
Arrays.stream(numbers); // int 배열을 IntStream으로 변환
- list.stream() - List나 컬렉션을 스트림으로 변환
List<String> cats = List.of("뭉이", "조이");
cats.stream(); // List를 Stream으로 변환
- String.chars() - 문자열을 각 문자의 아스키 코드 값으로 구성된 IntStream으로 변환
"abcd".chars(); // 아스키 코드 값(97, 98, 99, 100)으로 구성된 IntStream 반환
특수 생성 메서드
- Stream.of() - 전달된 값을 스트림으로 만듦
Stream.of("a", "b", "c"); // Stream<String>
- Stream.iterate(초기값, 조건, 연산) - 초기값에서 시작해 조건을 만족할 때까지 반복적으로 연산하여 요소를 생성
Stream.iterate(1, n -> n < 10, n -> n + 2); // 1, 3, 5, 7, 9
- IntStream.range(시작값, 끝값) - 시작값부터 끝값-1까지의 정수로 스트림을 생성
IntStream.range(1, 5); // 1, 2, 3, 4
- IntStream.rangeClosed(시작값, 끝값) - 시작값부터 끝값까지 포함하여 스트림 생성
IntStream.rangeClosed(1, 5); // 1, 2, 3, 4, 5
2. 중간 연산
필터링 및 변환
- filter(조건) - 특정 조건에 맞는 요소만 필터링
Arrays.stream(numbers).filter(n -> n % 2 == 0); // 짝수만 남김
- map(변환) - 스트림의 각 요소를 다른 값으로 변환(기본형 스트림 유지)
Arrays.stream(numbers).map(n -> n * 2); // 각 숫자를 두 배로 변환
- mapToObj(변환) - 기본형 스트림을 객체 스트림으로 변환하면서 요소를 변환
"abcd".chars().mapToObj(c -> (char) c); // int 값을 char로 변환하여 Stream<Character> 반환
- boxed() - 기본형 스트림을 객체 스트림으로 변환
List<Integer> list = IntStream.of(1, 2, 3).boxed().toList(); // int를 Integer로 변환하여 리스트로 수집
- distinct() - 중복된 요소를 제거
Arrays.stream(new int[]{1, 2, 2, 3}).distinct(); // 1, 2, 3
- sorted() - 요소를 정렬
Arrays.stream(numbers).sorted(); // 오름차순 정렬
조건확인
- anyMatch(조건) - 조건에 맞는 요소가 하나라도 있는지 확인함. 맞는 요소가 있으면 true 반환
Arrays.stream(new int[]{1, 2, 3}).anyMatch(n -> n > 2); // true
- allMatch(조건) - 모든 요소가 조건에 맞는지 확인. 모두 만족하면 true 반환
Arrays.stream(new int[]{2, 4, 6}).allMatch(n -> n % 2 == 0); // true
- noneMatch(조건) - 모든 요소가 조건에 맞지 않는지 확인. 조건에 맞는 요소가 없으면 true
Arrays.stream(new int[]{1, 2, 3}).noneMatch(n -> n > 5); // true
3. 최종 연산
결과 수집
- collect() - 스트림을 리스트, 집합, 문자열 등의 결과로 수집
- Collectors.toList() - List로 변환
Arrays.stream(numbers).boxed().collect(Collectors.toList());
- Collectors.joining() - 문자열 스트림을 하나의 문자열로 합침
Stream.of("a", "b", "c").collect(Collectors.joining()); // "abc"
- toArray() - 스트림을 배열로 변환
Arrays.stream(numbers).filter(n -> n > 2).toArray();
- reduce(초기값, 연산) - 모든 요소를 하나의 값으로 합침
Arrays.stream(numbers).reduce((a, b) -> a + b); // 전체 합산
- sum() : 기본형 스트림(숫자 스트림 : IntStream, LongStream, DoubleStream)에서 모든 요소의 합을 구함
Arrays.stream(numbers).sum(); // 전체 합계
요소 탐색
- findFirst() - 스트림의 첫 번째 요소를 반환(*Optional로 반환)
※ Optional - 값이 있을 수도 있고 없을 수도 있는 상태를 표현하는 특별한 객체
Arrays.stream(new int[]{3, 5, 7}).findFirst().orElse(-1); // 3
- findAny() - 스트림에서 아무 요소 하나를 반환. 주로 병렬 스트림에서 사용됨
Arrays.stream(new int[]{3, 5, 7}).findAny().orElse(-1); // 3 (병렬 처리 시 불특정)
집계 연산
- count() - 스트림의 요소 개수 반환
Arrays.stream(new int[]{1, 2, 3, 4}).count(); // 4
- average() - 모든 요소의 평균값 계산하고 Optional로 반환
Arrays.stream(new int[]{1, 2, 3, 4, 5}).average().orElse(0); // 3.0
- max() / min() - 스트림의 최대값, 최소값을 반환. Optional로 반환되므로 값이 없을 때 대비해야함
Arrays.stream(new int[]{1, 2, 3}).max().getAsInt(); // 3
Arrays.stream(new int[]{1, 2, 3}).min().orElse(-1); // 1
병렬 처리
- parallel() - 스트림을 병렬로 처리. 데이터가 많을 때 빠르게 계산하지만 작은 데이터에서는 오히려 성능이 떨어짐
Arrays.stream(new int[]{1, 2, 3, 4, 5}).parallel().sum(); // 병렬로 합쳐 계산
- 순차 처리 : parallel()을 사용X -> 1 + 2 + 3 + 4 + 5를 한 코어가 순서대로 처리
- 병렬 처리 : parallel()을 사용O -> [1, 2]와 [3, 4, 5]로 나뉘어 여러 코어가 동시에 더한 다음 합침
728x90
'Languages > JAVA' 카테고리의 다른 글
[JAVA] 객체지향 프로그래밍(OOP)이란? (0) | 2024.12.10 |
---|---|
[JAVA] JVM(자바 가상 머신)이란? (역할, 동작 과정, 구성 요소) (0) | 2024.09.23 |
[JAVA] 프로토타입 패턴&싱글톤 패턴(new, getInstance()의 차이) (0) | 2023.11.02 |
[JAVA] 자바 MD5, SHA-256 단방향 암호화(feat. MessageDigest)(+코드예제) (2) | 2023.11.01 |