└── README.md /README.md: -------------------------------------------------------------------------------- 1 | # Kotlin Collection Functions 2 | 3 | The Kotlin standard library offers a broad variety of functions for performing operations on collections. This includes simple operations, such as getting or adding elements, as well as more complex ones including search, sorting, filtering, transformations, and so on. 4 | 5 | # Contents 6 | - [distinct](#distinct) 7 | - [joinToString](#jointostring) 8 | - [reduce](#reduce) 9 | - [fold](#fold) 10 | - [all](#all) 11 | - [single](#single) 12 | - [find](#find) 13 | - [chunked](#chunked) 14 | - [copyInto](#copyinto) 15 | - [Changing type of collection to other](#changing-type-of-collection-to-other) 16 | - [associateBy](#associateby) 17 | - [Zip, Unzip](#zip-unzip) 18 | - [filter, filterNot](#filter-filternot) 19 | - [union](#union) 20 | - [intersect](#intersect) 21 | - [map](#map) 22 | - [flatMap](#flatmap) 23 | - [binarySearch](#binarysearch) 24 | - [groupBy](#groupby) 25 | - [sorted, sortedDescending](#sorted-sorteddescending) 26 | - [sortedBy](#sortedby) 27 | - [reversed, asReversed](#reversed-asreversed) 28 | - [retainAll](#retainall) 29 | - [removeFirst, removeLast, removeAll](#removefirst-removelast-removeall) 30 | - [partition](#partition) 31 | - [sum()](#sum) 32 | - [sumBy](#sumby) 33 | - [maxOrNull, minOrNull](#maxornull-minornull) 34 | - [maxByOrNull, minByOrNull](#maxbyornull-minbyornull) 35 | - [maxWithOrNull](#maxwithornull) 36 | - [drop, dropLast, dropWhile, dropLastWhile](#drop-droplast-dropwhile-droplastwhile) 37 | 38 | ## Helper Class 39 | ``` 40 | data class User( 41 | val id: Int, 42 | val name: String, 43 | val webDev: Boolean = false, 44 | val mobileDev: Boolean = false 45 | ) 46 | 47 | data class Product(val name: String, val quantity: Int, val price: Double) 48 | 49 | class Items(val items: List) 50 | 51 | data class Contact(val name: String, val phoneNumber: String) 52 | ``` 53 | 54 | ## `distinct` 55 | Retreive Distinct Items from Collection 56 | ``` 57 | fun distinctExample() { 58 | // Maintain the original order of items 59 | val devs = arrayOf("Alan", "Jones", "Bob", "Joe", "David", "Joe") 60 | println(devs.distinct()) // [Alan, Jones, Bob, David] 61 | 62 | // Maintain the original order of items 63 | println(devs.toSet()) // [Alan, Jones, Bob, David] 64 | 65 | // Maintain the original order of items 66 | println(devs.toMutableSet()) // [Alan, Jones, Bob, David] 67 | 68 | // DO NOT Maintain the original order of items 69 | println(devs.toHashSet()) // [Jones, Joe, Bob, Alan, David] 70 | } 71 | ``` 72 | Output: 73 | 74 | ``` 75 | [Alan, Jones, Bob, Joe, David] 76 | [Alan, Jones, Bob, Joe, David] 77 | [Alan, Jones, Bob, Joe, David] 78 | [Jones, Joe, Bob, Alan, David] 79 | ``` 80 | 81 | ## `joinToString` 82 | Convert an array or list to a string 83 | 84 | ``` 85 | fun joinToStringExample() { 86 | val someKotlinCollectionFunctions = listOf( 87 | "distinct", "map", 88 | "isEmpty", "contains", 89 | "filter", "first", 90 | "last", "reduce", 91 | "single", "joinToString" 92 | ) 93 | 94 | val message = someKotlinCollectionFunctions.joinToString( 95 | separator = ", ", 96 | prefix = "Kotlin has many collection functions like: ", 97 | postfix = "and they are awesome.", 98 | limit = 3, 99 | truncated = "etc " 100 | ) 101 | 102 | println(message) 103 | } 104 | ``` 105 | 106 | Output: 107 | ``` 108 | Kotlin has many collection functions like: distinct, map, isEmpty, etc and they are awesome. 109 | ``` 110 | 111 | ## `Reduce` 112 | Transform a collection into a single result 113 | 114 | ``` 115 | fun reduceExample() { 116 | // NOTE: If the list is empty, then it will throw a RuntimeException 117 | val numList = listOf(1, 2, 3, 4, 5) 118 | val result = numList.reduce { result, item -> 119 | result + item 120 | } 121 | println(result) // 15 122 | } 123 | ``` 124 | 125 | Output: 126 | ``` 127 | 15 128 | ``` 129 | 130 | ## `fold` 131 | Transform a collection into a single result 132 | 133 | ``` 134 | fun foldExample() { 135 | /*The difference between fold() & reduce() is that fold() takes an initial value and uses it as the 136 | accumulated value on the first step, whereas the first step of reduce() uses the first and the second 137 | elements as operation arguments on the first step.*/ 138 | val numList = listOf(1, 2, 3, 4, 5) 139 | val result = numList.fold(0, { result, item -> 140 | result + item 141 | }) 142 | println(result) // 15 143 | } 144 | ``` 145 | 146 | Output: 147 | ``` 148 | 15 149 | ``` 150 | 151 | ## `All` 152 | Find if all elements are satisfying a particular condition 153 | 154 | ``` 155 | fun allExample() { 156 | val user1 = User(id = 1, name = "Alan", webDev = true, mobileDev = false) 157 | val user2 = User(id = 2, name = "Joe", webDev = true, mobileDev = false) 158 | val user3 = User(id = 3, name = "Bob", webDev = true, mobileDev = false) 159 | val user4 = User(id = 4, name = "Jenny", webDev = true, mobileDev = false) 160 | 161 | val users = arrayOf(user1, user2, user3, user4) 162 | 163 | val allWebDevs = users.all { it.webDev } 164 | println(allWebDevs) // true 165 | 166 | val allMobileDevs = users.all { it.mobileDev } 167 | println(allMobileDevs) // false 168 | } 169 | ``` 170 | 171 | Output: 172 | ``` 173 | true 174 | false 175 | ``` 176 | 177 | ## `Single` 178 | Find a single element based on a certain condition 179 | 180 | ``` 181 | fun singleExample() { 182 | val users = arrayOf( 183 | User(1, "Alan"), 184 | User(2, "Bob"), 185 | User(3, "Joe"), 186 | User(4, "Jenny") 187 | ) 188 | 189 | val userWithId3 = users.single { it.id == 3 } 190 | println(userWithId3) // User(id=3, name=Joe) 191 | } 192 | ``` 193 | 194 | Output: 195 | ``` 196 | User(id=3, name=Joe, webDev=false, mobileDev=false) 197 | ``` 198 | 199 | ## `Find` 200 | Find a particular element based on a certain condition 201 | 202 | ``` 203 | fun findExample() { 204 | val users = arrayOf( 205 | User(1, "Alan"), 206 | User(2, "Bob"), 207 | User(3, "Joe"), 208 | User(4, "Jenny") 209 | ) 210 | val userWithId1 = users.find { it.id == 1 } 211 | println(userWithId1) // User(id=1, name=Alan) 212 | } 213 | ``` 214 | 215 | Output: 216 | ``` 217 | User(id=1, name=Alan, webDev=false, mobileDev=false) 218 | ``` 219 | 220 | ## `chunked` 221 | Break your list into multiple sublists of smaller size 222 | 223 | ``` 224 | fun chunkedExample() { 225 | val numList = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) 226 | val chunkedLists = numList.chunked(3) 227 | print(chunkedLists) // [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]] 228 | println() 229 | } 230 | ``` 231 | 232 | Output: 233 | ``` 234 | [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]] 235 | ``` 236 | 237 | ## `copyInto` 238 | Making copies of the array 239 | 240 | ``` 241 | fun copyArray() { 242 | val arrayOne = arrayOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) 243 | val arrayTwo = arrayOf(11, 12, 13, 14, 15, 16, 17, 18, 19, 20) 244 | arrayOne.copyInto( 245 | destination = arrayTwo, 246 | destinationOffset = 2, 247 | startIndex = 0, 248 | endIndex = 4 249 | ) 250 | arrayTwo.forEach { print("$it ") } // 11 12 1 2 3 4 17 18 19 20 251 | println() 252 | } 253 | ``` 254 | 255 | Output: 256 | ``` 257 | 11 12 1 2 3 4 17 18 19 20 258 | ``` 259 | 260 | ## Changing type of collection to other 261 | 262 | ``` 263 | fun changeTypeExample() { 264 | var uIntArray = UIntArray(5) { 1U } 265 | val intArray = uIntArray.toIntArray() 266 | intArray[0] = 0 267 | println(uIntArray.toList()) // [1, 1, 1, 1, 1] 268 | println(intArray.toList()) // [0, 1, 1, 1, 1] 269 | } 270 | ``` 271 | 272 | Output: 273 | ``` 274 | [1, 1, 1, 1, 1] 275 | [0, 1, 1, 1, 1] 276 | ``` 277 | 278 | ## `associateBy` 279 | Associating the data using some key 280 | 281 | ``` 282 | fun associateByExample() { 283 | val contactList = listOf( 284 | Contact("Alan", "+9199XXXX1111"), 285 | Contact("Bob", "+9199XXXX2222"), 286 | Contact("Joe", "+9199XXXX3333"), 287 | Contact("Jenny", "+9199XXXX4444") 288 | ) 289 | 290 | val phoneNumberToContactMap = contactList.associateBy { it.phoneNumber } 291 | println(phoneNumberToContactMap) 292 | // Map with key: phoneNumber and value: Contact 293 | // { 294 | // +9199XXXX1111=Contact(name=Alan, phoneNumber=+9199XXXX1111), 295 | // +9199XXXX2222=Contact(name=Bob, phoneNumber=+9199XXXX2222), 296 | // +9199XXXX3333=Contact(name=Joe, phoneNumber=+9199XXXX3333), 297 | // +9199XXXX4444=Contact(name=Jenny, phoneNumber=+9199XXXX4444) 298 | // } 299 | 300 | val phoneNumberToContactMap2 = contactList.associateBy({ it.phoneNumber }, { it.name }) 301 | println(phoneNumberToContactMap2) 302 | // Map with key: phoneNumber and value: name 303 | // { 304 | // +9199XXXX1111=Alan, 305 | // +9199XXXX2222=Bob, 306 | // +9199XXXX3333=Joe, 307 | // +9199XXXX4444=Jenny} 308 | // } 309 | } 310 | ``` 311 | 312 | Output: 313 | ``` 314 | {+9199XXXX1111=Contact(name=Alan, phoneNumber=+9199XXXX1111), +9199XXXX2222=Contact(name=Bob, phoneNumber=+9199XXXX2222), +9199XXXX3333=Contact(name=Joe, phoneNumber=+9199XXXX3333), +9199XXXX4444=Contact(name=Jenny, phoneNumber=+9199XXXX4444)} 315 | 316 | {+9199XXXX1111=Alan, +9199XXXX2222=Bob, +9199XXXX3333=Joe, +9199XXXX4444=Jenny} 317 | ``` 318 | 319 | ## `Zip, Unzip` 320 | Zip or Unzip a Collection 321 | 322 | ``` 323 | fun zipExample() { 324 | val listOne = listOf(1, 2, 3, 4, 5) 325 | val listTwo = listOf("a", "b", "c", "d", "e", "f") 326 | println(listOne zip listTwo) // [(1, a), (2, b), (3, c), (4, d), (5, e)] 327 | 328 | //zipWithNext return a list of pairs. The elements of the pair will be the adjacent elements of the collection. 329 | val list = listOf(1, 2, 3, 4, 5) 330 | println(list.zipWithNext()) // [(1, 2), (2, 3), (3, 4), (4, 5)] 331 | 332 | //Unzip 333 | val list2 = listOf("Alan" to 8, "Bob" to 10, "Joe" to 4, "Jenny" to 2) 334 | val (players, devSkills) = list2.unzip() 335 | println(players) // [Alan, Bob, Joe, Jenny] 336 | println(devSkills) // [8, 10, 4, 2] 337 | } 338 | ``` 339 | 340 | Output: 341 | ``` 342 | [(1, a), (2, b), (3, c), (4, d), (5, e)] 343 | [(1, 2), (2, 3), (3, 4), (4, 5)] 344 | [Alan, Bob, Joe, Jenny] 345 | [8, 10, 4, 2] 346 | ``` 347 | 348 | ## `filter, filterNot` 349 | Filter a collection based on some condition 350 | 351 | ``` 352 | fun filterExample() { 353 | val list = listOf(1, 2, 3, 4, 5, 6, 7, 8) 354 | val evenList = list.filter { it % 2 == 0 } 355 | println(evenList) // [2, 4, 6, 8] 356 | 357 | //Filter Not 358 | val oddList = list.filterNot { it % 2 == 0 } 359 | println(oddList) // [1, 3, 5, 7] 360 | 361 | //Similarly, you can filter the collection based on the index of elements by using filterIndexed. 362 | 363 | //If you want to store the filtered elements in some collection, then you can use the filterIndexedTo: 364 | 365 | val list2 = listOf(1, 2, 3, 4, 5, 6, 7, 8) 366 | val filteredList2 = mutableListOf() 367 | list2.filterIndexedTo(filteredList2) { index, i -> list[index] % 2 == 0 } 368 | println(filteredList2) // [2, 4, 6, 8] 369 | 370 | //You can also find the elements that are instances of a specified type in a collection by using 371 | // filterIsInstance. 372 | 373 | val mixedList = listOf(1, 2, 3, "one", "two", 4, "three", "four", 5, 6, "five", 7) 374 | val strList = mixedList.filterIsInstance() 375 | println(strList) // [one, two, three, four, five] 376 | } 377 | ``` 378 | 379 | Output: 380 | ``` 381 | [2, 4, 6, 8] 382 | [1, 3, 5, 7] 383 | [2, 4, 6, 8] 384 | [one, two, three, four, five] 385 | ``` 386 | 387 | ## `union` 388 | Union of collections 389 | 390 | ``` 391 | fun unionExample() { 392 | val listOne = listOf(1, 2, 3, 3, 4, 5, 6) 393 | val listTwo = listOf(2, 2, 4, 5, 6, 7, 8) 394 | println(listOne.union(listTwo)) // [1, 2, 3, 4, 5, 6, 7, 8] 395 | } 396 | ``` 397 | 398 | Output: 399 | ``` 400 | [1, 2, 3, 4, 5, 6, 7, 8] 401 | ``` 402 | 403 | ## `intersect` 404 | Intersection of collections 405 | 406 | ``` 407 | fun intersectionExample() { 408 | val listOne = listOf(1, 2, 3, 3, 4, 5, 6) 409 | val listTwo = listOf(2, 2, 4, 5, 6, 7, 8) 410 | println(listOne.intersect(listTwo)) // [2, 4, 5, 6] 411 | } 412 | ``` 413 | 414 | Output: 415 | ``` 416 | [2, 4, 5, 6] 417 | ``` 418 | 419 | ## `map` 420 | Map a collection for transformation 421 | 422 | ``` 423 | fun mapExample() { 424 | val userAgeStrings = 425 | listOf("1", "15", "10", "32", "14", "45", "9", "16", "18", "19", "27", "24") 426 | //Simple map function that just converts strings to an int 427 | val userAgeInts = userAgeStrings.map { it.toInt() } 428 | //A perfect example of the filter feature here 429 | val userAgesThatCanDrive = userAgeInts.filter { it >= 16 } 430 | 431 | println("All user ages: $userAgeInts") 432 | println("User ages that can drive: $userAgesThatCanDrive") 433 | } 434 | ``` 435 | 436 | Output: 437 | ``` 438 | All user ages: [1, 15, 10, 32, 14, 45, 9, 16, 18, 19, 27, 24] 439 | User ages that can drive: [32, 45, 16, 18, 19, 27, 24] 440 | ``` 441 | 442 | ## `flatMap` 443 | Flatten Collection 444 | 445 | ``` 446 | fun mapFlatMapExample() { 447 | val dataObjects = listOf( 448 | Items(listOf("a", "b", "c")), 449 | Items(listOf("1", "2", "3")) 450 | ) 451 | 452 | //With flatMap, you can "flatten" multiple Data::items into one collection as shown with the items variable. 453 | val items: List = dataObjects 454 | .flatMap { it.items } //[a, b, c, 1, 2, 3] 455 | println(items) 456 | 457 | //Using map, on the other hand, simply results in a list of lists. 458 | val items2: List> = dataObjects 459 | .map { it.items } //[[a, b, c], [1, 2, 3]] 460 | println(items2) 461 | 462 | /*FLatten produces the same result as flatMap. So flatMap is a combination of the two functions, map{} 463 | and then flatten()*/ 464 | val nestedCollections: List = dataObjects 465 | .map { it.items } 466 | .flatten() //[a, b, c, 1, 2, 3] 467 | println(nestedCollections) 468 | } 469 | ``` 470 | 471 | Output: 472 | ``` 473 | [a, b, c, 1, 2, 3] 474 | [[a, b, c], [1, 2, 3]] 475 | [a, b, c, 1, 2, 3] 476 | ``` 477 | 478 | ## `binarySearch` 479 | Perform search in collection 480 | 481 | ``` 482 | fun binarySearchExample() { 483 | //This example uses the sort extension, so put this after it. 484 | val largeIntArray = arrayOf( 485 | 4, 486 | 9, 487 | 2, 488 | 19, 489 | 1, 490 | 3, 491 | 2, 492 | 6 493 | ) 494 | //largeIntArray.sort() 495 | println("Array = ${largeIntArray.asList()}") 496 | println("Index of element 19: ${largeIntArray.binarySearch(19)}") 497 | } 498 | ``` 499 | 500 | Output: 501 | ``` 502 | Array = [4, 9, 2, 19, 1, 3, 2, 6] 503 | Index of element 19: 3 504 | ``` 505 | 506 | ## `groupBy` 507 | Group elements of a collection based on some condition 508 | 509 | ``` 510 | fun groupByExample() { 511 | val list = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) 512 | println(list.groupBy { it % 4 }) 513 | // { 514 | // 1=[1, 5, 9], 515 | // 2=[2, 6, 10], 516 | // 3=[3, 7], 517 | // 0=[4, 8] 518 | // } 519 | } 520 | ``` 521 | 522 | Output: 523 | ``` 524 | {1=[1, 5, 9], 2=[2, 6, 10], 3=[3, 7], 0=[4, 8]} 525 | ``` 526 | 527 | ## `sorted, sortedDescending` 528 | Sort a collection 529 | 530 | ``` 531 | fun sortExample() { 532 | val unsortedAges = listOf(1, 3, 2, 7, 5, 15, 9, 8, 20, 18, 25) 533 | 534 | //Automatic sorting order is ascending 535 | val youngestToOldestAges = unsortedAges.sorted() 536 | println("Youngest to oldest ages: $youngestToOldestAges") 537 | 538 | val oldestToYoungestAges = unsortedAges.sortedDescending() 539 | println("Oldest to youngest ages: $oldestToYoungestAges") 540 | /*Similarly, there are other functions that can be used to sort the collection based on certain conditions. 541 | Some of these functions are sortedArray, sortedArrayWith, sortedBy, sortedByDescending, 542 | sortedArraydescending, sortedWith, etc.*/ 543 | } 544 | ``` 545 | 546 | Output: 547 | ``` 548 | Youngest to oldest ages: [1, 2, 3, 5, 7, 8, 9, 15, 18, 20, 25] 549 | Oldest to youngest ages: [25, 20, 18, 15, 9, 8, 7, 5, 3, 2, 1] 550 | ``` 551 | 552 | ## `sortedBy` 553 | Sort Collection by custom property 554 | 555 | ``` 556 | fun sortedByExample() { 557 | val products = listOf( 558 | Product("A1", 10, 6.90), 559 | Product("B1", 20, 3.45), 560 | Product("C1", 30, 1.05), 561 | Product("D1", 50, 5.05) 562 | ) 563 | val sorted = products.sortedBy { it.price } 564 | println(sorted) 565 | /*[Product(name=C1, quantity=30, price=1.05), 566 | Product(name=B1, quantity=20, price=3.45), 567 | Product(name=D1, quantity=50, price=5.05), 568 | Product(name=A1, quantity=10, price=6.9)]*/ 569 | } 570 | ``` 571 | 572 | Output: 573 | ``` 574 | [Product(name=C1, quantity=30, price=1.05), Product(name=B1, quantity=20, price=3.45), Product(name=D1, quantity=50, price=5.05), Product(name=A1, quantity=10, price=6.9)] 575 | ``` 576 | 577 | ## `reversed, asReversed` 578 | Reverse a collection 579 | 580 | ``` 581 | fun reverseExample() { 582 | val list = listOf(1, 2, 3, 4, 5) 583 | println(list.reversed()) // [5, 4, 3, 2, 1] 584 | println(list.asReversed()) // [5, 4, 3, 2, 1] 585 | } 586 | ``` 587 | 588 | Output: 589 | ``` 590 | [5, 4, 3, 2, 1] 591 | [5, 4, 3, 2, 1] 592 | ``` 593 | 594 | ## `retainAll` 595 | Keep the specified elements only 596 | 597 | ``` 598 | fun retainExample() { 599 | val listOne = mutableListOf(1, 2, 3, 3, 4, 5, 6) 600 | val listTwo = listOf(1, 2, 3, 3, 4, 5, 6) 601 | val listThree = listOf(1, 2, 3, 3, 4, 5, 7) 602 | println(listOne.retainAll(listTwo)) // false 603 | println(listOne.retainAll(listThree)) // true 604 | println(listOne) // [1, 2, 3, 3, 4, 5] 605 | //you can use removeAll to remove all the elements of one collection that are present in another 606 | // collection. 607 | } 608 | ``` 609 | 610 | Output: 611 | ``` 612 | false 613 | true 614 | [1, 2, 3, 3, 4, 5] 615 | ``` 616 | 617 | ## `removeFirst, removeLast, removeAll` 618 | Remove element in collection 619 | 620 | ``` 621 | fun removeExample() { 622 | val listOne = mutableListOf(1, 2, 3, 3, 4, 5, 6) 623 | val listTwo = listOf(1, 2, 3) 624 | val listThree = listOf(6, 7) 625 | println(listOne.removeFirst()) //Prints 1 626 | println(listOne.removeLast()) //Prints 6 627 | println(listOne) // Prints [2,3,3,4,5] 628 | println(listOne.removeAll(listTwo)) //Prints True 629 | println(listOne) // Prints [4,5] 630 | println(listOne.removeAll(listThree)) //Prints False 631 | println(listOne) // Prints [4,5] 632 | } 633 | ``` 634 | 635 | Output: 636 | ``` 637 | 1 638 | 6 639 | [2, 3, 3, 4, 5] 640 | true 641 | [4, 5] 642 | false 643 | [4, 5] 644 | ``` 645 | 646 | ## `partition` 647 | Split array into two parts based on some condition 648 | 649 | ``` 650 | fun partitionExample() { 651 | val users = listOf( 652 | User(1, "Alan", true), 653 | User(2, "Bob", true), 654 | User(3, "Joe", false), 655 | User(4, "Jenny", false) 656 | ) 657 | 658 | val (webDevs, nonWebDevs) = users.partition { it.webDev } 659 | println(webDevs) // [User(id=1, name=Alan, webDev=true), User(id=2, name=Bob, webDev=true)] 660 | println(nonWebDevs) // [User(id=3, name=Joe, webDev=false), User(id=4, name=Jenny, webDev=false)] 661 | } 662 | ``` 663 | 664 | Output: 665 | ``` 666 | [User(id=1, name=Alan, webDev=true, mobileDev=false), User(id=2, name=Bob, webDev=true, mobileDev=false)] 667 | [User(id=3, name=Joe, webDev=false, mobileDev=false), User(id=4, name=Jenny, webDev=false, mobileDev=false)] 668 | ``` 669 | 670 | ## `sum()` 671 | Calculate sum of element in collection 672 | 673 | ``` 674 | fun sumExample() { 675 | val nums = listOf(10, 20, 30) 676 | println(nums.sum()) // 60 677 | 678 | val doubles = listOf(1.05, 2.05, 3.65) 679 | println(doubles.sum()) // 6.75 680 | 681 | val products = listOf( 682 | Product("A", 10, 6.90), 683 | Product("B", 20, 3.45), 684 | Product("C", 30, 1.05) 685 | ) 686 | 687 | val totalQuantity: Int = products.map { it.quantity }.sum() 688 | println(totalQuantity) //60 689 | } 690 | ``` 691 | 692 | Output: 693 | ``` 694 | 60 695 | 6.75 696 | 60 697 | ``` 698 | 699 | ## `sumBy` 700 | sum of specific field in List of Objects 701 | 702 | ``` 703 | fun sumByExample() { 704 | /*Kotlin sumBy() 705 | sum (and change value to Int) of all items in the normal List 706 | sum of specific Int field in List of Objects (no need map()) 707 | sum of specific Int field of all values in Map of Objects (no need map()) 708 | Why we don’t need map()? 709 | Look at protoype of sumBy() function: 710 | 711 | inline fun sumBy(selector: (T) -> Int): Int 712 | You can see that sumBy() receives a selector which indicates the field to be processed.*/ 713 | val nums = listOf(10, 20, 30) 714 | println(nums.sumBy { it }) // 60 715 | println(nums.sumBy { it * 2 }) // 120 716 | 717 | val doubles = listOf(1.05, 2.05, 3.65) 718 | println(doubles.sumBy { it.roundToInt() }) // 7 719 | 720 | val products = listOf( 721 | Product("A", 10, 6.90), 722 | Product("B", 20, 3.45), 723 | Product("C", 30, 1.05) 724 | ) 725 | 726 | val totalQuantity: Int = products.sumBy { it.quantity } 727 | println(totalQuantity) // 60 728 | 729 | val productsMap = mapOf( 730 | "a" to Product("A", 10, 6.90), 731 | "b" to Product("B", 20, 3.45), 732 | "c" to Product("C", 30, 1.05) 733 | ) 734 | 735 | val totalQuantity2: Int = productsMap.map { it.value }.sumBy { it.quantity } 736 | println(totalQuantity2) // 60 737 | } 738 | ``` 739 | 740 | Output: 741 | ``` 742 | 60 743 | 120 744 | 7 745 | 60 746 | 60 747 | ``` 748 | 749 | ## `maxOrNull, minOrNull` 750 | Find max or min element in Collection 751 | 752 | ``` 753 | fun maxMinExample() { 754 | val simpleList = listOf(1.99, 55.4, 20.0, 99.99, 23.0, 34.2, 88.0, 72.1, 61.2, 43.9) 755 | val largestElement = simpleList.maxOrNull() 756 | println(largestElement) //99.99 757 | val smallestElement = simpleList.minOrNull() 758 | println(smallestElement) //1.99 759 | } 760 | ``` 761 | 762 | Output: 763 | ``` 764 | 99.99 765 | 1.99 766 | ``` 767 | 768 | ## `maxByOrNull, minByOrNull` 769 | Find max or min element based on custom property 770 | 771 | ``` 772 | fun maxMinByExample() { 773 | val products = listOf( 774 | Product("A", 10, 6.90), 775 | Product("B", 20, 3.45), 776 | Product("C", 30, 1.05) 777 | ) 778 | val productWithHighestPrice = products.maxByOrNull { it -> it.price } 779 | println(productWithHighestPrice) 780 | 781 | val productWithLowestPrice = products.minByOrNull { it -> it.price } 782 | println(productWithLowestPrice) 783 | } 784 | ``` 785 | 786 | Output: 787 | ``` 788 | Product(name=A, quantity=10, price=6.9) 789 | Product(name=C, quantity=30, price=1.05) 790 | ``` 791 | 792 | ## `maxWithOrNull` 793 | Find first element having the largest value according to the provided comparator 794 | 795 | ``` 796 | fun maxWithExample() { 797 | //maxWith() returns the first element having the largest value according to the provided [comparator] 798 | val productList = listOf( 799 | Product("A", 10, 6.90), 800 | Product("B", 20, 3.45), 801 | Product("C", 30, 1.05), 802 | Product("D", 20, 9.05) 803 | ) 804 | val productWithHighestPrice = productList.maxWithOrNull(object : Comparator { 805 | override fun compare(o1: Any?, o2: Any?): Int { 806 | val obj1: Product? = o1 as? Product 807 | val obj2: Product? = o2 as? Product 808 | safeLet(obj1, obj2) { p1, p2 -> 809 | if (p1.price > p2.price) return 1 810 | if (p1.price == p2.price) return 0 811 | else return -1 812 | } 813 | return -1 814 | } 815 | }) 816 | 817 | println(productWithHighestPrice) 818 | } 819 | 820 | inline fun safeLet(p1: T1?, p2: T2?, block: (T1, T2) -> R?): R? { 821 | return if (p1 != null && p2 != null) block(p1, p2) else null 822 | } 823 | ``` 824 | 825 | Output: 826 | ``` 827 | Product(name=D, quantity=20, price=9.05) 828 | ``` 829 | 830 | ## `drop, dropLast, dropWhile, dropLastWhile` 831 | 832 | Drop elements from sequence. 833 | 834 | ``` 835 | fun dropExample() { 836 | val chars = ('a'..'z').toList() 837 | println(chars.drop(23)) // [x, y, z] 838 | println(chars.dropLast(23)) // [a, b, c] 839 | println(chars.dropWhile { it < 'x' }) // [x, y, z] 840 | println(chars.dropLastWhile { it > 'c' }) // [a, b, c] 841 | 842 | val numbers = (1..50).toList() 843 | println(numbers.drop(5).take(10).sortedDescending().toList()) //[15, 14, 13, 12, 11, 10, 9, 8, 7, 6] 844 | } 845 | ``` 846 | 847 | Output: 848 | ``` 849 | [x, y, z] 850 | [a, b, c] 851 | [x, y, z] 852 | [a, b, c] 853 | [15, 14, 13, 12, 11, 10, 9, 8, 7, 6] 854 | 855 | ``` --------------------------------------------------------------------------------