Search
Duplicate
🎳

kotlin 에서 stream 을 지워보자, kotlin 함수를 사용하기

태그
Kotlin
Java
공개여부
작성일자
2021/08/11
java 를 쓰다가 kotlin 으로 넘어오다 보니 여러 곳에서 stream 을 사용하다가 최근에 이런 리뷰를 받았다. kotlin에선 더 간결한 collection 함수를 제공하기 때문에 굳이 stream 을 사용할 필요가 없다는 것이다
코틀린을 자바같이 쓰면 앙대앙대
그래서 이 코드를 바꿧고 다시 리뷰를 받았는데
엉엉.... 마감은 다가오고
그래 이왕 이렇게 된김에 Stream 을 모두 한번 제거해보자 라는 생각이 들었다.
collection에 . 찍고 보면 뭐가 있을지 대충 보이잖아? 그래서 비교하며 간단히 메모해두려고 한다

Kotlin 으로 Map (key, value) 만들기

val dormantById = dormantRepository.findAll().stream() .collect(Collectors.toMap(AccountDormant::id, Function.identity()))
Kotlin
Java 인가 Kotlin 인가
이 코드는 다음과 같이 수정이 가능하다
val dormantById = dormantRepository.findAll().map { it.id to it }.toMap()
Kotlin
그런데 똑똑한 IntelliJ 는 여기에 추천 코드를 보여줬다
val dormantById = dormantRepository.findAll().associateBy { it.id }
Kotlin
왠지 이게 제일 맘에들어
3가지 모두 다 key-value 형태의 Map 을 만들어준다.

Kotlin 으로 Set (key) 만들기

val accountIds = items.stream().map { it.id }.collect(Collectors.toSet())
Kotlin
Java 인가 Kotlin 인가
이 코드 역시 쉽게 변환이 가능하다
val accountIds = items.map { it.id }.toSet()
Kotlin
처음엔 toSet() 을 바로 붙일 수 있는줄 알고 이러기도 해보고 저러기도 해봤다
kotlin 에서 map 이라는 친구는 stream().map 과 하는 행동이 비슷한가보다
/** * Applies the given [transform] function to each element of the original collection * and appends the results to the given [destination]. */ public inline fun <T, R, C : MutableCollection<in R>> Iterable<T>.mapTo(destination: C, transform: (T) -> R): C { for (item in this) destination.add(transform(item)) return destination }
Kotlin
kotlin 에서 정의된 mapTo 라는 함수
transform 하는데 사용한다고 한다

Kotlin 으로 List 만들기

사실 딱히 예시가 없긴하지만 그래도 구색은 맞춰야 하니 한번 만들어보자
val accountIdList = accountRepository.findAll().stream() .map{ it.id } .collect(Collectors.toList())
Kotlin
이상하게 이렇게 쓸 일은 없었다 코틀린 사용한지 이제 3개월 되었으니
val accountIdList = accountRepository.findAll().map { it.id }.toList()
Kotlin
중요한건 map 인듯 하다

shuffle, entries

test 에서 id 하나를 추출하여 데이터를 삭제하고 다시 batch 를 수행하여 멱등성이 보장되는지 검증하는 코드가 있었다. 그 코드의 원본은 아래와 같았다
val account = dormantRepository.findByEmail("test1@gmail.com")!! notificationRepository.deleteByAnotherId(account.anotherId) notificationRepository.flush()
Kotlin
문제는 deleteByAnotherId 라는 값이 test code 만을 위해 repository 에 생성된 코드인데 우리팀에서 이러한 코드는 지양하고 있다. 굳이 테스트를 위해서 어떠한 기능을 만들 필요는 없다고 여기고 있다.
그래서 다음과 같이 수정하였다.
val pick = dormantRepository.findAll().associateBy { it.anotherId }.entries.shuffled().first().also { notificationRepository.delete(notificationRepository.findByAnotherId(it.value.anotherId)!!) notificationRepository.flush() }
Kotlin
핵심은 collection API 에서 제공하는 entriessuffled 이다
/** * Returns a read-only [Set] of all key/value pairs in this map. */ public val entries: Set<Map.Entry<K, V>>
Kotlin
read-only 의 key-value entries 를 반환해준다
/** * Returns a new list with the elements of this list randomly shuffled. */ @SinceKotlin("1.2") public actual fun <T> Iterable<T>.shuffled(): List<T> = toMutableList().apply { shuffle() }
Kotlin
이 코드에서 shuffle() 은 다음을 호출한다
/** * Randomly shuffles elements in this mutable list. */ @kotlin.internal.InlineOnly @SinceKotlin("1.2") public actual inline fun <T> MutableList<T>.shuffle() { java.util.Collections.shuffle(this) }
Kotlin
그리고 이 shufflejava.util.Collections 안에 있는 shuffle 이다.
그간 java 를 사용하면서 단 한번도 사용해본적이 없었는데 (그땐 이렇게 하드하게 테스트를 짜지 않았으니깐)
/** * Randomly permutes the specified list using a default source of * randomness. All permutations occur with approximately equal * likelihood. * * <p>The hedge "approximately" is used in the foregoing description because * default source of randomness is only approximately an unbiased source * of independently chosen bits. If it were a perfect source of randomly * chosen bits, then the algorithm would choose permutations with perfect * uniformity. * * <p>This implementation traverses the list backwards, from the last * element up to the second, repeatedly swapping a randomly selected element * into the "current position". Elements are randomly selected from the * portion of the list that runs from the first element to the current * position, inclusive. * * <p>This method runs in linear time. If the specified list does not * implement the {@link RandomAccess} interface and is large, this * implementation dumps the specified list into an array before shuffling * it, and dumps the shuffled array back into the list. This avoids the * quadratic behavior that would result from shuffling a "sequential * access" list in place. * * @param list the list to be shuffled. * @throws UnsupportedOperationException if the specified list or * its list-iterator does not support the {@code set} operation. */ public static void shuffle(List<?> list) { Random rnd = r; if (rnd == null) r = rnd = new Random(); // harmless race. shuffle(list, rnd); }
Java
List 가 shuffle 된다, 안전하게
TOP