Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- 그리디알고리즘
- 애자일기법
- database
- Spring
- 개발자
- 코딩
- 읽기쉬운코드
- 애자일
- 스프링
- Baekjoon
- 그리디
- 코딩테스트
- Java
- Elasticsearch
- cleancode
- 데이터베이스
- 클린코드
- 백준
- ES
- API
- framework
- 개발
- 자바
- 알고리즘
- 애자일프로그래밍
- JPA
- 프레임워크
- 코드
- 엘라스틱서치
- spring boot
Archives
- Today
- Total
튼튼발자 개발 성장기🏋️
Stream 본문
반응형
Stream은 JAVA 8에서 추가 된 도구로써 함수형 인터페이스를 활용해서 데이터를 매우 간편하고 간결하게 가공할 수 있도록 도와준다.
이번 포스트에서는 이 Stream의 built in method에 대해서 알아보는 시간을 가진다.
Stream은 데이터의 가공되는 흐름을 한 눈에 알아보기 쉽게 가독성을 향상시키는 장점이 있다. 이로인한 이유로 기존에 loop로 짰던 로직을 Stream으로 간결하고 직관적으로 대체가 가능하다. 또한 병렬처리도 가능하다.
다음 아래 내용은 Stream으로 변환하는 세 가지 방법을 소개한다.
// Stream 변환 A방법
Stream<String> nameStream = Stream.of("홍길동", "김길동", "박길동");
List<String> names = nameStream.collect(Collectors.toList());
System.out.println(names); // [홍길동, 김길동, 박길동]
// Stream 변환 B방법
String[] nameArray = new String[] {"이길동", "강길동", "진길동"};
nameStream = Arrays.stream(nameArray);
names = nameStream.collect(Collectors.toList());
System.out.println(names); // [이길동, 강길동, 진길동]
// Stream 변환 C방법
Set<String> nameSet = new HashSet<>(Arrays.asList("나길동", "신길동", "조길동"));
nameStream = nameSet.stream();
names = nameStream.collect(Collectors.toList());
System.out.println(names); // [신길동, 나길동, 조길동]
Built In Method
- filter
- 만족하는 데이터만 걸러낼 때 사용
- 매개변수 predicate에 true를 리턴하는 데이터만 존재하는 별도의 Stream 리턴
Stream<T> filter(Predicate<? super T> predicate);
아래 예제는 isVerified = true인 user만 걸러내는 방법으로, filter를 사용한 코드다.
@Getter
@Builder
@ToString
class User {
private int id;
private String name;
private String email;
private boolean isVerified;
}
public class Exercise {
public static void main(String[] args) {
User user1 = User.builder()
.id(1)
.name("아이언맨")
.email("ironMan@aaa.co.kr")
.isVerified(true)
.build();
User user2 = User.builder()
.id(2)
.name("캡틴")
.email("captain@aaa.co.kr")
.isVerified(false)
.build();
User user3 = User.builder()
.id(3)
.name("토르")
.email("thor@aaa.co.kr")
.isVerified(false)
.build();
List<User> users = Arrays.asList(user1, user2, user3);
List<User> verifiedUsers = users.stream()
.filter(User::isVerified)
.collect(Collectors.toList());
System.out.println(verifiedUsers); // [User(id=1, name=아이언맨, email=ironMan@aaa.co.kr, isVerified=true, friendUserIds=null)]
}
}
- Map
- 데이터를 변형할 때 사용
- 매개변수 mapper가 데이터에 적용된 별도의 Stream을 리턴
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
아래 예제는 isVerified = true인 user의 이름을 추출하는 방법으로, filter와 map을 사용한 코드다.
@Getter
@Builder
@ToString
class User {
private int id;
private String name;
private String email;
private boolean isVerified;
}
public class Exercise {
public static void main(String[] args) {
User user1 = User.builder()
.id(1)
.name("아이언맨")
.email("ironMan@aaa.co.kr")
.isVerified(true)
.build();
User user2 = User.builder()
.id(2)
.name("캡틴")
.email("captain@aaa.co.kr")
.isVerified(false)
.build();
User user3 = User.builder()
.id(3)
.name("토르")
.email("thor@aaa.co.kr")
.isVerified(false)
.build();
User user4 = User.builder()
.id(4)
.name("스파이더맨")
.email("spiderMan@aaa.co.kr")
.isVerified(true)
.build();
List<User> users = Arrays.asList(user1, user2, user3, user4);
List<String> verifiedUserNames = users.stream()
.filter(User::isVerified)
.map(User::getName)
.collect(Collectors.toList());
System.out.println(verifiedUserNames); // [아이언맨, 스파이더맨]
}
}
- sorted
- 데이터가 정렬되어 있는 Stream을 리턴
- 데이터 종류에 따라서 Comparator가 필요
Stream<T> sorted();
Stream<T> sorted(Comparator<? super T> comparator);
아래 예제는 sorted를 사용하여 정렬하는 코드다.
@Getter
@Builder
@ToString
class User {
private int id;
private String name;
private String email;
private boolean isVerified;
}
public class Exercise {
public static void main(String[] args) {
User user1 = User.builder()
.id(1)
.name("아이언맨")
.email("ironMan@aaa.co.kr")
.isVerified(true)
.build();
User user2 = User.builder()
.id(2)
.name("캡틴")
.email("captain@aaa.co.kr")
.isVerified(false)
.build();
User user3 = User.builder()
.id(3)
.name("토르")
.email("thor@bbb.co.kr")
.isVerified(false)
.build();
User user4 = User.builder()
.id(4)
.name("스파이더맨")
.email("spiderMan@bbb.co.kr")
.isVerified(true)
.build();
User user5 = User.builder()
.id(5)
.name("슈퍼맨")
.email("superMan@aaa.co.kr")
.isVerified(true)
.build();
User user6 = User.builder()
.id(6)
.name("배트맨")
.email("batMan@bbb.co.kr")
.isVerified(true)
.build();
List<User> users = Arrays.asList(user6, user5, user1, user2, user3, user4);
List<Integer> sortedByUserIds = users.stream()
.filter(User::isVerified)
.filter(user -> user.getEmail().contains("@aaa.co.kr"))
.map(User::getId)
.sorted()
.collect(Collectors.toList());
System.out.println(sortedByUserIds); // [1, 5]
sortedByUserIds = users.stream()
.filter(User::isVerified)
.filter(user -> user.getEmail().contains("@aaa.co.kr"))
.map(User::getId)
.sorted(Comparator.reverseOrder())
.collect(Collectors.toList());
System.out.println(sortedByUserIds); // [5, 1]
List<String> sortedByUserNames = users.stream()
.filter(User::isVerified)
.filter(user -> user.getEmail().contains("@bbb.co.kr"))
.sorted(Comparator.comparing(User::getName))
.map(User::getName)
.collect(Collectors.toList());
System.out.println(sortedByUserNames); // [배트맨, 스파이더맨]
}
}
- distinct
- 중복 데이터가 제거된 Stream을 리턴
Stream<T> distinct();
@Getter
@Builder
@ToString
class User {
private int id;
private String name;
private String email;
private boolean isVerified;
}
public class Exercise {
public static void main(String[] args) {
User user1 = User.builder()
.id(1)
.name("아이언맨")
.email("ironMan@aaa.co.kr")
.isVerified(true)
.build();
User user2 = User.builder()
.id(2)
.name("아이언맨")
.email("ironMan@aaa.co.kr")
.isVerified(true)
.build();
User user3 = User.builder()
.id(3)
.name("토르")
.email("thor@bbb.co.kr")
.isVerified(false)
.build();
List<User> users = Arrays.asList(user1, user2, user3);
List<String> distinctUserNames = users.stream()
.filter(User::isVerified)
.map(User::getName)
.distinct()
.collect(Collectors.toList());
System.out.println(distinctUserNames); // [1, 5]}
}
}
- flatMap
- 데이터에 함수를 사용한 후 중첩된 Stream을 하나로 연결하여 하나의 Stream을 리턴
<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);
아래 예제는 flatMap을 사용하는 방법을 설명한다.
Stream의 Stream과 같이 어색하고 이상하고 찝찝한 객체가 생성된다면 flatMap을 사용해서 하나로 연결시켜주면 간단하게 해결할 수 있다.
String[][] names = {
{"스파이더맨", "토르"},
{"캡틴", "아이언맨"}
};
Stream<Stream<String>> nameStreamStream = Arrays.stream(names).map(x -> Arrays.stream(x));
List<Stream<String>> result = nameStreamStream.collect(Collectors.toList());
System.out.println(result); // [java.util.stream.ReferencePipeline$Head@{주소값}, java.util.stream.ReferencePipeline$Head@{주소값}]
Stream<String> nameStream = Arrays.stream(names).flatMap(x -> Arrays.stream(x));
List<String> result2 = nameStream.collect(Collectors.toList());
System.out.println(result2); // [스파이더맨, 토르, 캡틴, 아이언맨]
반응형
'프로그래밍 > JAVA' 카테고리의 다른 글
STREAM 활용 (0) | 2022.08.23 |
---|---|
Optional (0) | 2022.08.12 |
Method Reference (0) | 2022.07.14 |
Functional Interface (0) | 2022.07.06 |
Lambda Expression (0) | 2022.07.06 |