Post

Java Stream으로 성능 향상하기: 반복문에서 Stream으로의 전환

iterate 가능한 Object for 문으로 돌기


가장 처음에 Q&A 플랫폼을 개발할 당시에는 java 도 거의 처음이었고 당연히 loop 를 iterate 할때는 for 문을 사용했었다.

우리가 운영하는 서비스에는 Poll이라고 투표기능을 만들었는데 해당 Poll 에 참가한 기록은 이렇게 구성이 되어있다

1
2
id : {poll 의 id}:{투표한 사람의 profile id},
item : ["투표한 항목 1", "투표한 항목 2"],

그리고 기능 중에는 어떤 항목에 누가누가 투표했는지 보여주는 기능이 있다. 따라서 해당 투표를 한 기록 (위의 기록!) 을 싹다 가져와서 그 어떤 항목이 item 에 있는지를 확인을 해야 한다.

지금 보니까 투표한 항목 별로 따로 따로 저장하는게 훨씬 좋아보이는데 그럼 속도도 아주 괜찮게 나올꺼같다 그렇게 수정을 해야겠다

따라서 그걸 코드로 하자면 다음과 비슷하게 된다.

1
2
3
4
5
6
7
for (PollParticipant p : pollParticipant) {
    if (p.getItem().contains(item)) {
        String[] splitId = p.getId().split(":");
        String lastElement = splitId[splitId.length - 1];
        result.add(lastElement);
    }
}

Stream 문으로 돌기


하지만 이 작업이 투표한 사람이 몇백명이 넘어가니까 조금 시간이 걸리게 되는 것을 발견했다… 따라서 Stream 을 사용하기로 했다.

우선 Stream 은 장점이 여러가지 있지만 나로써 체감하는것은 2가지가 제일 크다

  1. 코드가 조금 더 보기 쉬워진다
  2. parallel 하게동작해도 되는 iteration 이라면 아주아주 쉽게 병렬로 가능하다 위의 코드를 stream 으로 한번 바꿔보면 다음과 같다
1
2
3
4
5
pollParticipant.stream()
	.filter(p -> p.,getItem().contains(item))
	.map(p -> Arrays.asList(p.getId().split(":")))
	.map(list -> list.get(list.size() - 1))
	.collect(Collectors.toList());

처음 stream 을 접한다면 조금은 어렵지만 잘 보면 indent 도 늘어 나지 않고 하는 역할을 확실하게 알 수 있다. 지금은 filter 가 1개여서 망정이지 filter 가 여러개라면 for 문으로 작성했을경우 화살촉 코드가 되어버릴것이다!

여기에서 parallel 하게 만드는 방법은 정말이지 간단하다 바로 stream 을 parallelStream으로 바꿔주는 것이다.

1
2
3
4
5
pollParticipant.parallelStream()
	.filter(p -> p.,getItem().contains(item))
	.map(p -> Arrays.asList(p.getId().split(":")))
	.map(list -> list.get(list.size() - 1))
	.collect(Collectors.toList());

지금 코드의 동작과 return 값을 그저 순서 상관없이 보여주는 것이라서 parallelStream으로 으로 바꾸어도 전혀 무방하다. 이때 parallel stream 으로 상당히 큰 개선을 한 이후로 지나가다가 for 문을 보면 stream으로 하면 좋은가 아닌가를 생각하게 되었다!

This post is licensed under CC BY 4.0 by the author.

© 병욱. Some rights reserved.