스트림의 3가지 순서 (생성 → 가공 → 결과) 중 가공에 해당하는 부분이며, 원하는 결과를 얻기 위해 필요한 데이터만 걸러내는 방법이다.
중복을 제거하기 위해 사용한다.
Stream : “Object.equals(Object)”가 true 일 경우에 동일한 객체로 판단하여 중복 제거
IntStream, LongStream, DoubleStream: 값이 동일한 경우 중복 제거
List<String> list = Arrays.asList("a","b","b","c","c","a");
list.stream()
.distinct()
.forEach(System.out::print);
조건이 참이면 true, 거짓이면 false를 리턴하며, true인 것만 필터링 한다.
List<String> sentences = Arrays.asList("김밥", "김밥", "김치", "나비", "나방");
sentences.stream()
.filter(str -> str.startsWith("김")) // 구현체가 true 일 경우에만 출력 (앞글자가 김일 경우에만)
.distinct() // 중복 제거
.forEach(System.out::println);
System.out.println("=============");
Set<String> set = sentences.stream()
.filter(x -> x.startsWith("김"))
.collect(Collectors.toSet());
System.out.println(set);
System.out.println("=============");
distinct, filter 동시 사용
String[] dupArray = {"김밥", "김밥", "김치", "나비", "나방"};
Set<String> hashSet = Arrays
.stream(dupArray)
.collect(Collectors.toSet());
List<String> arrayList =
Arrays.stream(dupArray)
.distinct()
.toList();
System.out.println(hashSet);
System.out.println(arrayList);
가공에 해당하는 부분
스트림의 요소를 하나씩 특정 값으로 변환, 변환된 값은 새로운 스트림으로 만들어진다. 어떤 값으로 변환할지는 map 메소드에 정의할 수 있다.
List<String> list = Arrays.asList("a", "b", "c", "d", "e");
list.stream()
.map(element -> element.toUpperCase())
.forEach(System.out::println);
스트림의 요소들을 다른 값으로 대체하지만, 대체하는 값이 스트림일 경우에 사용한다. 스트림 안에 또 다른 스트림이 있는 2차원 배열과 유사한 구조이다. flatMap 을 사용하여 중첩 구조를 한 단계 제거하는 것을 flattening이라고 한다. → 2차원 배열을 나열하여 1차월 배열처럼 출력할 수 있다.
// flatmap 2차원 -> 1차원
Integer [][] array = {{1,2}, {3,4}};
Arrays.stream(array)
.flatMap(element -> Arrays.stream(element))
.forEach(System.out::println);
1
2
3
4
split을 사용하여 배열에서 특정 문자를 기준으로 나눌 수도 있다. collect를 사용하면 나눈 단어들을 다시 리스트에 넣을 수 있다.
// flatmap
List<String> sentences = Arrays.asList("Hello World","Java stream");
sentences.stream()
.flatMap(element -> Arrays.stream(element.split(" ")))
.forEach(System.out::println);
Hello
World
Java
stream
// flatmap
List<String> sentences2 = Arrays.asList("Hello World","Java stream");
List<String> collect = sentences2.stream()
.flatMap(element -> Arrays.stream(element.split(" ")))
.collect(Collectors.toList());
System.out.println(collect);
[Hello, World, Java, stream]
가공에 해당하는 부분
스트림의 요소들을 정렬하기 위해 사용하며, 아무 옵션도 주지 않으면 오름차순으로 정렬한다. Comparator을 사용하면 원하는 방식으로 정렬도 가능하다.
List<String> list = Arrays.asList("e", "a", "c", "z", "d");
List<String> sortedList = list.stream()
.sorted() // 오름차순 정렬
.toList();
System.out.println(sortedList);
System.out.println("=============");
List<String> sortedList2 = list.stream()
.sorted(Comparator.reverseOrder()) // **Comparator 사용 (역순 정렬)**
.toList();
System.out.println(sortedList2); // 내림차순 정렬
요소 전체를 반복하여 어떠한 작업을 수행하는 것을 말한다.
가공 단계에서 사용하는 메소드이다. 확인해본다는 의미이며, 특정 결과를 반환하지는 않는다. 작업을 처리하는 중간에 결과를 확인해볼 때 사용할 수 있다. → 결과를 집계하는 메소드를 호출하지 않으면 적용되지 않는다.
List<Integer> list = Arrays.asList(1,2,3,4,5);
// 짝수를 걸러내서 총 합 구하기 / 가공 단계에서 사용할 수 있는 peek 사용
// Integer 타입이라 sum 연산을 할 수 없어서 primitive 타입으로 변환 후 sum 연산을 해야한다.
// Stream<Integer> -> IntStream 으로 변환
int sum = list.stream()
.mapToInt(element -> element) // 타입 변환
.filter(element -> element % 2 == 0)
.peek(System.out::println)
.sum();
System.out.println("짝수들의 총 합 : " + sum);
// IntStream -> Stream<Integer> primitive 타입 stream을 wrraper 타입 stream 으로 변환 시에는 boxing 메소드 사용
결과에서 사용하는 메소드이다. 위 코드에서 sum과 같은 결과 메소드와 중복해서 사용할 수 없다.
// forEach 사용해서 필터링된 stream 요소 출력 / 결과 단계에서 사용
List<Integer> list2 = Arrays.asList(1,2,3,4,5);
list2.stream()
.filter(element -> element % 2 == 0)
.forEach(element -> System.out.println(element)); // = System.out::println
결과 단계에서 사용한다.
스트림 최종 단계에서 사용하는 메소드이며, 어떤 요소를 어떤 컬렉션에 수집할 지 결정할 수 있다. 스트림으로 가공한 데이터를 최종적으로 컬렉션에 변환한다.
// 홀수만 골라내어 새로운 집합을 만드는 예제
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.toCollection 을 사용하여 HashSet이라는 컬렉션에 데이터를 수집
Collectors에서 제공하는 메소드
| Collectors 정적 메소드 | 설명 |
|---|---|
| toList | 요소를 List에 저장 |
| toSet | 요소를 Set에 저장 |
| toCollection | 요소를 특정 컬렉션에 저장 |
| toMap | 요소를 Map에 저장 |
collect 메소드를 사용하여 컬렉션 요소들을 그룹핑해서 Map 객체를 생성하는 기능, Collectors의 groupingBy를 사용
List<Integer> list = Arrays.asList(1,1,2,2,2,3,4,5,5,5);
Map<Integer, Long> collected = list.stream()
.collect(
Collectors.groupingBy(
n -> n, // 요소 그대로 키값으로
Collectors.counting() // 그룹핑 요소 각각 카운팅
)
);
collected.forEach((key, value) -> System.out.println(key + " : " + value + "개"));
1 : 2개
2 : 3개
3 : 1개
4 : 1개
5 : 3개
// List<Integer>가 주어졌을 때, 각 숫자를 제곱한 값의 리스트로 변환하세요
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5)
// 결과 예시 [1, 4, 9, 16, 25]
List<Integer> numbers = Arrays.asList(1,2,3,4,5);
List<Integer> result = numbers.stream()
.map(x -> x * x)
.collect(Collectors.toList());
System.out.println(result);
//ist<String>의 문장들을 단어로 나누어(‘:’구분자) 하나의 List<String>로 변환하세요.
List<String> sentences = Arrays.asList("Hello:world", "Java:stream:flatMap", "Functional:programming");
// 결과 [Hello, world, Java, stream, flatMap, Functional, programming]
List<String> sentences = Arrays.asList("Hello:world","Java:stream:flatMap","Functional:programming");
List<String> collect = sentences.stream()
.flatMap(x -> Arrays.stream(x.split(":")))
.collect(Collectors.toList());
System.out.println(collect);
// 이차원 컬렉션에 들어있는 정수들을 하나의 컬렉션으로 변환해주세요
List<List<Integer>> numbers = Arrays.asList(
Arrays.asList(1, 2, 3),
Arrays.asList(4, 5, 6),
Arrays.asList(7, 8, 9)
);
// 결과 [1, 2, 3, 4, 5, 6, 7, 8, 9]
List<List<Integer>> numbers2 = Arrays.asList(
Arrays.asList(1, 2, 3),
Arrays.asList(4, 5, 6),
Arrays.asList(7, 8, 9)
);
List<Integer> result2 =
numbers2.stream()
.flatMap(x -> x.stream())
.toList();
System.out.println(result2);
// Person 클래스의 리스트가 주어졌을 때, 각 객체의 이름만 추출하여 List<String>으로 변환하세요.
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", 30),
new Person("Bob", 25),
new Person("Charlie", 28)
);
// 결과 예시 [Alice, Bob, Charlie]
List<String> peopleList = people.stream()
.map(person -> person.name)
.toList();
System.out.println(peopleList);
// Person 클래스의 리스트가 주어졌을 때, 나이가 28 이상인 사람만 필터링하여 새로운 리스트를 만드세요
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", 30),
new Person("Bob", 25),
new Person("Charlie", 28)
);
// 결과 예시 [Alice, Charlie]
List<String> peopleList = people.stream()
.filter(person -> person.age >= 28)
.map(person -> person.name)
.toList();
System.out.println(peopleList);
// List<String> 형태의 문자열 리스트가 주어졌을 때, 각 문자열의 길이를 계산하여 길이가 5이하인 요소만 담아서 List<String> 으로 변환하세요.
List<String> words = Arrays.asList("apple", "banana", "cherry");
// 결과 예시 [apple]
List<String> words = Arrays.asList("apple", "banana", "cherry");
List<String> wordsResult = words.stream()
.filter(x -> x.length() <= 5)
.toList();
System.out.println(wordsResult);
// List<String> 형태의 문자열 리스트가 주어졌을 때, 내림차순으로 정렬하고 모든 문자열을 대문자로 변환하세요.
List<String> words = Arrays.asList("hello", "world", "java");
// 결과 예시 [WORLD, JAVA, HELLO]
List<String> words2 = Arrays.asList("hello", "world", "java");
List<String> result3 = words2.stream()
.map(x -> x.toUpperCase())
.sorted(Comparator.reverseOrder())
.toList();
System.out.println(result3);
// List<String> 형태의 문자열 리스트가 주어졌을 때, 문자열의 길이가 5글자 이상인 것만 필터링하여 새로운 리스트를 만드세요.
List<String> words = Arrays.asList("apple", "banana", "cat", "dog", "elephant");
// 결과 예시 [apple, banana, elephant]
List<String> words3 = Arrays.asList("apple", "banana", "cat", "dog", "elephant");
List<String> result4 = words3.stream()
.filter(x -> x.length() >= 5)
.toList();
System.out.println(result4);
// List<Integer>가 주어졌을 때, 리스트에서 10보다 크고 50보다 작은 숫자만 필터링하세요.
List<Integer> numbers = Arrays.asList(5, 12, 25, 37, 48, 50, 63);
// 결과 예시 [12, 25, 37, 48]
List<Integer> numbers3 = Arrays.asList(5, 12, 25, 37, 48, 50, 63);
List<Integer> result5 = numbers3.stream()
.filter(x -> 50 > x && x > 10)
.toList();
System.out.println(result5);
// List<String> 형태의 문자열 리스트가 주어졌을 때, 특정 단어 (예: "apple")가 포함된 문자열만 필터링하세요.
List<String> sentences = Arrays.asList("I like apples", "Bananas are tasty", "apple pie is delicious", "I have an apple");
// 결과 예시 [I like apples, apple pie is delicious, I have an apple]
List<String> sentences2 = Arrays.asList("I like apples", "Bananas are tasty", "apple pie is delicious", "I have an apple");
List<String> result6 = sentences2.stream()
.filter(x -> x.contains("apple"))
.toList();
System.out.println(result6);