Stream은 컬렉션, 배열 등의 데이터를 함수형으로 처리하는 API입니다 (Java 8+)
Stream 생성 방법
// 컬렉션에서
List<String> list = Arrays.asList("a", "b", "c");
Stream<String> stream = list.stream();
// 배열에서
String[] arr = {"a", "b", "c"};
Stream<String> stream = Arrays.stream(arr);
// 직접 생성
Stream<String> stream = Stream.of("a", "b", "c");
// 범위 생성
IntStream range = IntStream.range(1, 5); // 1,2,3,4
IntStream rangeClosed = IntStream.rangeClosed(1, 5); // 1,2,3,4,5
배열에서 Stream 생성
// Primitive 타입
int[] intArray = {1, 2, 3, 4, 5};
IntStream intStream = Arrays.stream(intArray);
long[] longArray = {1L, 2L, 3L};
LongStream longStream = Arrays.stream(longArray);
double[] doubleArray = {1.0, 2.0, 3.0};
DoubleStream doubleStream = Arrays.stream(doubleArray);
// Wrapper 타입
Integer[] integerArray = {1, 2, 3, 4, 5};
Stream<Integer> stream = Arrays.stream(integerArray);
String[] strArray = {"a", "b", "c"};
Stream<String> strStream = Arrays.stream(strArray);
컬렉션에서 Stream 생성
// List
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
Stream<Integer> listStream = list.stream();
// Set
Set<String> set = new HashSet<>(Arrays.asList("a", "b", "c"));
Stream<String> setStream = set.stream();
// Map (Entry로 변환)
Map<String, Integer> map = new HashMap<>();
map.put("one", 1);
map.put("two", 2);
Stream<Map.Entry<String, Integer>> mapStream = map.entrySet().stream();
범위로 Stream 생성
// 1부터 10까지 (10 포함)
IntStream range1 = IntStream.rangeClosed(1, 10);
// 1부터 10 미만 (10 미포함)
IntStream range2 = IntStream.range(1, 10);
// LongStream도 동일
LongStream longRange = LongStream.rangeClosed(1L, 100L);
기타 생성 방법
// 빈 Stream
Stream<String> emptyStream = Stream.empty();
// 값으로 직접 생성
Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5);
IntStream intStream = IntStream.of(1, 2, 3, 4, 5);
// 무한 Stream (limit과 함께 사용)
Stream<Integer> infiniteStream = Stream.iterate(0, n -> n + 2)
.limit(10); // 0, 2, 4, 6...
중간 연산 (Intermediate Operations)
필터링
// filter - 조건에 맞는 요소만 선택
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6);
list.stream()
.filter(n -> n % 2 == 0) // 짝수만
.forEach(System.out::println); // 2, 4, 6
// distinct - 중복 제거
Arrays.asList(1, 2, 2, 3, 3, 4)
.stream()
.distinct()
.forEach(System.out::println); // 1, 2, 3, 4
변환
// map - 요소를 다른 형태로 변환
List<String> words = Arrays.asList("hello", "world");
words.stream()
.map(String::length) // 각 문자열의 길이로 변환
.forEach(System.out::println); // 5, 5
// mapToInt, mapToLong, mapToDouble - Primitive Stream으로 변환
List<String> strings = Arrays.asList("1", "2", "3");
int sum = strings.stream()
.mapToInt(Integer::parseInt)
.sum();
// flatMap - 중첩 구조를 평탄화
List<List<Integer>> nested = Arrays.asList(
Arrays.asList(1, 2),
Arrays.asList(3, 4),
Arrays.asList(5, 6)
);
nested.stream()
.flatMap(Collection::stream)
.forEach(System.out::println); // 1, 2, 3, 4, 5, 6
정렬
// sorted - 기본 정렬 (오름차순)
Arrays.asList(3, 1, 4, 1, 5)
.stream()
.sorted()
.forEach(System.out::println); // 1, 1, 3, 4, 5
// Comparator 사용
Arrays.asList(3, 1, 4, 1, 5)
.stream()
.sorted(Comparator.reverseOrder()) // 내림차순
.forEach(System.out::println);
// 객체 정렬
class Person {
String name;
int age;
Person(String name, int age) {
this.name = name;
this.age = age;
}
}
List<Person> people = Arrays.asList(
new Person("Alice", 25),
new Person("Bob", 20)
);
people.stream()
.sorted(Comparator.comparing(Person::getAge)) // 나이순 정렬
.forEach(p -> System.out.println(p.name));
제한
// limit - 개수 제한
IntStream.range(1, 100)
.limit(5) // 처음 5개만
.forEach(System.out::println); // 1, 2, 3, 4, 5
// skip - 앞에서 n개 건너뛰기
IntStream.range(1, 10)
.skip(3) // 처음 3개 건너뛰기
.forEach(System.out::println); // 4, 5, 6, 7, 8, 9
확인
// peek - 중간에 각 요소를 확인 (디버깅용)
IntStream.range(1, 5)
.peek(n -> System.out.println("before: " + n))
.map(n -> n * 2)
.peek(n -> System.out.println("after: " + n))
.sum();
최종 연산 (Terminal Operations)
수집
// toList - List로 수집
List<Integer> list = IntStream.range(1, 6)
.boxed() // Integer로 boxing
.collect(Collectors.toList());
// toSet - Set으로 수집
Set<Integer> set = Arrays.asList(1, 2, 2, 3)
.stream()
.collect(Collectors.toSet());
// toArray - 배열로 수집
int[] intArray = IntStream.range(1, 6).toArray();
Integer[] integerArray = IntStream.range(1, 6)
.boxed()
.toArray(Integer[]::new);
// toMap - Map으로 수집
Map<String, Integer> map = Arrays.asList("a", "bb", "ccc")
.stream()
.collect(Collectors.toMap(
s -> s, // key
String::length // value
));
// groupingBy - 그룹화
Map<Integer, List<String>> grouped =
Arrays.asList("a", "bb", "ccc", "dd")
.stream()
.collect(Collectors.groupingBy(String::length));
// {1=[a], 2=[bb, dd], 3=[ccc]}
집계
// count
long count = IntStream.range(1, 10).count(); // 9
// sum (Primitive Stream만 가능)
int sum = IntStream.of(1, 2, 3, 4, 5).sum(); // 15
// average (Primitive Stream만 가능)
double avg = IntStream.of(1, 2, 3, 4, 5)
.average()
.orElse(0.0); // 3.0
// max, min
int max = IntStream.of(1, 5, 3, 2, 4)
.max()
.orElse(0); // 5
int min = IntStream.of(1, 5, 3, 2, 4)
.min()
.orElse(0); // 1
// Wrapper 타입의 집계
Integer maxValue = Arrays.asList(1, 5, 3, 2, 4)
.stream()
.max(Integer::compareTo)
.orElse(null);
// reduce - 사용자 정의 집계
int product = IntStream.of(1, 2, 3, 4, 5)
.reduce(1, (a, b) -> a * b); // 120
// summaryStatistics - 한 번에 여러 통계 정보
IntSummaryStatistics stats = IntStream.range(1, 11)
.summaryStatistics();
System.out.println("Count: " + stats.getCount());
System.out.println("Sum: " + stats.getSum());
System.out.println("Min: " + stats.getMin());
System.out.println("Max: " + stats.getMax());
System.out.println("Average: " + stats.getAverage());
매칭
// anyMatch - 하나라도 조건을 만족하는지
boolean hasEven = IntStream.of(1, 3, 5, 6, 7)
.anyMatch(n -> n % 2 == 0); // true
// allMatch - 모두 조건을 만족하는지
boolean allPositive = IntStream.of(1, 2, 3, 4, 5)
.allMatch(n -> n > 0); // true
// noneMatch - 모두 조건을 만족하지 않는지
boolean noNegative = IntStream.of(1, 2, 3, 4, 5)
.noneMatch(n -> n < 0); // true
검색
// findFirst - 첫 번째 요소
OptionalInt first = IntStream.of(1, 2, 3, 4, 5)
.findFirst(); // 1
// findAny - 아무 요소나 (병렬 처리시 유용)
OptionalInt any = IntStream.of(1, 2, 3, 4, 5)
.findAny();
반복
// forEach - 각 요소에 대해 작업 수행
IntStream.range(1, 5)
.forEach(System.out::println);
// forEachOrdered - 순서를 보장하며 반복 (병렬 Stream에서도)
IntStream.range(1, 5)
.parallel()
.forEachOrdered(System.out::println);
자료구조별 활용법
배열 (Array)
// 배열 정렬
int[] arr = {3, 1, 4, 1, 5};
arr = Arrays.stream(arr)
.sorted()
.toArray();
// 배열 필터링
int[] filtered = Arrays.stream(arr)
.filter(n -> n > 2)
.toArray();
// 배열 변환
int[] doubled = Arrays.stream(arr)
.map(n -> n * 2)
.toArray();
// 2차원 배열 평탄화
int[][] matrix = {{1, 2}, {3, 4}, {5, 6}};
int[] flattened = Arrays.stream(matrix)
.flatMapToInt(Arrays::stream)
.toArray();
// 배열 통계
int sum = Arrays.stream(arr).sum();
double avg = Arrays.stream(arr).average().orElse(0.0);
int max = Arrays.stream(arr).max().orElse(0);
리스트 (List)
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
// 리스트 필터링
List<Integer> evens = list.stream()
.filter(n -> n % 2 == 0)
.collect(Collectors.toList());
// 리스트 변환
List<String> strings = list.stream()
.map(String::valueOf)
.collect(Collectors.toList());
// 리스트 정렬 (원본 유지)
List<Integer> sorted = list.stream()
.sorted()
.collect(Collectors.toList());
// 특정 조건으로 분리
Map<Boolean, List<Integer>> partitioned =
list.stream()
.collect(Collectors.partitioningBy(n -> n % 2 == 0));
// {false=[1, 3, 5], true=[2, 4]}
// 중복 제거
List<Integer> unique = Arrays.asList(1, 2, 2, 3, 3, 4)
.stream()
.distinct()
.collect(Collectors.toList());
셋 (Set)
Set<Integer> set = new HashSet<>(Arrays.asList(1, 2, 3, 4, 5));
// Set을 List로
List<Integer> list = set.stream()
.collect(Collectors.toList());
// Set 필터링
Set<Integer> filtered = set.stream()
.filter(n -> n > 3)
.collect(Collectors.toSet());
// 두 Set의 교집합
Set<Integer> set1 = new HashSet<>(Arrays.asList(1, 2, 3));
Set<Integer> set2 = new HashSet<>(Arrays.asList(2, 3, 4));
Set<Integer> intersection = set1.stream()
.filter(set2::contains)
.collect(Collectors.toSet());
// 두 Set의 합집합
Set<Integer> union = Stream.concat(set1.stream(), set2.stream())
.collect(Collectors.toSet());
맵 (Map)
Map<String, Integer> map = new HashMap<>();
map.put("apple", 100);
map.put("banana", 200);
map.put("cherry", 150);
// Map의 value로 필터링
Map<String, Integer> expensive = map.entrySet()
.stream()
.filter(e -> e.getValue() > 100)
.collect(Collectors.toMap(
Map.Entry::getKey,
Map.Entry::getValue
));
// Map의 key를 List로
List<String> keys = map.keySet()
.stream()
.collect(Collectors.toList());
// Map의 value를 List로
List<Integer> values = map.values()
.stream()
.collect(Collectors.toList());
// List를 Map으로
List<String> words = Arrays.asList("a", "bb", "ccc");
Map<String, Integer> wordLengths = words.stream()
.collect(Collectors.toMap(
w -> w,
String::length
));
// value 기준 오름차순 정렬
List<Map.Entry<String, Integer>> list = map.entrySet().stream()
.sorted(Map.Entry.comparingByValue())
.collect(Collectors.toList());
// value 기준 내림차순 정렬
List<Map.Entry<String, Integer>> list = map.entrySet().stream()
.sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
.collect(Collectors.toList());
// key 기준 오름차순 정렬
List<Map.Entry<String, Integer>> list = map.entrySet().stream()
.sorted(Map.Entry.comparingByKey())
.collect(Collectors.toList());
// key 기준 내림차순 정렬
List<Map.Entry<String, Integer>> list = map.entrySet().stream()
.sorted(Map.Entry.comparingByKey(Comparator.reverseOrder()))
.collect(Collectors.toList());
'자바 > ++' 카테고리의 다른 글
자바 정렬 ( with claude ) (0) | 2025.09.28 |
---|---|
자바 n진법 <-> 10진법 바꾸는법 (0) | 2024.01.18 |
repeat로 문자열 반복해서 이어붙이기 (0) | 2023.05.17 |
[Java] 두 배열 비교하기 (0) | 2022.12.27 |
[Java] BigInteger (큰 숫자 다루기) (0) | 2022.12.14 |
댓글