associate
associate()
를 이용하면 List를 Map 형태로 변형시킬 수 있습니다.
단, groupBy()와의 차이점이 있습니다.
associate()
는 groupBy()와는 달리, key가 중복이 되면 마지막 요소를 Map의 value로 저장합니다. (groupBy()는 Map<K, List<T>> 형태로 만들기 때문에 key가 중복이 되어도 List에 전부 담을 수 있습니다.)
1. associate()
associate() 함수
public inline fun <T, K, V> Iterable<T>.associate(transform: (T) -> Pair<K, V>): Map<K, V> {
val capacity = mapCapacity(collectionSizeOrDefault(10)).coerceAtLeast(16)
return associateTo(LinkedHashMap<K, V>(capacity), transform)
}
associateTo() 함수
public inline fun <T, K, V, M : MutableMap<in K, in V>> Iterable<T>.associateTo(destination: M, transform: (T) -> Pair<K, V>): M {
for (element in this) {
destination += transform(element)
}
return destination
}
associate()
의 매개변수에는 T를 전달하고 Pair를 return하는 람다함수 transform을 인자로 받습니다.
List를 전체 탐색하면서 받아온 Pair를 통해 pair.first를 key로, pair.second를 value로 Map<K, V>로 만들어 return합니다.
예제
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
data class Person(val name: String, val age: Int)
internal class AssociateTest {
private lateinit var personList: List<Person>
@BeforeEach
internal fun setUp() {
personList = listOf(Person("abc", 1), Person("def", 1), Person("ghi", 2), Person("jkl", 3), Person("mno", 3))
}
@Test
fun `associate() 테스트`() {
val associateMap: Map<String, Int> = personList.associate { it.name to it.age }
println(associateMap) // {abc=1, def=1, ghi=2, jkl=3, mno=3}
}
}
2. associateBy()
associateBy() 함수
public inline fun <T, K> Iterable<T>.associateBy(keySelector: (T) -> K): Map<K, T> {
val capacity = mapCapacity(collectionSizeOrDefault(10)).coerceAtLeast(16)
return associateByTo(LinkedHashMap<K, T>(capacity), keySelector)
}
associateTo() 함수
public inline fun <T, K, M : MutableMap<in K, in T>> Iterable<T>.associateByTo(destination: M, keySelector: (T) -> K): M {
for (element in this) {
destination.put(keySelector(element), element)
}
return destination
}
associateBy()
의 매개변수에는 T를 전달하고 key를 return하는 람다함수 keySelector를 인자로 받습니다.
List를 전체 탐색하면서 매개변수로 받은 keySelector를 key로, List의 인자를 value로 Map<K, V>를 만들어 return합니다.
예제
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
data class Person(val name: String, val age: Int)
internal class AssociateTest {
private lateinit var personList: List<Person>
@BeforeEach
internal fun setUp() {
personList = listOf(Person("abc", 1), Person("def", 1), Person("ghi", 2), Person("jkl", 3), Person("mno", 3))
}
@Test
fun `associateBy() 테스트`() {
val associateMap: Map<String, Person> = personList.associateBy { it.name }
println(associateMap) // {abc=Person(name=abc, age=1), def=Person(name=def, age=1), ghi=Person(name=ghi, age=2), jkl=Person(name=jkl, age=3), mno=Person(name=mno, age=3)}
}
}
3. associateWith()
public inline fun <K, V> Iterable<K>.associateWith(valueSelector: (K) -> V): Map<K, V> {
val result = LinkedHashMap<K, V>(mapCapacity(collectionSizeOrDefault(10)).coerceAtLeast(16))
return associateWithTo(result, valueSelector)
}
public inline fun <K, V, M : MutableMap<in K, in V>> Iterable<K>.associateWithTo(destination: M, valueSelector: (K) -> V): M {
for (element in this) {
destination.put(element, valueSelector(element))
}
return destination
}
associateWith()
의 매개변수에는 T를 전달하고 V를 return하는 람다함수 valueSelector를 인자로 받습니다.
associateBy()와는 반대로 List를 전체 탐색하면서 List의 인자를 key로, 매개변수로 받은 valueSelector를 value로 Map<K, V>를 만들어 return합니다.
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
data class Person(val name: String, val age: Int)
internal class AssociateTest {
private lateinit var personList: List<Person>
@BeforeEach
internal fun setUp() {
personList = listOf(Person("abc", 1), Person("def", 1), Person("ghi", 2), Person("jkl", 3), Person("mno", 3))
}
@Test
fun `associateWith() 테스트`() {
val associateMap: Map<Person, String> = personList.associateWith { it.name }
println(associateMap) // {Person(name=abc, age=1)=abc, Person(name=def, age=1)=def, Person(name=ghi, age=2)=ghi, Person(name=jkl, age=3)=jkl, Person(name=mno, age=3)=mno}
}
}
groupBy
groupBy()
를 이용하면 List를 Map 형태로 변형시킬 수 있습니다.
associate()와는 달리, key가 중복이 되어도 value가 List<T>이므로 전부 저장합니다.
public inline fun <T, K> Iterable<T>.groupBy(keySelector: (T) -> K): Map<K, List<T>> {
return groupByTo(LinkedHashMap<K, MutableList<T>>(), keySelector)
}
public inline fun <T, K, M : MutableMap<in K, MutableList<T>>> Iterable<T>.groupByTo(destination: M, keySelector: (T) -> K): M {
for (element in this) {
val key = keySelector(element)
val list = destination.getOrPut(key) { ArrayList<T>() }
list.add(element)
}
return destination
}
groupBy()
의 매개변수에는 T를 전달하고 key를 return하는 람다함수 keySelector를 인자로 받습니다.
List를 전체 탐색하면서 List의 인자를 key로, ArrayList를 만들고 매개변수로 받은 keySelector를 value로 넣어서 Map<K, List<T>>를 만들어 return합니다.
예제1
import org.junit.jupiter.api.Test
internal class GroupByTest {
@Test
fun `groupBy() 테스트`() {
val list = listOf(0, 1, 2, 3, 4, 5, 6, 7, 8)
val groupByMap: Map<Int, List<Int>> = list.groupBy { it % 2 }
println(groupByMap) // {0=[0, 2, 4, 6, 8], 1=[1, 3, 5, 7]}
}
}
예제2
import org.junit.jupiter.api.Test
data class Person(val name: String, val age: Int)
internal class GroupByTest {
@Test
fun `groupBy() 테스트`() {
val personList = listOf(Person("abc", 1), Person("def", 1), Person("ghi", 2), Person("jk", 3))
val personGroupByMap: Map<Int, List<Person>> = personList.groupBy { it.age }
println(personGroupByMap) // {1=[Person(name=abc, age=1), Person(name=def, age=1)], 2=[Person(name=ghi, age=2)], 3=[Person(name=jk, age=3)]}
}
}