[{"data":1,"prerenderedAt":1134},["ShallowReactive",2],{"article-using-kotlin-sequences-to-abstract-pagination":3},{"id":4,"title":5,"body":6,"description":1122,"extension":1123,"meta":1124,"navigation":97,"path":1125,"published_at":1126,"seo":1127,"status":1128,"stem":1129,"subtitle":1128,"tags":1130,"timeToRead":285,"__hash__":1133},"articles\u002Fusing-kotlin-sequences-to-abstract-pagination.md","Using Kotlin Sequences to abstract pagination",{"type":7,"value":8,"toc":1120},"minimark",[9,13,171,174,356,363,368,374,377,380,525,675,678,681,685,706,717,925,1063,1077,1093,1097,1116],[10,11,12],"p",{},"Let's assume you need to process millions of records from some third party data source. This data source will usually provide a pagination mechanism that looks like this:",[14,15,20],"pre",{"className":16,"code":17,"language":18,"meta":19,"style":19},"language-kotlin shiki shiki-themes github-light","interface SomeThirdPartyRepository {\n    fun searchBy(someCriteria: String, pageSize: Int = 100): ResultPage\n    fun nextPage(cursor: Cursor): ResultPage\n\n    data class ResultPage(val results: List\u003CString>, val cursor: Cursor)\n    data class Cursor(val value: String)\n}\n","kotlin","",[21,22,23,40,74,92,99,141,165],"code",{"__ignoreMap":19},[24,25,28,32,36],"span",{"class":26,"line":27},"line",1,[24,29,31],{"class":30},"sD7c4","interface",[24,33,35],{"class":34},"s7eDp"," SomeThirdPartyRepository",[24,37,39],{"class":38},"sgsFI"," {\n",[24,41,43,46,49,52,55,58,61,64,68,71],{"class":26,"line":42},2,[24,44,45],{"class":30},"    fun",[24,47,48],{"class":34}," searchBy",[24,50,51],{"class":38},"(someCriteria: ",[24,53,54],{"class":34},"String",[24,56,57],{"class":38},", pageSize: ",[24,59,60],{"class":34},"Int",[24,62,63],{"class":30}," =",[24,65,67],{"class":66},"sYu0t"," 100",[24,69,70],{"class":38},"): ",[24,72,73],{"class":34},"ResultPage\n",[24,75,77,79,82,85,88,90],{"class":26,"line":76},3,[24,78,45],{"class":30},[24,80,81],{"class":34}," nextPage",[24,83,84],{"class":38},"(cursor: ",[24,86,87],{"class":34},"Cursor",[24,89,70],{"class":38},[24,91,73],{"class":34},[24,93,95],{"class":26,"line":94},4,[24,96,98],{"emptyLinePlaceholder":97},true,"\n",[24,100,102,105,108,111,114,117,120,123,126,128,131,133,136,138],{"class":26,"line":101},5,[24,103,104],{"class":30},"    data",[24,106,107],{"class":30}," class",[24,109,110],{"class":34}," ResultPage",[24,112,113],{"class":38},"(",[24,115,116],{"class":30},"val",[24,118,119],{"class":38}," results: ",[24,121,122],{"class":34},"List",[24,124,125],{"class":38},"\u003C",[24,127,54],{"class":34},[24,129,130],{"class":38},">, ",[24,132,116],{"class":30},[24,134,135],{"class":38}," cursor: ",[24,137,87],{"class":34},[24,139,140],{"class":38},")\n",[24,142,144,146,148,151,153,155,158,161,163],{"class":26,"line":143},6,[24,145,104],{"class":30},[24,147,107],{"class":30},[24,149,150],{"class":34}," Cursor",[24,152,113],{"class":38},[24,154,116],{"class":30},[24,156,157],{"class":30}," value",[24,159,160],{"class":38},": ",[24,162,54],{"class":34},[24,164,140],{"class":38},[24,166,168],{"class":26,"line":167},7,[24,169,170],{"class":38},"}\n",[10,172,173],{},"Your code to process the records currently looks like this:",[14,175,177],{"className":16,"code":176,"language":18,"meta":19,"style":19},"class InitialProcessor(\n    private val thirdPartyRepository: SomeThirdPartyRepository\n) : Processor {\n    override fun execute() {\n        var currentPage = thirdPartyRepository.searchBy(\"someCriteria\", pageSize = 100)\n        while (currentPage.results.isNotEmpty()) {\n            currentPage.results \u002F\u002F 100 items\n                .map { it.uppercase() }\n                .forEach { someSideEffect(it) }\n\n            currentPage = thirdPartyRepository.nextPage(currentPage.cursor)\n        }\n    }\n}\n",[21,178,179,190,204,214,228,260,274,283,301,318,323,339,345,351],{"__ignoreMap":19},[24,180,181,184,187],{"class":26,"line":27},[24,182,183],{"class":30},"class",[24,185,186],{"class":34}," InitialProcessor",[24,188,189],{"class":38},"(\n",[24,191,192,195,198,201],{"class":26,"line":42},[24,193,194],{"class":30},"    private",[24,196,197],{"class":30}," val",[24,199,200],{"class":38}," thirdPartyRepository: ",[24,202,203],{"class":34},"SomeThirdPartyRepository\n",[24,205,206,209,212],{"class":26,"line":76},[24,207,208],{"class":38},") : ",[24,210,211],{"class":34},"Processor",[24,213,39],{"class":38},[24,215,216,219,222,225],{"class":26,"line":94},[24,217,218],{"class":30},"    override",[24,220,221],{"class":30}," fun",[24,223,224],{"class":34}," execute",[24,226,227],{"class":38},"() {\n",[24,229,230,233,236,239,242,245,247,251,254,256,258],{"class":26,"line":101},[24,231,232],{"class":30},"        var",[24,234,235],{"class":38}," currentPage ",[24,237,238],{"class":30},"=",[24,240,241],{"class":38}," thirdPartyRepository.",[24,243,244],{"class":34},"searchBy",[24,246,113],{"class":38},[24,248,250],{"class":249},"sYBdl","\"someCriteria\"",[24,252,253],{"class":38},", pageSize ",[24,255,238],{"class":30},[24,257,67],{"class":66},[24,259,140],{"class":38},[24,261,262,265,268,271],{"class":26,"line":143},[24,263,264],{"class":30},"        while",[24,266,267],{"class":38}," (currentPage.results.",[24,269,270],{"class":34},"isNotEmpty",[24,272,273],{"class":38},"()) {\n",[24,275,276,279],{"class":26,"line":167},[24,277,278],{"class":38},"            currentPage.results ",[24,280,282],{"class":281},"sAwPA","\u002F\u002F 100 items\n",[24,284,286,289,292,295,298],{"class":26,"line":285},8,[24,287,288],{"class":38},"                .",[24,290,291],{"class":34},"map",[24,293,294],{"class":38}," { it.",[24,296,297],{"class":34},"uppercase",[24,299,300],{"class":38},"() }\n",[24,302,304,306,309,312,315],{"class":26,"line":303},9,[24,305,288],{"class":38},[24,307,308],{"class":34},"forEach",[24,310,311],{"class":38}," { ",[24,313,314],{"class":34},"someSideEffect",[24,316,317],{"class":38},"(it) }\n",[24,319,321],{"class":26,"line":320},10,[24,322,98],{"emptyLinePlaceholder":97},[24,324,326,329,331,333,336],{"class":26,"line":325},11,[24,327,328],{"class":38},"            currentPage ",[24,330,238],{"class":30},[24,332,241],{"class":38},[24,334,335],{"class":34},"nextPage",[24,337,338],{"class":38},"(currentPage.cursor)\n",[24,340,342],{"class":26,"line":341},12,[24,343,344],{"class":38},"        }\n",[24,346,348],{"class":26,"line":347},13,[24,349,350],{"class":38},"    }\n",[24,352,354],{"class":26,"line":353},14,[24,355,170],{"class":38},[10,357,358,359,362],{},"This code works, but it doesn’t feel right. You are concerned that your domain logic is mixed with the pagination logic. It is also not reusable, your codebase will be littered with references to ",[21,360,361],{},"SomeThirdPartyRepository",". You can do better.",[364,365,367],"h1",{"id":366},"first-refactoring","First refactoring",[10,369,370,371,373],{},"You decide to create your own wrapper around ",[21,372,361],{},".",[10,375,376],{},"You can then reuse this wrapper across your codebase. Any changes to the logic for fetching data will happen only in this wrapper. You also get the ability to test the pagination logic in isolation for free.",[10,378,379],{},"The universe is in balance again 🧘🏽‍♀️. Good job!",[14,381,383],{"className":16,"code":382,"language":18,"meta":19,"style":19},"class SimpleSearchRepository(\n    private val thirdPartyRepository: SomeThirdPartyRepository\n) {\n    fun search(someCriteria: String): List\u003CString> {\n        val mutableList = mutableListOf\u003CString>()\n        var currentPage = thirdPartyRepository.searchBy(someCriteria, pageSize = 100)\n        while (currentPage.results.isNotEmpty()) {\n            mutableList.addAll(currentPage.results)\n            currentPage = thirdPartyRepository.nextPage(currentPage.cursor)\n        }\n        return mutableList\n    }\n}\n",[21,384,385,394,404,409,431,451,472,482,493,505,509,517,521],{"__ignoreMap":19},[24,386,387,389,392],{"class":26,"line":27},[24,388,183],{"class":30},[24,390,391],{"class":34}," SimpleSearchRepository",[24,393,189],{"class":38},[24,395,396,398,400,402],{"class":26,"line":42},[24,397,194],{"class":30},[24,399,197],{"class":30},[24,401,200],{"class":38},[24,403,203],{"class":34},[24,405,406],{"class":26,"line":76},[24,407,408],{"class":38},") {\n",[24,410,411,413,416,418,420,422,424,426,428],{"class":26,"line":94},[24,412,45],{"class":30},[24,414,415],{"class":34}," search",[24,417,51],{"class":38},[24,419,54],{"class":34},[24,421,70],{"class":38},[24,423,122],{"class":34},[24,425,125],{"class":38},[24,427,54],{"class":34},[24,429,430],{"class":38},"> {\n",[24,432,433,436,439,441,444,446,448],{"class":26,"line":101},[24,434,435],{"class":30},"        val",[24,437,438],{"class":38}," mutableList ",[24,440,238],{"class":30},[24,442,443],{"class":34}," mutableListOf",[24,445,125],{"class":38},[24,447,54],{"class":34},[24,449,450],{"class":38},">()\n",[24,452,453,455,457,459,461,463,466,468,470],{"class":26,"line":143},[24,454,232],{"class":30},[24,456,235],{"class":38},[24,458,238],{"class":30},[24,460,241],{"class":38},[24,462,244],{"class":34},[24,464,465],{"class":38},"(someCriteria, pageSize ",[24,467,238],{"class":30},[24,469,67],{"class":66},[24,471,140],{"class":38},[24,473,474,476,478,480],{"class":26,"line":167},[24,475,264],{"class":30},[24,477,267],{"class":38},[24,479,270],{"class":34},[24,481,273],{"class":38},[24,483,484,487,490],{"class":26,"line":285},[24,485,486],{"class":38},"            mutableList.",[24,488,489],{"class":34},"addAll",[24,491,492],{"class":38},"(currentPage.results)\n",[24,494,495,497,499,501,503],{"class":26,"line":303},[24,496,328],{"class":38},[24,498,238],{"class":30},[24,500,241],{"class":38},[24,502,335],{"class":34},[24,504,338],{"class":38},[24,506,507],{"class":26,"line":320},[24,508,344],{"class":38},[24,510,511,514],{"class":26,"line":325},[24,512,513],{"class":30},"        return",[24,515,516],{"class":38}," mutableList\n",[24,518,519],{"class":26,"line":341},[24,520,350],{"class":38},[24,522,523],{"class":26,"line":347},[24,524,170],{"class":38},[14,526,528],{"className":16,"code":527,"language":18,"meta":19,"style":19},"class SimpleProcessor(\n    private val simpleSearchRepository: SimpleSearchRepository\n) : Processor {\n    override fun execute() {\n        val items = simpleSearchRepository.search(\"someCriteria\")\n        processItems(items)\n    }\n\n    private fun processItems(items: Collection\u003CString>): Unit =\n        items \u002F\u002F contains millions of records\n            .map { it.uppercase() } \u002F\u002F creates an intermediary collection of same size\n            .forEach { someSideEffect(it) }\n}\n",[21,529,530,539,551,559,569,590,598,602,606,634,642,659,671],{"__ignoreMap":19},[24,531,532,534,537],{"class":26,"line":27},[24,533,183],{"class":30},[24,535,536],{"class":34}," SimpleProcessor",[24,538,189],{"class":38},[24,540,541,543,545,548],{"class":26,"line":42},[24,542,194],{"class":30},[24,544,197],{"class":30},[24,546,547],{"class":38}," simpleSearchRepository: ",[24,549,550],{"class":34},"SimpleSearchRepository\n",[24,552,553,555,557],{"class":26,"line":76},[24,554,208],{"class":38},[24,556,211],{"class":34},[24,558,39],{"class":38},[24,560,561,563,565,567],{"class":26,"line":94},[24,562,218],{"class":30},[24,564,221],{"class":30},[24,566,224],{"class":34},[24,568,227],{"class":38},[24,570,571,573,576,578,581,584,586,588],{"class":26,"line":101},[24,572,435],{"class":30},[24,574,575],{"class":38}," items ",[24,577,238],{"class":30},[24,579,580],{"class":38}," simpleSearchRepository.",[24,582,583],{"class":34},"search",[24,585,113],{"class":38},[24,587,250],{"class":249},[24,589,140],{"class":38},[24,591,592,595],{"class":26,"line":143},[24,593,594],{"class":34},"        processItems",[24,596,597],{"class":38},"(items)\n",[24,599,600],{"class":26,"line":167},[24,601,350],{"class":38},[24,603,604],{"class":26,"line":285},[24,605,98],{"emptyLinePlaceholder":97},[24,607,608,610,612,615,618,621,623,625,628,631],{"class":26,"line":303},[24,609,194],{"class":30},[24,611,221],{"class":30},[24,613,614],{"class":34}," processItems",[24,616,617],{"class":38},"(items: ",[24,619,620],{"class":34},"Collection",[24,622,125],{"class":38},[24,624,54],{"class":34},[24,626,627],{"class":38},">): ",[24,629,630],{"class":34},"Unit",[24,632,633],{"class":30}," =\n",[24,635,636,639],{"class":26,"line":320},[24,637,638],{"class":38},"        items ",[24,640,641],{"class":281},"\u002F\u002F contains millions of records\n",[24,643,644,647,649,651,653,656],{"class":26,"line":325},[24,645,646],{"class":38},"            .",[24,648,291],{"class":34},[24,650,294],{"class":38},[24,652,297],{"class":34},[24,654,655],{"class":38},"() } ",[24,657,658],{"class":281},"\u002F\u002F creates an intermediary collection of same size\n",[24,660,661,663,665,667,669],{"class":26,"line":341},[24,662,646],{"class":38},[24,664,308],{"class":34},[24,666,311],{"class":38},[24,668,314],{"class":34},[24,670,317],{"class":38},[24,672,673],{"class":26,"line":347},[24,674,170],{"class":38},[10,676,677],{},"Your application suddenly starts running out of memory 🧨💥, and you realize the shortcomings of this implementation.",[10,679,680],{},"The issue here is that the repository loads millions🤯 of records in memory. This is one of the problems the third-party repository was trying to avoid by providing a pagination mechanism.",[364,682,684],{"id":683},"second-refactoring","Second refactoring",[10,686,687,688,695,696,700,701,705],{},"Fortunately, you learned about ",[689,690,694],"a",{"href":691,"rel":692},"https:\u002F\u002Fkotlinlang.org\u002Fdocs\u002Fsequences.html",[693],"nofollow","Kotlin Sequences"," just in time for this incident.\nSequences are the ",[697,698,699],"em",{},"lazy"," ",[702,703,704],"del",{},"person’s"," version of collections, the Kotlin equivalent to Java Streams.",[10,707,708,709,712,713,716],{},"Instead of returning a ",[21,710,711],{},"List\u003CString>"," containing millions of records, your repository now returns a ",[21,714,715],{},"Sequence\u003CString>"," that provides one item at a time, on-demand.",[14,718,720],{"className":16,"code":719,"language":18,"meta":19,"style":19},"class SophisticatedSearchRepository( \u002F\u002F 🧐\n    private val thirdPartyRepository: SomeThirdPartyRepository\n) {\n    fun search(someCriteria: String): Sequence\u003CString> =\n        pageSequence(someCriteria)\n            .flatMap { it.results } \n            \u002F\u002F flatMap converts Seq[Page(a,b),Page(c,d)] -> Seq[a,b,c,d]\n\n    private fun pageSequence(\n      someCriteria: String\n    ): Sequence\u003CSomeThirdPartyRepository.ResultPage> {\n        val firstPage = thirdPartyRepository.searchBy(someCriteria, pageSize = 100)\n        return generateSequence(firstPage) { previousPage ->\n            if (previousPage.results.isNotEmpty()) {\n                thirdPartyRepository.nextPage(previousPage.cursor)\n            } else null \u002F\u002F returning null closes the sequence\n        }\n    }\n}\n",[21,721,722,735,745,749,774,782,792,797,801,812,820,838,859,872,884,895,910,915,920],{"__ignoreMap":19},[24,723,724,726,729,732],{"class":26,"line":27},[24,725,183],{"class":30},[24,727,728],{"class":34}," SophisticatedSearchRepository",[24,730,731],{"class":38},"( ",[24,733,734],{"class":281},"\u002F\u002F 🧐\n",[24,736,737,739,741,743],{"class":26,"line":42},[24,738,194],{"class":30},[24,740,197],{"class":30},[24,742,200],{"class":38},[24,744,203],{"class":34},[24,746,747],{"class":26,"line":76},[24,748,408],{"class":38},[24,750,751,753,755,757,759,761,764,766,768,771],{"class":26,"line":94},[24,752,45],{"class":30},[24,754,415],{"class":34},[24,756,51],{"class":38},[24,758,54],{"class":34},[24,760,70],{"class":38},[24,762,763],{"class":34},"Sequence",[24,765,125],{"class":38},[24,767,54],{"class":34},[24,769,770],{"class":38},"> ",[24,772,773],{"class":30},"=\n",[24,775,776,779],{"class":26,"line":101},[24,777,778],{"class":34},"        pageSequence",[24,780,781],{"class":38},"(someCriteria)\n",[24,783,784,786,789],{"class":26,"line":143},[24,785,646],{"class":38},[24,787,788],{"class":34},"flatMap",[24,790,791],{"class":38}," { it.results } \n",[24,793,794],{"class":26,"line":167},[24,795,796],{"class":281},"            \u002F\u002F flatMap converts Seq[Page(a,b),Page(c,d)] -> Seq[a,b,c,d]\n",[24,798,799],{"class":26,"line":285},[24,800,98],{"emptyLinePlaceholder":97},[24,802,803,805,807,810],{"class":26,"line":303},[24,804,194],{"class":30},[24,806,221],{"class":30},[24,808,809],{"class":34}," pageSequence",[24,811,189],{"class":38},[24,813,814,817],{"class":26,"line":320},[24,815,816],{"class":38},"      someCriteria: ",[24,818,819],{"class":34},"String\n",[24,821,822,825,827,829,831,833,836],{"class":26,"line":325},[24,823,824],{"class":38},"    ): ",[24,826,763],{"class":34},[24,828,125],{"class":38},[24,830,361],{"class":34},[24,832,373],{"class":38},[24,834,835],{"class":34},"ResultPage",[24,837,430],{"class":38},[24,839,840,842,845,847,849,851,853,855,857],{"class":26,"line":341},[24,841,435],{"class":30},[24,843,844],{"class":38}," firstPage ",[24,846,238],{"class":30},[24,848,241],{"class":38},[24,850,244],{"class":34},[24,852,465],{"class":38},[24,854,238],{"class":30},[24,856,67],{"class":66},[24,858,140],{"class":38},[24,860,861,863,866,869],{"class":26,"line":347},[24,862,513],{"class":30},[24,864,865],{"class":34}," generateSequence",[24,867,868],{"class":38},"(firstPage) { previousPage ",[24,870,871],{"class":30},"->\n",[24,873,874,877,880,882],{"class":26,"line":353},[24,875,876],{"class":30},"            if",[24,878,879],{"class":38}," (previousPage.results.",[24,881,270],{"class":34},[24,883,273],{"class":38},[24,885,887,890,892],{"class":26,"line":886},15,[24,888,889],{"class":38},"                thirdPartyRepository.",[24,891,335],{"class":34},[24,893,894],{"class":38},"(previousPage.cursor)\n",[24,896,898,901,904,907],{"class":26,"line":897},16,[24,899,900],{"class":38},"            } ",[24,902,903],{"class":30},"else",[24,905,906],{"class":66}," null",[24,908,909],{"class":281}," \u002F\u002F returning null closes the sequence\n",[24,911,913],{"class":26,"line":912},17,[24,914,344],{"class":38},[24,916,918],{"class":26,"line":917},18,[24,919,350],{"class":38},[24,921,923],{"class":26,"line":922},19,[24,924,170],{"class":38},[14,926,928],{"className":16,"code":927,"language":18,"meta":19,"style":19},"class SophisticatedProcessor( \u002F\u002F sophisticated only by association 😁\n    private val sophisticatedSearchRepository: SophisticatedSearchRepository\n) : Processor {\n    override fun execute() {\n        val items = sophisticatedSearchRepository.search(\"someCriteria\")\n        processItems(items)\n    }\n\n    private fun processItems(items: Sequence\u003CString>): Unit =\n        items\n            .map { it.uppercase() } \u002F\u002F transforms one item at a time, NO intermediary collection created\n            .forEach { someSideEffect(it) }\n}\n",[21,929,930,942,954,962,972,991,997,1001,1005,1027,1032,1047,1059],{"__ignoreMap":19},[24,931,932,934,937,939],{"class":26,"line":27},[24,933,183],{"class":30},[24,935,936],{"class":34}," SophisticatedProcessor",[24,938,731],{"class":38},[24,940,941],{"class":281},"\u002F\u002F sophisticated only by association 😁\n",[24,943,944,946,948,951],{"class":26,"line":42},[24,945,194],{"class":30},[24,947,197],{"class":30},[24,949,950],{"class":38}," sophisticatedSearchRepository: ",[24,952,953],{"class":34},"SophisticatedSearchRepository\n",[24,955,956,958,960],{"class":26,"line":76},[24,957,208],{"class":38},[24,959,211],{"class":34},[24,961,39],{"class":38},[24,963,964,966,968,970],{"class":26,"line":94},[24,965,218],{"class":30},[24,967,221],{"class":30},[24,969,224],{"class":34},[24,971,227],{"class":38},[24,973,974,976,978,980,983,985,987,989],{"class":26,"line":101},[24,975,435],{"class":30},[24,977,575],{"class":38},[24,979,238],{"class":30},[24,981,982],{"class":38}," sophisticatedSearchRepository.",[24,984,583],{"class":34},[24,986,113],{"class":38},[24,988,250],{"class":249},[24,990,140],{"class":38},[24,992,993,995],{"class":26,"line":143},[24,994,594],{"class":34},[24,996,597],{"class":38},[24,998,999],{"class":26,"line":167},[24,1000,350],{"class":38},[24,1002,1003],{"class":26,"line":285},[24,1004,98],{"emptyLinePlaceholder":97},[24,1006,1007,1009,1011,1013,1015,1017,1019,1021,1023,1025],{"class":26,"line":303},[24,1008,194],{"class":30},[24,1010,221],{"class":30},[24,1012,614],{"class":34},[24,1014,617],{"class":38},[24,1016,763],{"class":34},[24,1018,125],{"class":38},[24,1020,54],{"class":34},[24,1022,627],{"class":38},[24,1024,630],{"class":34},[24,1026,633],{"class":30},[24,1028,1029],{"class":26,"line":320},[24,1030,1031],{"class":38},"        items\n",[24,1033,1034,1036,1038,1040,1042,1044],{"class":26,"line":325},[24,1035,646],{"class":38},[24,1037,291],{"class":34},[24,1039,294],{"class":38},[24,1041,297],{"class":34},[24,1043,655],{"class":38},[24,1045,1046],{"class":281},"\u002F\u002F transforms one item at a time, NO intermediary collection created\n",[24,1048,1049,1051,1053,1055,1057],{"class":26,"line":341},[24,1050,646],{"class":38},[24,1052,308],{"class":34},[24,1054,311],{"class":38},[24,1056,314],{"class":34},[24,1058,317],{"class":38},[24,1060,1061],{"class":26,"line":347},[24,1062,170],{"class":38},[10,1064,1065,1066,1069,1070,1073,1074,373],{},"The code for ",[21,1067,1068],{},"processItems()","  does not change because ",[21,1071,1072],{},"Sequence\u003CT>"," has a similar API to ",[21,1075,1076],{},"Collection\u003CT>",[10,1078,1079,1080,1084,1085,1088,1089,1092],{},"⚠️ The consumer of the sequence receives ",[1081,1082,1083],"strong",{},"one"," item at a time, but our repository still loads ",[21,1086,1087],{},"N=pageSize"," items in memory.\nThe appropriate value for ",[21,1090,1091],{},"pageSize"," will depend on the size of an item and the cost of fetching a page. A large page size might consume more memory, but a small one will cause a lot of potentially expensive round trips.",[364,1094,1096],{"id":1095},"extra-resources","Extra resources",[1098,1099,1100,1108],"ul",{},[1101,1102,1103,1104],"li",{},"Sequences - ",[689,1105,1107],{"href":691,"rel":1106},[693],"Kotlin official documentation",[1101,1109,1110,1111],{},"Collections and sequences ",[689,1112,1115],{"href":1113,"rel":1114},"https:\u002F\u002Fyoutu.be\u002F77hfjIYwouw",[693],"Youtube Video",[1117,1118,1119],"style",{},"html pre.shiki code .sD7c4, html code.shiki .sD7c4{--shiki-default:#D73A49}html pre.shiki code .s7eDp, html code.shiki .s7eDp{--shiki-default:#6F42C1}html pre.shiki code .sgsFI, html code.shiki .sgsFI{--shiki-default:#24292E}html pre.shiki code .sYu0t, html code.shiki .sYu0t{--shiki-default:#005CC5}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .sYBdl, html code.shiki .sYBdl{--shiki-default:#032F62}html pre.shiki code .sAwPA, html code.shiki .sAwPA{--shiki-default:#6A737D}",{"title":19,"searchDepth":42,"depth":42,"links":1121},[],"Let's assume you need to process millions of records from some third party data source. This data source will usually provide a pagination mechanism...","md",{},"\u002Fusing-kotlin-sequences-to-abstract-pagination","2022-04-10",{"title":5,"description":1122},null,"using-kotlin-sequences-to-abstract-pagination",[1131,1132],"Software Engineering","Kotlin","7U6fJ1nWdgPKoVzXls4TltH8q-hWIM4vYZ6gYUh_n98",1792339960447]