시뻘건 개발 도전기

Stream 본문

프로그래밍/JAVA

Stream

시뻘건볼때기 2022. 7. 25. 18:03
반응형

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
Comments