[{"data":1,"prerenderedAt":2011},["ShallowReactive",2],{"blog-\u002Fblog\u002Fjava-stream-api-guide":3},{"id":4,"title":5,"body":6,"description":1997,"difficulty":1998,"extension":1999,"framework":2000,"frameworkSlug":82,"meta":2001,"navigation":181,"order":97,"path":2002,"qaPath":2003,"seo":2004,"stem":2005,"subtopic":2006,"topic":2007,"topicSlug":2008,"updated":2009,"__hash__":2010},"blog\u002Fblog\u002Fjava-stream-api-guide.md","Java Stream API — Pipelines, Laziness & the Core Operations Explained",{"type":7,"value":8,"toc":1983},"minimark",[9,14,39,42,46,77,266,285,289,300,483,503,507,514,626,698,705,709,728,823,865,869,903,1056,1086,1090,1096,1238,1259,1263,1273,1375,1403,1407,1410,1562,1594,1598,1621,1753,1782,1786,1801,1820,1901,1916,1920,1979],[10,11,13],"h2",{"id":12},"thinking-in-streams-not-loops","Thinking in streams, not loops",[15,16,17,18,22,23,30,31,34,35,38],"p",{},"The Stream API (Java 8) lets you describe a computation over a sequence of data\n",[19,20,21],"strong",{},"declaratively"," — what you want, not the loop that produces it. The mental shift that\ntrips people up is this: a ",[19,24,25,29],{},[26,27,28],"code",{},"Stream"," is not a data structure",". It holds no elements. It\nis a ",[19,32,33],{},"pipeline"," that pulls elements from a ",[19,36,37],{},"source",", runs them through a chain of\noperations, and produces a result. Once you internalise that, the rest of the API — the\nlaziness, the single-use rule, the parallel caveats — stops feeling arbitrary and starts\nfeeling inevitable.",[15,40,41],{},"This guide walks the pipeline end to end: where streams come from, how lazy and eager\noperations divide the work, and the handful of operations you reach for every day.",[10,43,45],{"id":44},"stream-vs-collection","Stream vs collection",[15,47,48,49,52,53,57,58,61,62,65,66,52,69,72,73,76],{},"A ",[19,50,51],{},"collection"," is about ",[54,55,56],"em",{},"storage",": it sits in memory and you iterate it ",[19,59,60],{},"externally","\n(you write the ",[26,63,64],{},"for"," loop, you control the cursor). A ",[19,67,68],{},"stream",[54,70,71],{},"processing",": it\nstores nothing, pulls from its source on demand, and iterates ",[19,74,75],{},"internally"," (the stream\ndrives the loop, you just supply the behaviour).",[78,79,84],"pre",{"className":80,"code":81,"language":82,"meta":83,"style":83},"language-java shiki shiki-themes github-light github-dark","\u002F\u002F External iteration — you manage the loop\nList\u003CString> out = new ArrayList\u003C>();\nfor (String s : names) {\n    if (s.length() > 4) out.add(s.toUpperCase());\n}\n\n\u002F\u002F Internal iteration — the stream manages the loop\nList\u003CString> out2 = names.stream()\n    .filter(s -> s.length() > 4)\n    .map(String::toUpperCase)\n    .toList();\n","java","",[26,85,86,95,118,132,170,176,183,189,209,238,255],{"__ignoreMap":83},[87,88,91],"span",{"class":89,"line":90},"line",1,[87,92,94],{"class":93},"sJ8bj","\u002F\u002F External iteration — you manage the loop\n",[87,96,98,102,106,109,112,115],{"class":89,"line":97},2,[87,99,101],{"class":100},"sVt8B","List\u003C",[87,103,105],{"class":104},"szBVR","String",[87,107,108],{"class":100},"> out ",[87,110,111],{"class":104},"=",[87,113,114],{"class":104}," new",[87,116,117],{"class":100}," ArrayList\u003C>();\n",[87,119,121,123,126,129],{"class":89,"line":120},3,[87,122,64],{"class":104},[87,124,125],{"class":100}," (String s ",[87,127,128],{"class":104},":",[87,130,131],{"class":100}," names) {\n",[87,133,135,138,141,145,148,151,155,158,161,164,167],{"class":89,"line":134},4,[87,136,137],{"class":104},"    if",[87,139,140],{"class":100}," (s.",[87,142,144],{"class":143},"sScJk","length",[87,146,147],{"class":100},"() ",[87,149,150],{"class":104},">",[87,152,154],{"class":153},"sj4cs"," 4",[87,156,157],{"class":100},") out.",[87,159,160],{"class":143},"add",[87,162,163],{"class":100},"(s.",[87,165,166],{"class":143},"toUpperCase",[87,168,169],{"class":100},"());\n",[87,171,173],{"class":89,"line":172},5,[87,174,175],{"class":100},"}\n",[87,177,179],{"class":89,"line":178},6,[87,180,182],{"emptyLinePlaceholder":181},true,"\n",[87,184,186],{"class":89,"line":185},7,[87,187,188],{"class":93},"\u002F\u002F Internal iteration — the stream manages the loop\n",[87,190,192,194,196,199,201,204,206],{"class":89,"line":191},8,[87,193,101],{"class":100},[87,195,105],{"class":104},[87,197,198],{"class":100},"> out2 ",[87,200,111],{"class":104},[87,202,203],{"class":100}," names.",[87,205,68],{"class":143},[87,207,208],{"class":100},"()\n",[87,210,212,215,218,221,224,227,229,231,233,235],{"class":89,"line":211},9,[87,213,214],{"class":100},"    .",[87,216,217],{"class":143},"filter",[87,219,220],{"class":100},"(s ",[87,222,223],{"class":104},"->",[87,225,226],{"class":100}," s.",[87,228,144],{"class":143},[87,230,147],{"class":100},[87,232,150],{"class":104},[87,234,154],{"class":153},[87,236,237],{"class":100},")\n",[87,239,241,243,246,249,252],{"class":89,"line":240},10,[87,242,214],{"class":100},[87,244,245],{"class":143},"map",[87,247,248],{"class":100},"(String",[87,250,251],{"class":104},"::",[87,253,254],{"class":100},"toUpperCase)\n",[87,256,258,260,263],{"class":89,"line":257},11,[87,259,214],{"class":100},[87,261,262],{"class":143},"toList",[87,264,265],{"class":100},"();\n",[15,267,268,269,272,273,276,277,280,281,284],{},"Two consequences fall out of \"stores nothing\": a stream is ",[19,270,271],{},"single-use"," (consumed once),\nand it ",[19,274,275],{},"never mutates its source",". Use a collection to ",[54,278,279],{},"hold"," data and a stream to\n",[54,282,283],{},"transform"," it.",[10,286,288],{"id":287},"sources-where-a-stream-begins","Sources: where a stream begins",[15,290,291,292,295,296,299],{},"Every pipeline starts at a source. The most common is ",[26,293,294],{},"Collection.stream()",", but streams\ncan be built from explicit values, arrays, files, character data, and even ",[19,297,298],{},"infinite","\ngenerators.",[78,301,303],{"className":80,"code":302,"language":82,"meta":83,"style":83},"list.stream();                       \u002F\u002F any Collection\nStream.of(\"a\", \"b\", \"c\");            \u002F\u002F explicit values\nArrays.stream(new int[]{1, 2, 3});   \u002F\u002F an array\nIntStream.rangeClosed(1, 5);         \u002F\u002F 1,2,3,4,5\nStream.iterate(1, n -> n * 2);       \u002F\u002F INFINITE: 1,2,4,8,...\nStream.generate(Math::random);       \u002F\u002F INFINITE: repeated supplier\nFiles.lines(Path.of(\"data.txt\"));    \u002F\u002F lazy lines, backed by an open file\n",[26,304,305,318,350,387,410,441,459],{"__ignoreMap":83},[87,306,307,310,312,315],{"class":89,"line":90},[87,308,309],{"class":100},"list.",[87,311,68],{"class":143},[87,313,314],{"class":100},"();                       ",[87,316,317],{"class":93},"\u002F\u002F any Collection\n",[87,319,320,323,326,329,333,336,339,341,344,347],{"class":89,"line":97},[87,321,322],{"class":100},"Stream.",[87,324,325],{"class":143},"of",[87,327,328],{"class":100},"(",[87,330,332],{"class":331},"sZZnC","\"a\"",[87,334,335],{"class":100},", ",[87,337,338],{"class":331},"\"b\"",[87,340,335],{"class":100},[87,342,343],{"class":331},"\"c\"",[87,345,346],{"class":100},");            ",[87,348,349],{"class":93},"\u002F\u002F explicit values\n",[87,351,352,355,357,359,362,365,368,371,373,376,378,381,384],{"class":89,"line":120},[87,353,354],{"class":100},"Arrays.",[87,356,68],{"class":143},[87,358,328],{"class":100},[87,360,361],{"class":104},"new",[87,363,364],{"class":104}," int",[87,366,367],{"class":100},"[]{",[87,369,370],{"class":153},"1",[87,372,335],{"class":100},[87,374,375],{"class":153},"2",[87,377,335],{"class":100},[87,379,380],{"class":153},"3",[87,382,383],{"class":100},"});   ",[87,385,386],{"class":93},"\u002F\u002F an array\n",[87,388,389,392,395,397,399,401,404,407],{"class":89,"line":134},[87,390,391],{"class":100},"IntStream.",[87,393,394],{"class":143},"rangeClosed",[87,396,328],{"class":100},[87,398,370],{"class":153},[87,400,335],{"class":100},[87,402,403],{"class":153},"5",[87,405,406],{"class":100},");         ",[87,408,409],{"class":93},"\u002F\u002F 1,2,3,4,5\n",[87,411,412,414,417,419,421,424,426,429,432,435,438],{"class":89,"line":172},[87,413,322],{"class":100},[87,415,416],{"class":143},"iterate",[87,418,328],{"class":100},[87,420,370],{"class":153},[87,422,423],{"class":100},", n ",[87,425,223],{"class":104},[87,427,428],{"class":100}," n ",[87,430,431],{"class":104},"*",[87,433,434],{"class":153}," 2",[87,436,437],{"class":100},");       ",[87,439,440],{"class":93},"\u002F\u002F INFINITE: 1,2,4,8,...\n",[87,442,443,445,448,451,453,456],{"class":89,"line":178},[87,444,322],{"class":100},[87,446,447],{"class":143},"generate",[87,449,450],{"class":100},"(Math",[87,452,251],{"class":104},[87,454,455],{"class":100},"random);       ",[87,457,458],{"class":93},"\u002F\u002F INFINITE: repeated supplier\n",[87,460,461,464,467,470,472,474,477,480],{"class":89,"line":185},[87,462,463],{"class":100},"Files.",[87,465,466],{"class":143},"lines",[87,468,469],{"class":100},"(Path.",[87,471,325],{"class":143},[87,473,328],{"class":100},[87,475,476],{"class":331},"\"data.txt\"",[87,478,479],{"class":100},"));    ",[87,481,482],{"class":93},"\u002F\u002F lazy lines, backed by an open file\n",[15,484,485,486,335,488,490,491,494,495,498,499,502],{},"The infinite sources (",[26,487,416],{},[26,489,447],{},") are only usable because of laziness — you\n",[19,492,493],{},"must"," pair them with a short-circuiting op like ",[26,496,497],{},"limit(n)"," or they never terminate.\n",[26,500,501],{},"Files.lines"," holds an OS file handle, so wrap it in try-with-resources to close it.",[10,504,506],{"id":505},"the-pipeline-intermediate-vs-terminal","The pipeline: intermediate vs terminal",[15,508,509,510,513],{},"Every pipeline has exactly one shape: ",[19,511,512],{},"zero or more intermediate operations followed by\none terminal operation",". The distinction is the single most important idea in the API.",[515,516,517,532],"table",{},[518,519,520],"thead",{},[521,522,523,526,529],"tr",{},[524,525],"th",{},[524,527,528],{},"Intermediate",[524,530,531],{},"Terminal",[533,534,535,549,566,577],"tbody",{},[521,536,537,541,546],{},[538,539,540],"td",{},"Returns",[538,542,543,544],{},"another ",[26,545,28],{},[538,547,548],{},"a value \u002F side-effect (not a stream)",[521,550,551,554,560],{},[538,552,553],{},"Evaluation",[538,555,556,559],{},[19,557,558],{},"lazy"," — records, does nothing",[538,561,562,565],{},[19,563,564],{},"eager"," — triggers the whole run",[521,567,568,571,574],{},[538,569,570],{},"Count per pipeline",[538,572,573],{},"any number",[538,575,576],{},"exactly one",[521,578,579,582,603],{},[538,580,581],{},"Examples",[538,583,584,335,586,335,588,335,591,335,594,335,597,335,600],{},[26,585,217],{},[26,587,245],{},[26,589,590],{},"flatMap",[26,592,593],{},"sorted",[26,595,596],{},"distinct",[26,598,599],{},"limit",[26,601,602],{},"peek",[538,604,605,335,608,335,611,335,614,335,617,335,620,335,623],{},[26,606,607],{},"collect",[26,609,610],{},"forEach",[26,612,613],{},"reduce",[26,615,616],{},"count",[26,618,619],{},"findFirst",[26,621,622],{},"anyMatch",[26,624,625],{},"toArray",[78,627,629],{"className":80,"code":628,"language":82,"meta":83,"style":83},"list.stream()\n    .filter(s -> s.length() > 3)   \u002F\u002F intermediate — lazy, returns a Stream\n    .map(String::toUpperCase)      \u002F\u002F intermediate — lazy, returns a Stream\n    .collect(Collectors.toList()); \u002F\u002F terminal — NOW the pipeline runs\n",[26,630,631,639,666,681],{"__ignoreMap":83},[87,632,633,635,637],{"class":89,"line":90},[87,634,309],{"class":100},[87,636,68],{"class":143},[87,638,208],{"class":100},[87,640,641,643,645,647,649,651,653,655,657,660,663],{"class":89,"line":97},[87,642,214],{"class":100},[87,644,217],{"class":143},[87,646,220],{"class":100},[87,648,223],{"class":104},[87,650,226],{"class":100},[87,652,144],{"class":143},[87,654,147],{"class":100},[87,656,150],{"class":104},[87,658,659],{"class":153}," 3",[87,661,662],{"class":100},")   ",[87,664,665],{"class":93},"\u002F\u002F intermediate — lazy, returns a Stream\n",[87,667,668,670,672,674,676,679],{"class":89,"line":120},[87,669,214],{"class":100},[87,671,245],{"class":143},[87,673,248],{"class":100},[87,675,251],{"class":104},[87,677,678],{"class":100},"toUpperCase)      ",[87,680,665],{"class":93},[87,682,683,685,687,690,692,695],{"class":89,"line":134},[87,684,214],{"class":100},[87,686,607],{"class":143},[87,688,689],{"class":100},"(Collectors.",[87,691,262],{"class":143},[87,693,694],{"class":100},"()); ",[87,696,697],{"class":93},"\u002F\u002F terminal — NOW the pipeline runs\n",[15,699,700,701,704],{},"Build a pipeline without a terminal operation and ",[19,702,703],{},"nothing executes",". The intermediate\nsteps are merely a recorded recipe waiting for a terminal op to ask for results.",[10,706,708],{"id":707},"laziness-and-short-circuiting","Laziness and short-circuiting",[15,710,711,712,715,716,719,720,723,724,727],{},"Because intermediate ops are lazy, the runtime can do two clever things. First, ",[19,713,714],{},"fusion",":\ninstead of materialising an intermediate collection after each stage, elements flow\n",[19,717,718],{},"vertically"," — one element passes through ",[54,721,722],{},"all"," stages before the next one starts, in a\nsingle pass. Second, ",[19,725,726],{},"short-circuiting",": the pipeline can stop the moment the answer is\nknown, without touching every element. That is what makes infinite sources tractable.",[78,729,731],{"className":80,"code":730,"language":82,"meta":83,"style":83},"int firstMultipleOf7 = Stream.iterate(1, n -> n + 1)  \u002F\u002F infinite\n    .filter(n -> n % 7 == 0)\n    .findFirst()                                        \u002F\u002F stops at 7\n    .orElseThrow();\n\u002F\u002F \"filter 1, filter 2 ... filter 7\" then DONE — never runs forever\n",[26,732,733,770,797,809,818],{"__ignoreMap":83},[87,734,735,738,741,743,746,748,750,752,754,756,758,761,764,767],{"class":89,"line":90},[87,736,737],{"class":104},"int",[87,739,740],{"class":100}," firstMultipleOf7 ",[87,742,111],{"class":104},[87,744,745],{"class":100}," Stream.",[87,747,416],{"class":143},[87,749,328],{"class":100},[87,751,370],{"class":153},[87,753,423],{"class":100},[87,755,223],{"class":104},[87,757,428],{"class":100},[87,759,760],{"class":104},"+",[87,762,763],{"class":153}," 1",[87,765,766],{"class":100},")  ",[87,768,769],{"class":93},"\u002F\u002F infinite\n",[87,771,772,774,776,779,781,783,786,789,792,795],{"class":89,"line":97},[87,773,214],{"class":100},[87,775,217],{"class":143},[87,777,778],{"class":100},"(n ",[87,780,223],{"class":104},[87,782,428],{"class":100},[87,784,785],{"class":104},"%",[87,787,788],{"class":153}," 7",[87,790,791],{"class":104}," ==",[87,793,794],{"class":153}," 0",[87,796,237],{"class":100},[87,798,799,801,803,806],{"class":89,"line":120},[87,800,214],{"class":100},[87,802,619],{"class":143},[87,804,805],{"class":100},"()                                        ",[87,807,808],{"class":93},"\u002F\u002F stops at 7\n",[87,810,811,813,816],{"class":89,"line":134},[87,812,214],{"class":100},[87,814,815],{"class":143},"orElseThrow",[87,817,265],{"class":100},[87,819,820],{"class":89,"line":172},[87,821,822],{"class":93},"\u002F\u002F \"filter 1, filter 2 ... filter 7\" then DONE — never runs forever\n",[15,824,825,826,829,830,335,832,335,835,335,837,840,841,844,845,848,849,851,852,854,855,335,858,860,861,864],{},"Short-circuiting ",[19,827,828],{},"terminal"," ops are ",[26,831,619],{},[26,833,834],{},"findAny",[26,836,622],{},[26,838,839],{},"allMatch",",\n",[26,842,843],{},"noneMatch","; the short-circuiting ",[19,846,847],{},"intermediate"," op is ",[26,850,599],{},". ",[26,853,839],{}," quits at the\nfirst element that ",[19,856,857],{},"fails",[26,859,622],{}," at the first that ",[19,862,863],{},"passes"," — neither usually\nscans the whole stream.",[10,866,868],{"id":867},"the-everyday-operations","The everyday operations",[15,870,871,872,874,875,878,879,882,883,874,885,888,889,892,893,895,896,898,899,902],{},"A handful of intermediate ops cover the bulk of real work. ",[26,873,217],{}," decides ",[54,876,877],{},"whether"," an\nelement survives (a ",[26,880,881],{},"Predicate","); ",[26,884,245],{},[54,886,887],{},"what"," it becomes (a ",[26,890,891],{},"Function",", one-to-one,\nmay change type); ",[26,894,590],{}," maps each element to a ",[19,897,68],{}," and ",[19,900,901],{},"flattens"," the results\ninto one (one-to-many, merged).",[78,904,906],{"className":80,"code":905,"language":82,"meta":83,"style":83},"sentences.stream()\n    .map(String::trim)                       \u002F\u002F 1-to-1: transform each\n    .flatMap(s -> Arrays.stream(s.split(\" \"))) \u002F\u002F 1-to-many: explode into words, flatten\n    .filter(w -> !w.isBlank())               \u002F\u002F keep the non-empty ones\n    .distinct()                              \u002F\u002F drop duplicates (equals\u002FhashCode)\n    .sorted()                                \u002F\u002F natural order\n    .skip(2)                                 \u002F\u002F discard the first two\n    .limit(10)                               \u002F\u002F keep at most ten\n    .toList();\n",[26,907,908,917,933,964,990,1002,1014,1031,1048],{"__ignoreMap":83},[87,909,910,913,915],{"class":89,"line":90},[87,911,912],{"class":100},"sentences.",[87,914,68],{"class":143},[87,916,208],{"class":100},[87,918,919,921,923,925,927,930],{"class":89,"line":97},[87,920,214],{"class":100},[87,922,245],{"class":143},[87,924,248],{"class":100},[87,926,251],{"class":104},[87,928,929],{"class":100},"trim)                       ",[87,931,932],{"class":93},"\u002F\u002F 1-to-1: transform each\n",[87,934,935,937,939,941,943,946,948,950,953,955,958,961],{"class":89,"line":120},[87,936,214],{"class":100},[87,938,590],{"class":143},[87,940,220],{"class":100},[87,942,223],{"class":104},[87,944,945],{"class":100}," Arrays.",[87,947,68],{"class":143},[87,949,163],{"class":100},[87,951,952],{"class":143},"split",[87,954,328],{"class":100},[87,956,957],{"class":331},"\" \"",[87,959,960],{"class":100},"))) ",[87,962,963],{"class":93},"\u002F\u002F 1-to-many: explode into words, flatten\n",[87,965,966,968,970,973,975,978,981,984,987],{"class":89,"line":134},[87,967,214],{"class":100},[87,969,217],{"class":143},[87,971,972],{"class":100},"(w ",[87,974,223],{"class":104},[87,976,977],{"class":104}," !",[87,979,980],{"class":100},"w.",[87,982,983],{"class":143},"isBlank",[87,985,986],{"class":100},"())               ",[87,988,989],{"class":93},"\u002F\u002F keep the non-empty ones\n",[87,991,992,994,996,999],{"class":89,"line":172},[87,993,214],{"class":100},[87,995,596],{"class":143},[87,997,998],{"class":100},"()                              ",[87,1000,1001],{"class":93},"\u002F\u002F drop duplicates (equals\u002FhashCode)\n",[87,1003,1004,1006,1008,1011],{"class":89,"line":178},[87,1005,214],{"class":100},[87,1007,593],{"class":143},[87,1009,1010],{"class":100},"()                                ",[87,1012,1013],{"class":93},"\u002F\u002F natural order\n",[87,1015,1016,1018,1021,1023,1025,1028],{"class":89,"line":185},[87,1017,214],{"class":100},[87,1019,1020],{"class":143},"skip",[87,1022,328],{"class":100},[87,1024,375],{"class":153},[87,1026,1027],{"class":100},")                                 ",[87,1029,1030],{"class":93},"\u002F\u002F discard the first two\n",[87,1032,1033,1035,1037,1039,1042,1045],{"class":89,"line":191},[87,1034,214],{"class":100},[87,1036,599],{"class":143},[87,1038,328],{"class":100},[87,1040,1041],{"class":153},"10",[87,1043,1044],{"class":100},")                               ",[87,1046,1047],{"class":93},"\u002F\u002F keep at most ten\n",[87,1049,1050,1052,1054],{"class":89,"line":211},[87,1051,214],{"class":100},[87,1053,262],{"class":143},[87,1055,265],{"class":100},[15,1057,1058,1059,1062,1063,898,1065,1067,1068,1070,1071,1074,1075,1078,1079,1081,1082,1085],{},"Two of these are ",[19,1060,1061],{},"stateful",": ",[26,1064,593],{},[26,1066,596],{}," must see other elements before they\ncan emit. ",[26,1069,593],{}," in particular is a ",[19,1072,1073],{},"full barrier"," — it buffers the entire stream, so\nit cannot short-circuit and ",[19,1076,1077],{},"hangs on an infinite source",". Apply ",[26,1080,217],{}," ",[54,1083,1084],{},"before"," the\nstateful ops to shrink the work they have to do.",[10,1087,1089],{"id":1088},"reduce-folding-to-a-single-value","reduce: folding to a single value",[15,1091,1092,1093,1095],{},"When you need to collapse a stream into one result — a sum, a product, a concatenation —\n",[26,1094,613],{}," repeatedly applies a binary operator. It has three overloads, escalating in power.",[78,1097,1099],{"className":80,"code":1098,"language":82,"meta":83,"style":83},"\u002F\u002F 1. accumulator only -> Optional (the stream might be empty)\nOptional\u003CInteger> sum = nums.stream().reduce((a, b) -> a + b);\n\n\u002F\u002F 2. identity + accumulator -> plain value (returns identity if empty)\nint total = nums.stream().reduce(0, Integer::sum);\n\n\u002F\u002F 3. identity + accumulator + combiner -> parallel-safe \u002F type-changing\nint charCount = words.stream()\n    .reduce(0, (acc, w) -> acc + w.length(), Integer::sum);\n",[26,1100,1101,1106,1142,1146,1151,1181,1185,1190,1206],{"__ignoreMap":83},[87,1102,1103],{"class":89,"line":90},[87,1104,1105],{"class":93},"\u002F\u002F 1. accumulator only -> Optional (the stream might be empty)\n",[87,1107,1108,1111,1114,1117,1119,1122,1124,1127,1129,1132,1134,1137,1139],{"class":89,"line":97},[87,1109,1110],{"class":100},"Optional\u003C",[87,1112,1113],{"class":104},"Integer",[87,1115,1116],{"class":100},"> sum ",[87,1118,111],{"class":104},[87,1120,1121],{"class":100}," nums.",[87,1123,68],{"class":143},[87,1125,1126],{"class":100},"().",[87,1128,613],{"class":143},[87,1130,1131],{"class":100},"((a, b) ",[87,1133,223],{"class":104},[87,1135,1136],{"class":100}," a ",[87,1138,760],{"class":104},[87,1140,1141],{"class":100}," b);\n",[87,1143,1144],{"class":89,"line":120},[87,1145,182],{"emptyLinePlaceholder":181},[87,1147,1148],{"class":89,"line":134},[87,1149,1150],{"class":93},"\u002F\u002F 2. identity + accumulator -> plain value (returns identity if empty)\n",[87,1152,1153,1155,1158,1160,1162,1164,1166,1168,1170,1173,1176,1178],{"class":89,"line":172},[87,1154,737],{"class":104},[87,1156,1157],{"class":100}," total ",[87,1159,111],{"class":104},[87,1161,1121],{"class":100},[87,1163,68],{"class":143},[87,1165,1126],{"class":100},[87,1167,613],{"class":143},[87,1169,328],{"class":100},[87,1171,1172],{"class":153},"0",[87,1174,1175],{"class":100},", Integer",[87,1177,251],{"class":104},[87,1179,1180],{"class":100},"sum);\n",[87,1182,1183],{"class":89,"line":178},[87,1184,182],{"emptyLinePlaceholder":181},[87,1186,1187],{"class":89,"line":185},[87,1188,1189],{"class":93},"\u002F\u002F 3. identity + accumulator + combiner -> parallel-safe \u002F type-changing\n",[87,1191,1192,1194,1197,1199,1202,1204],{"class":89,"line":191},[87,1193,737],{"class":104},[87,1195,1196],{"class":100}," charCount ",[87,1198,111],{"class":104},[87,1200,1201],{"class":100}," words.",[87,1203,68],{"class":143},[87,1205,208],{"class":100},[87,1207,1208,1210,1212,1214,1216,1219,1221,1224,1226,1229,1231,1234,1236],{"class":89,"line":211},[87,1209,214],{"class":100},[87,1211,613],{"class":143},[87,1213,328],{"class":100},[87,1215,1172],{"class":153},[87,1217,1218],{"class":100},", (acc, w) ",[87,1220,223],{"class":104},[87,1222,1223],{"class":100}," acc ",[87,1225,760],{"class":104},[87,1227,1228],{"class":100}," w.",[87,1230,144],{"class":143},[87,1232,1233],{"class":100},"(), Integer",[87,1235,251],{"class":104},[87,1237,1180],{"class":100},[15,1239,1240,1241,1244,1245,1247,1248,1250,1251,1254,1255,1258],{},"The ",[19,1242,1243],{},"identity"," must be a genuine no-op for the operation (",[26,1246,1172],{}," for sum, ",[26,1249,370],{}," for product,\n",[26,1252,1253],{},"\"\""," for concatenation). The ",[19,1256,1257],{},"combiner"," merges partial results computed by parallel\nsub-streams and is required whenever the result type differs from the element type.",[10,1260,1262],{"id":1261},"collect-building-a-result-briefly","collect: building a result (briefly)",[15,1264,1265,1266,1268,1269,1272],{},"The most flexible terminal op is ",[26,1267,607],{},", which uses a ",[26,1270,1271],{},"Collector"," to accumulate elements\ninto a container. For the common cases there are also direct shortcuts.",[78,1274,1276],{"className":80,"code":1275,"language":82,"meta":83,"style":83},"List\u003CString> list = s.collect(Collectors.toList()); \u002F\u002F classic, mutable-ish\nList\u003CString> imm  = s.toList();                      \u002F\u002F Java 16+, UNMODIFIABLE\nSet\u003CString>  set  = s.collect(Collectors.toSet());\nString[]     arr  = s.toArray(String[]::new);        \u002F\u002F typed array (not Object[])\n",[26,1277,1278,1302,1323,1346],{"__ignoreMap":83},[87,1279,1280,1282,1284,1287,1289,1291,1293,1295,1297,1299],{"class":89,"line":90},[87,1281,101],{"class":100},[87,1283,105],{"class":104},[87,1285,1286],{"class":100},"> list ",[87,1288,111],{"class":104},[87,1290,226],{"class":100},[87,1292,607],{"class":143},[87,1294,689],{"class":100},[87,1296,262],{"class":143},[87,1298,694],{"class":100},[87,1300,1301],{"class":93},"\u002F\u002F classic, mutable-ish\n",[87,1303,1304,1306,1308,1311,1313,1315,1317,1320],{"class":89,"line":97},[87,1305,101],{"class":100},[87,1307,105],{"class":104},[87,1309,1310],{"class":100},"> imm  ",[87,1312,111],{"class":104},[87,1314,226],{"class":100},[87,1316,262],{"class":143},[87,1318,1319],{"class":100},"();                      ",[87,1321,1322],{"class":93},"\u002F\u002F Java 16+, UNMODIFIABLE\n",[87,1324,1325,1328,1330,1333,1335,1337,1339,1341,1344],{"class":89,"line":120},[87,1326,1327],{"class":100},"Set\u003C",[87,1329,105],{"class":104},[87,1331,1332],{"class":100},">  set  ",[87,1334,111],{"class":104},[87,1336,226],{"class":100},[87,1338,607],{"class":143},[87,1340,689],{"class":100},[87,1342,1343],{"class":143},"toSet",[87,1345,169],{"class":100},[87,1347,1348,1350,1353,1355,1357,1359,1361,1363,1366,1369,1372],{"class":89,"line":134},[87,1349,105],{"class":104},[87,1351,1352],{"class":100},"[]     arr  ",[87,1354,111],{"class":104},[87,1356,226],{"class":100},[87,1358,625],{"class":143},[87,1360,328],{"class":100},[87,1362,105],{"class":104},[87,1364,1365],{"class":100},"[]",[87,1367,1368],{"class":104},"::new",[87,1370,1371],{"class":100},");        ",[87,1373,1374],{"class":93},"\u002F\u002F typed array (not Object[])\n",[15,1376,1377,1380,1381,1384,1385,1388,1389,840,1392,335,1395,1398,1399,1402],{},[26,1378,1379],{},"toList()"," is the concise modern choice but returns an ",[19,1382,1383],{},"unmodifiable"," list — use\n",[26,1386,1387],{},"Collectors.toList()"," if you must mutate it afterwards. The richer recipes (",[26,1390,1391],{},"groupingBy",[26,1393,1394],{},"partitioningBy",[26,1396,1397],{},"joining",", downstream collectors) belong to the ",[19,1400,1401],{},"Collectors"," topic and\nget their own page.",[10,1404,1406],{"id":1405},"match-and-find-operations","Match and find operations",[15,1408,1409],{},"When you only need a boolean or a single element, short-circuiting terminal ops are the\nright tool — they stop as soon as the answer is decided.",[78,1411,1413],{"className":80,"code":1412,"language":82,"meta":83,"style":83},"boolean hasNeg  = nums.stream().anyMatch(n -> n \u003C 0);  \u002F\u002F stops at first negative\nboolean allPos  = nums.stream().allMatch(n -> n > 0);  \u002F\u002F stops at first non-positive\nOptional\u003CInteger> first = nums.stream().filter(n -> n > 10).findFirst(); \u002F\u002F encounter order\nOptional\u003CInteger> any   = nums.parallelStream().filter(n -> n > 10).findAny(); \u002F\u002F any thread\n",[26,1414,1415,1450,1482,1523],{"__ignoreMap":83},[87,1416,1417,1420,1423,1425,1427,1429,1431,1433,1435,1437,1439,1442,1444,1447],{"class":89,"line":90},[87,1418,1419],{"class":104},"boolean",[87,1421,1422],{"class":100}," hasNeg  ",[87,1424,111],{"class":104},[87,1426,1121],{"class":100},[87,1428,68],{"class":143},[87,1430,1126],{"class":100},[87,1432,622],{"class":143},[87,1434,778],{"class":100},[87,1436,223],{"class":104},[87,1438,428],{"class":100},[87,1440,1441],{"class":104},"\u003C",[87,1443,794],{"class":153},[87,1445,1446],{"class":100},");  ",[87,1448,1449],{"class":93},"\u002F\u002F stops at first negative\n",[87,1451,1452,1454,1457,1459,1461,1463,1465,1467,1469,1471,1473,1475,1477,1479],{"class":89,"line":97},[87,1453,1419],{"class":104},[87,1455,1456],{"class":100}," allPos  ",[87,1458,111],{"class":104},[87,1460,1121],{"class":100},[87,1462,68],{"class":143},[87,1464,1126],{"class":100},[87,1466,839],{"class":143},[87,1468,778],{"class":100},[87,1470,223],{"class":104},[87,1472,428],{"class":100},[87,1474,150],{"class":104},[87,1476,794],{"class":153},[87,1478,1446],{"class":100},[87,1480,1481],{"class":93},"\u002F\u002F stops at first non-positive\n",[87,1483,1484,1486,1488,1491,1493,1495,1497,1499,1501,1503,1505,1507,1509,1512,1515,1517,1520],{"class":89,"line":120},[87,1485,1110],{"class":100},[87,1487,1113],{"class":104},[87,1489,1490],{"class":100},"> first ",[87,1492,111],{"class":104},[87,1494,1121],{"class":100},[87,1496,68],{"class":143},[87,1498,1126],{"class":100},[87,1500,217],{"class":143},[87,1502,778],{"class":100},[87,1504,223],{"class":104},[87,1506,428],{"class":100},[87,1508,150],{"class":104},[87,1510,1511],{"class":153}," 10",[87,1513,1514],{"class":100},").",[87,1516,619],{"class":143},[87,1518,1519],{"class":100},"(); ",[87,1521,1522],{"class":93},"\u002F\u002F encounter order\n",[87,1524,1525,1527,1529,1532,1534,1536,1539,1541,1543,1545,1547,1549,1551,1553,1555,1557,1559],{"class":89,"line":134},[87,1526,1110],{"class":100},[87,1528,1113],{"class":104},[87,1530,1531],{"class":100},"> any   ",[87,1533,111],{"class":104},[87,1535,1121],{"class":100},[87,1537,1538],{"class":143},"parallelStream",[87,1540,1126],{"class":100},[87,1542,217],{"class":143},[87,1544,778],{"class":100},[87,1546,223],{"class":104},[87,1548,428],{"class":100},[87,1550,150],{"class":104},[87,1552,1511],{"class":153},[87,1554,1514],{"class":100},[87,1556,834],{"class":143},[87,1558,1519],{"class":100},[87,1560,1561],{"class":93},"\u002F\u002F any thread\n",[15,1563,1564,1565,1568,1569,898,1571,1573,1574,1579,1580,1582,1583,851,1588,1590,1591,1593],{},"Mind the ",[19,1566,1567],{},"empty-stream"," edge cases: on an empty stream ",[26,1570,839],{},[26,1572,843],{}," return\n",[19,1575,1576],{},[26,1577,1578],{},"true"," (vacuous truth) while ",[26,1581,622],{}," returns ",[19,1584,1585],{},[26,1586,1587],{},"false",[26,1589,619],{}," honours\nencounter order; ",[26,1592,834],{}," may return any match, which lets a parallel stream skip the\nordering constraint and run faster.",[10,1595,1597],{"id":1596},"primitive-streams","Primitive streams",[15,1599,1600,1603,1604,335,1609,1614,1615,1620],{},[26,1601,1602],{},"Stream\u003CInteger>"," boxes every element, which is wasteful for heavy numeric work. The\nspecialized ",[19,1605,1606],{},[26,1607,1608],{},"IntStream",[19,1610,1611],{},[26,1612,1613],{},"LongStream",", and ",[19,1616,1617],{},[26,1618,1619],{},"DoubleStream"," carry raw primitives\nand add numeric terminal ops the object stream lacks.",[78,1622,1624],{"className":80,"code":1623,"language":82,"meta":83,"style":83},"int sum    = IntStream.rangeClosed(1, 100).sum();       \u002F\u002F 5050, no boxing\ndouble avg = IntStream.of(1, 2, 3).average().orElse(0);  \u002F\u002F OptionalDouble\n\nIntSummaryStatistics st = people.stream()\n    .mapToInt(Person::age)      \u002F\u002F Stream\u003CPerson> -> IntStream\n    .summaryStatistics();       \u002F\u002F count, sum, min, max, average in one pass\n",[26,1625,1626,1660,1705,1709,1723,1741],{"__ignoreMap":83},[87,1627,1628,1630,1633,1635,1638,1640,1642,1644,1646,1649,1651,1654,1657],{"class":89,"line":90},[87,1629,737],{"class":104},[87,1631,1632],{"class":100}," sum    ",[87,1634,111],{"class":104},[87,1636,1637],{"class":100}," IntStream.",[87,1639,394],{"class":143},[87,1641,328],{"class":100},[87,1643,370],{"class":153},[87,1645,335],{"class":100},[87,1647,1648],{"class":153},"100",[87,1650,1514],{"class":100},[87,1652,1653],{"class":143},"sum",[87,1655,1656],{"class":100},"();       ",[87,1658,1659],{"class":93},"\u002F\u002F 5050, no boxing\n",[87,1661,1662,1665,1668,1670,1672,1674,1676,1678,1680,1682,1684,1686,1688,1691,1693,1696,1698,1700,1702],{"class":89,"line":97},[87,1663,1664],{"class":104},"double",[87,1666,1667],{"class":100}," avg ",[87,1669,111],{"class":104},[87,1671,1637],{"class":100},[87,1673,325],{"class":143},[87,1675,328],{"class":100},[87,1677,370],{"class":153},[87,1679,335],{"class":100},[87,1681,375],{"class":153},[87,1683,335],{"class":100},[87,1685,380],{"class":153},[87,1687,1514],{"class":100},[87,1689,1690],{"class":143},"average",[87,1692,1126],{"class":100},[87,1694,1695],{"class":143},"orElse",[87,1697,328],{"class":100},[87,1699,1172],{"class":153},[87,1701,1446],{"class":100},[87,1703,1704],{"class":93},"\u002F\u002F OptionalDouble\n",[87,1706,1707],{"class":89,"line":120},[87,1708,182],{"emptyLinePlaceholder":181},[87,1710,1711,1714,1716,1719,1721],{"class":89,"line":134},[87,1712,1713],{"class":100},"IntSummaryStatistics st ",[87,1715,111],{"class":104},[87,1717,1718],{"class":100}," people.",[87,1720,68],{"class":143},[87,1722,208],{"class":100},[87,1724,1725,1727,1730,1733,1735,1738],{"class":89,"line":172},[87,1726,214],{"class":100},[87,1728,1729],{"class":143},"mapToInt",[87,1731,1732],{"class":100},"(Person",[87,1734,251],{"class":104},[87,1736,1737],{"class":100},"age)      ",[87,1739,1740],{"class":93},"\u002F\u002F Stream\u003CPerson> -> IntStream\n",[87,1742,1743,1745,1748,1750],{"class":89,"line":178},[87,1744,214],{"class":100},[87,1746,1747],{"class":143},"summaryStatistics",[87,1749,1656],{"class":100},[87,1751,1752],{"class":93},"\u002F\u002F count, sum, min, max, average in one pass\n",[15,1754,1755,1756,1758,1759,1758,1762,1765,1766,1769,1770,1773,1774,335,1776,1778,1779,1781],{},"Cross between worlds with ",[26,1757,1729],{},"\u002F",[26,1760,1761],{},"mapToLong",[26,1763,1764],{},"mapToDouble"," to enter a primitive stream,\nand ",[26,1767,1768],{},"boxed()"," or ",[26,1771,1772],{},"mapToObj(...)"," to return to an object stream. Reach for primitive streams\nwhenever you do real arithmetic — they are faster and give you ",[26,1775,1653],{},[26,1777,1690],{},", and\n",[26,1780,1747],{}," for free.",[10,1783,1785],{"id":1784},"single-use-streams-and-parallel-pitfalls","Single-use streams and parallel pitfalls",[15,1787,1788,1789,1792,1793,1796,1797,1800],{},"A stream is ",[19,1790,1791],{},"traversed once",". After a terminal op runs, the stream is consumed; touching\nit again throws ",[26,1794,1795],{},"IllegalStateException: stream has already been operated upon or closed",". If\nyou need the data twice, re-create the stream from the source, or wrap it in a\n",[26,1798,1799],{},"Supplier\u003CStream\u003CT>>"," that builds a fresh one on demand.",[15,1802,1803,1804,1807,1808,1811,1812,1815,1816,1819],{},"Parallelism is the other sharp edge. ",[26,1805,1806],{},"parallelStream()"," splits the source across the common\n",[19,1809,1810],{},"ForkJoinPool"," — but it only pays off for large, CPU-bound work over a cheaply-splittable\nsource (arrays, ",[26,1813,1814],{},"ArrayList","). The deeper trap is ",[19,1817,1818],{},"shared mutable state"," in your lambdas.",[78,1821,1823],{"className":80,"code":1822,"language":82,"meta":83,"style":83},"\u002F\u002F BROKEN: data race — multiple threads mutate one ArrayList\nList\u003CInteger> out = new ArrayList\u003C>();\nnums.parallelStream().forEach(out::add);\n\n\u002F\u002F CORRECT: let the framework do the accumulation safely\nList\u003CInteger> safe = nums.parallelStream()\n    .collect(Collectors.toList());\n",[26,1824,1825,1830,1844,1863,1867,1872,1889],{"__ignoreMap":83},[87,1826,1827],{"class":89,"line":90},[87,1828,1829],{"class":93},"\u002F\u002F BROKEN: data race — multiple threads mutate one ArrayList\n",[87,1831,1832,1834,1836,1838,1840,1842],{"class":89,"line":97},[87,1833,101],{"class":100},[87,1835,1113],{"class":104},[87,1837,108],{"class":100},[87,1839,111],{"class":104},[87,1841,114],{"class":104},[87,1843,117],{"class":100},[87,1845,1846,1849,1851,1853,1855,1858,1860],{"class":89,"line":120},[87,1847,1848],{"class":100},"nums.",[87,1850,1538],{"class":143},[87,1852,1126],{"class":100},[87,1854,610],{"class":143},[87,1856,1857],{"class":100},"(out",[87,1859,251],{"class":104},[87,1861,1862],{"class":100},"add);\n",[87,1864,1865],{"class":89,"line":134},[87,1866,182],{"emptyLinePlaceholder":181},[87,1868,1869],{"class":89,"line":172},[87,1870,1871],{"class":93},"\u002F\u002F CORRECT: let the framework do the accumulation safely\n",[87,1873,1874,1876,1878,1881,1883,1885,1887],{"class":89,"line":178},[87,1875,101],{"class":100},[87,1877,1113],{"class":104},[87,1879,1880],{"class":100},"> safe ",[87,1882,111],{"class":104},[87,1884,1121],{"class":100},[87,1886,1538],{"class":143},[87,1888,208],{"class":100},[87,1890,1891,1893,1895,1897,1899],{"class":89,"line":185},[87,1892,214],{"class":100},[87,1894,607],{"class":143},[87,1896,689],{"class":100},[87,1898,262],{"class":143},[87,1900,169],{"class":100},[15,1902,1903,1904,1907,1908,1758,1910,1912,1913,1915],{},"Keep stream lambdas ",[19,1905,1906],{},"pure"," (no side effects, no external mutation) and express the result\nwith ",[26,1909,607],{},[26,1911,613],{}," rather than accumulating from ",[26,1914,610],{},". Stay sequential by default\nand only parallelize after measuring a genuine win.",[10,1917,1919],{"id":1918},"recap","Recap",[15,1921,48,1922,1924,1925,1928,1929,1931,1932,1934,1935,1937,1938,1940,1941,1943,1944,1946,1947,1758,1949,1758,1951,1758,1953,1758,1955,1758,1957,1758,1959,1961,1962,1964,1965,1967,1968,1971,1972,1974,1975,1978],{},[19,1923,28],{}," is a ",[19,1926,1927],{},"lazy pipeline",", not a data structure — it pulls elements from a\n",[19,1930,37],{}," through ",[19,1933,847],{}," operations (lazy, return a ",[26,1936,28],{},") to a single\n",[19,1939,828],{}," operation (eager, triggers the run). Laziness buys you ",[19,1942,714],{}," and\n",[19,1945,726],{},", which is what makes infinite sources usable. Master the everyday ops —\n",[26,1948,217],{},[26,1950,245],{},[26,1952,590],{},[26,1954,596],{},[26,1956,593],{},[26,1958,599],{},[26,1960,1020],{},", fold with ",[26,1963,613],{},", finish with\n",[26,1966,607],{}," or a match\u002Ffind op — and prefer ",[19,1969,1970],{},"primitive streams"," for numeric work. Respect\nthe two hard rules: a stream is ",[19,1973,271],{},", and parallel streams demand ",[19,1976,1977],{},"pure,\nstateless"," lambdas to stay correct.",[1980,1981,1982],"style",{},"html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}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 .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}",{"title":83,"searchDepth":97,"depth":97,"links":1984},[1985,1986,1987,1988,1989,1990,1991,1992,1993,1994,1995,1996],{"id":12,"depth":97,"text":13},{"id":44,"depth":97,"text":45},{"id":287,"depth":97,"text":288},{"id":505,"depth":97,"text":506},{"id":707,"depth":97,"text":708},{"id":867,"depth":97,"text":868},{"id":1088,"depth":97,"text":1089},{"id":1261,"depth":97,"text":1262},{"id":1405,"depth":97,"text":1406},{"id":1596,"depth":97,"text":1597},{"id":1784,"depth":97,"text":1785},{"id":1918,"depth":97,"text":1919},"A practical guide to the Java Stream API: how a stream pipeline works, lazy intermediate vs eager terminal operations, short-circuiting, the core ops (filter\u002Fmap\u002FflatMap\u002Freduce), primitive streams, and parallel-stream pitfalls.","medium","md","Java",{},"\u002Fblog\u002Fjava-stream-api-guide","\u002Fjava\u002Fstreams-functional\u002Fstreams-api",{"title":5,"description":1997},"blog\u002Fjava-stream-api-guide","Stream API","Streams & Functional","streams-functional","2026-06-20","TgW42Ynf1gxkpiUOwG9cmfJPXCZ1pIehDASZ8QOUqXY",1782244089891]