티스토리 뷰
반응형
간단한 토이 프로젝트를 진행하던 중, List의 요소를 랜덤하게 뒤섞되
문자열 인자의 값에 따라 섞는 방법을 결정해야 하는 경우가 생겼다.
내가 써놓고도 뭔 소리인지 모르겠다. 더 자세히 말해보면, 상술한 기능을 하는 함수 A는 다음과 같은 요구 사항을 충족해야 했다:
- 함수 A는 List<T> 인자 하나와 문자열 인자 하나를 받아 다시 List<T>를 반환해야 한다.
- 함수 A에 의해 반환된 List는 첫 번째 인자로 전달된 List를 랜덤하게 뒤섞은 결과여야 한다.
- 함수 A에 전달된 문자열 인자가 동일한 경우, 항상 같은 순서로 뒤섞인 List가 반환되어야 한다.
즉, A("first")와 A("first")의 결과는 같지만 A("first")와 A("second")는 달라야 한다.
아시다시피 Kotlin은 List의 요소를 랜덤하게 뒤섞는 shuffled() 확장 함수를 다음과 같이 지원한다.
class Playground {
@Test
fun `shuffled() 확장 함수는 List의 요소를 랜덤하게 뒤섞는다`() {
val list = listOf(1, 2, 3, 4, 5)
println(list.shuffled()) // [4, 5, 1, 3, 2]
println(list.shuffled()) // [4, 2, 1, 5, 3]
println(list.shuffled()) // [3, 4, 5, 1, 2]
}
}
그런데 shuffled() 확장 함수는 내부적으로 Java Collection의 shuffle() 메소드를 호출하며, 해당 메소드는 다시 내부적으로 Random() 인스턴스에 따라 동작하고 있는 것을 알 수 있다.
즉, Random() 인스턴스의 값에 따라 섞임 순서가 결정되기에 동일한 문자열에 대해 동일한 Random() 인스턴스가 생성되도록 보장하면 된다. 참고로, Random() 인스턴스는 생성자에 Int 인자를 전달 받으므로 함수 A의 문자열 인자를 그대로 생성자에 전달하기보다는 hashCode()를 통해 Int로 해싱한 후에 전달해야 한다.
다행히도 Kotlin은 shuffled() 확장 함수를 오버로딩하여 Random() 인스턴스를 인자로 전달 받는 친구를 이미 만들어두었다.
이를 이용하여 나만의 확장 함수 A(아래의 코드에서, myShuffle() 확장 함수를 의미한다)를 만들어보면 다음과 같다.
class Playground {
companion object {
fun <T> List<T>.myShuffle(seed: String): List<T> = this.shuffled(Random(seed.hashCode()))
}
@Test
fun `myShuffle() 확장 함수는 인자에 따라 List의 요소를 규칙적으로 뒤섞는다`() {
val list = listOf(1, 2, 3, 4, 5)
// 호출 시 인자가 항상 같으므로 동일하게 뒤섞인다.
println(list.myShuffle("seed")) // [3, 4, 1, 5, 2]
println(list.myShuffle("seed")) // [3, 4, 1, 5, 2]
println(list.myShuffle("seed")) // [3, 4, 1, 5, 2]
// 호출 시 인자가 같다면 동일하게 뒤섞이지만, uuid가 실행 시마다 변경된다는 점에 유의하자.
val uuid = UUID.randomUUID().toString()
println(list.myShuffle(uuid)) // [5, 1, 4, 3, 2]
println(list.myShuffle(uuid)) // [5, 1, 4, 3, 2]
println(list.myShuffle(uuid)) // [5, 1, 4, 3, 2]
}
}
잘 동작한다.
'Dev. > Kotlin' 카테고리의 다른 글
[mockk] private extension function 모킹하기 (0) | 2024.10.28 |
---|---|
[Kotlin] Class should have [public, protected] no-arg constructor 해결법 (0) | 2024.02.25 |
[Kotlin] Scope Functions (0) | 2023.10.23 |
[SpringBoot] WebTestClient NoSuchBeanDefinitionException 예외 해결법 (0) | 2023.04.19 |
[Kotlin] java.security.InvalidKeyException: IOException : algid parse error 원인 (0) | 2023.03.21 |
댓글
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- shell
- mysql
- spring boot
- Spring Cloud Config
- Node.js
- pgloader
- 코딩테스트
- Linux
- Vault
- JPA
- Git
- eureka
- IntelliJ
- javascript
- Gradle
- terraform
- RancherDesktop
- JEST
- etc
- AWS IoT
- Puppeteer
- postgresql
- jQuery
- kotlin
- AWS
- Database
- hashicorp
- Docker
- react
- Java
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
글 보관함