groupBy
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 32 33 data class Member ( val name: String, val status: MemberStatus ) enum class MemberStatus (description: String) { NORMAL("정산" ), VAN("정지" ) } class Collection { @Test fun groupBy () { val members = (1. .50 ).map { Member( name = "name${it} " , status = when { (0. .1 ).random() == 0 -> MemberStatus.NORMAL else -> MemberStatus.VAN } ) } val groupBy = members.groupBy { it.status } val vanMembers = groupBy[MemberStatus.VAN] val normalMembers = groupBy[MemberStatus.NORMAL] val groupBy1 = members.groupBy( { it.status }, { it.name } ) } }
컬렉션의 특정 값으로 그룹화를 진행이 가능하다. 그룹화 한 값은 LinkedHashMap 컬렉션으로 리턴되며 (1),(2)처럼 Key 값으로 리턴할 수 있다.
만약 리턴되는 객체를 컬렉션 요소의 객체가 아닌 객체를 리턴 받고 싶다면 (3)처럼 가능하다. 해당 객체는 Member 객체가 아닌 name 필드만 추출한 코드이다.
groupingBy
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 data class Order ( val orderNumber: String, val status: OrderStatus, val price: Int ) enum class OrderStatus (description: String) { COMPLETE_ORDER("주문 완료" ), COMPLETE_PAYMENT("결제 완료" ), } class Collection { @Test fun groupingBy () { val orders = (1. .10 ).map { Order( orderNumber = "name${it} " , status = when { (0. .1 ).random() == 0 -> OrderStatus.COMPLETE_ORDER else -> OrderStatus.COMPLETE_PAYMENT }, price = (100. .15000 ).random() ) } val groupingBy = orders .groupingBy { it.status } val aggregate = groupingBy .aggregate { key, accumulator: OrderPrice?, element, first -> when { first -> OrderPrice(orderStatus = key, price = element.price) else -> OrderPrice(orderStatus = key, price = accumulator!!.price + element.price) } } val totalPrice1 = aggregate[OrderStatus.COMPLETE_ORDER] val totalPrice2 = aggregate[OrderStatus.COMPLETE_PAYMENT] val eachCount = groupingBy.eachCount() val count1 = eachCount[OrderStatus.COMPLETE_ORDER] val count2 = eachCount[OrderStatus.COMPLETE_PAYMENT] } }
groupingBy는 컬렉션에 대해서 그룹화하여 이후 다양한 연산을 편리한 제공할 수 있는 Grouping 객체로 리턴해줍니다.
(1) groupingBy으로 Grouping 객체로 응답받고 해당 확장함 수로 다양한 연산 작업이 가능합니다. (2) aggregate으로 groupingBy된 값 기반으로 가격에 대한 sum 작업, (3) eachCount으로 groupingBy된 카운트를 조회 가능합니다.
chunked
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 class Collection { @Test fun chunked () { val orders = (1. .100 ).map { Order( orderNumber = "name${it} " , status = when { (0. .1 ).random() == 0 -> OrderStatus.COMPLETE_ORDER else -> OrderStatus.COMPLETE_PAYMENT }, price = (100. .15000 ).random() ) } val chunked = orders.chunked(10 ) } }
chunked는 컬렉션 객체를 넘겨받은 인자 크기만큼 컬렉션을 나눕니다.
100개의 orders 객체를 10개로 나누면 10개 컬렉션이 10개가 됩니다. 말 그대로 청크를 나누는 컬렉션 객체입니다. 처리해야 할 데이터가 너무 크다면 적절한 청크 처리하는 경우 유용합니다.
flatMap
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 32 33 34 35 36 class Collection { data class OrderNumbers ( val orderStatus: OrderStatus, val orderNumbers: Set<String> ) enum class OrderStatus (description: String) { COMPLETE_ORDER("주문 완료" ), COMPLETE_PAYMENT("결제 완료" ), } @Test fun flatMap () { val orderNumbers = listOf( OrderNumbers( orderStatus = OrderStatus.COMPLETE_ORDER, orderNumbers = setOf("order-number-1" , "order-number-2" , " order-number-3" , "order-number-3" ), ), OrderNumbers( orderStatus = OrderStatus.COMPLETE_ORDER, orderNumbers = setOf("order-number-4" , "order-number-5" , " order-number-6" , "order-number-7" ), ), OrderNumbers( orderStatus = OrderStatus.COMPLETE_PAYMENT, orderNumbers = setOf("order-number-8" , "order-number-9" , " order-number-10" , "order-number-11" ), ), OrderNumbers( orderStatus = OrderStatus.COMPLETE_PAYMENT, orderNumbers = setOf("order-number-11" , "order-number-12" , " order-number-13" , "order-number-14" ), ) ) val flatMap = orderNumbers.flatMap { it.orderNumbers } } }
flatMap은 여러 컬렉션을 합쳐서 하나의 컬렉션으로 합쳐줍니다. 위처럼 여러 컬렉션 객체 안의 컬렉션 객체가 있는 경우 하나의 컬렉션으로 flatMap을 통해서 합칠 수 있습니다.
orderNumbers로 각 객체에 있던 값들을 한 컬렉션으로 합쳐진 것을 확인할 수 있습니다.