[{"data":1,"prerenderedAt":135},["ShallowReactive",2],{"qa-\u002Fjava\u002Fstreams-functional\u002Fstreams-api":3},{"page":4,"siblings":118,"blog":132},{"id":5,"title":6,"body":7,"description":11,"difficulty":14,"extension":15,"framework":16,"frameworkSlug":17,"meta":18,"navigation":19,"order":12,"path":20,"questions":21,"questionsCount":108,"related":109,"seo":110,"seoDescription":111,"stem":112,"subtopic":113,"topic":114,"topicSlug":115,"updated":116,"__hash__":117},"qa\u002Fjava\u002Fstreams-functional\u002Fstreams-api.md","Streams Api",{"type":8,"value":9,"toc":10},"minimark",[],{"title":11,"searchDepth":12,"depth":12,"links":13},"",2,[],"medium","md","Java","java",{},true,"\u002Fjava\u002Fstreams-functional\u002Fstreams-api",[22,27,31,35,39,43,47,51,56,60,64,68,72,76,80,84,88,92,96,100,104],{"id":23,"difficulty":24,"q":25,"a":26},"what-is-a-stream","easy","What is a Stream in Java and how does it differ from a collection?","A **`Stream`** is not a data structure — it's a **pipeline** that carries\nelements from a **source** (a collection, array, generator, file…) through a\nseries of operations and produces a result. It **stores nothing**; it just\n*describes* a computation over the source.\n\nKey differences from a collection:\n\n| Collection | Stream |\n| ---------- | ------ |\n| Stores elements in memory | Holds no data — pulls from a source |\n| Eagerly built | **Lazily** evaluated |\n| Iterated externally (you loop) | Iterated internally (the stream loops) |\n| Reusable | **Single-use** (consumed once) |\n| Can be modified | Source is never mutated |\n\nSo you use a collection to *hold* data and a stream to *process* it\ndeclaratively (`filter` → `map` → `collect`) instead of writing explicit loops.\n",{"id":28,"difficulty":24,"q":29,"a":30},"creating-streams","What are the common ways to create a Stream?","Streams come from many **sources**:\n\n```java\nlist.stream();                       \u002F\u002F from any Collection\nStream.of(\"a\", \"b\", \"c\");            \u002F\u002F from explicit values\nArrays.stream(new int[]{1, 2, 3});   \u002F\u002F from an array\nStream.iterate(1, n -> n * 2);       \u002F\u002F infinite: 1,2,4,8,...\nStream.generate(Math::random);       \u002F\u002F infinite: repeated supplier calls\nIntStream.range(0, 5);               \u002F\u002F 0,1,2,3,4 (range)\nIntStream.rangeClosed(1, 5);         \u002F\u002F 1,2,3,4,5 (inclusive)\nFiles.lines(Path.of(\"data.txt\"));    \u002F\u002F lazy stream of lines\n\"abc\".chars();                       \u002F\u002F IntStream of char codes\n```\n\n`Stream.iterate`\u002F`generate` are **infinite** — always pair them with a\nshort-circuiting op like `limit(n)`. `Files.lines` returns a stream backed by an\nopen file, so close it (use try-with-resources).\n",{"id":32,"difficulty":14,"q":33,"a":34},"intermediate-vs-terminal","What is the difference between intermediate and terminal operations?","A stream pipeline is exactly **zero-or-more intermediate operations followed by\none terminal operation**.\n\n| | Intermediate | Terminal |\n| --- | ------------ | -------- |\n| Returns | another `Stream` | a value \u002F side-effect (not a stream) |\n| Evaluation | **lazy** — does nothing yet | **eager** — triggers the work |\n| Count per pipeline | any number | exactly one |\n| Examples | `filter`, `map`, `sorted`, `distinct`, `limit`, `peek` | `collect`, `forEach`, `reduce`, `count`, `findFirst`, `toArray` |\n\n```java\nlist.stream()\n    .filter(s -> s.length() > 3)   \u002F\u002F intermediate — lazy\n    .map(String::toUpperCase)      \u002F\u002F intermediate — lazy\n    .collect(Collectors.toList()); \u002F\u002F terminal — runs the pipeline\n```\n\nWithout a terminal operation **nothing executes** — the intermediate steps are\njust recorded.\n",{"id":36,"difficulty":14,"q":37,"a":38},"laziness","What does it mean that streams are lazy?","**Laziness** means intermediate operations are not evaluated when they are\ncalled — they only run when a **terminal** operation demands elements. The\npipeline then processes elements **one at a time, vertically** (each element\nflows through all stages before the next starts), not stage-by-stage over the\nwhole collection.\n\n```java\nStream\u003CString> s = list.stream()\n    .filter(x -> { System.out.println(\"filter \" + x); return true; })\n    .map(x -> { System.out.println(\"map \" + x); return x; });\n\u002F\u002F nothing printed yet — no terminal op\ns.forEach(x -> {});   \u002F\u002F NOW it runs, interleaving \"filter a\", \"map a\", ...\n```\n\nLaziness enables two big wins: **fusion** (multiple ops run in one pass) and\n**short-circuiting** (the pipeline can stop early without touching every\nelement).\n",{"id":40,"difficulty":14,"q":41,"a":42},"short-circuiting","What is short-circuiting in a stream pipeline?","A **short-circuiting** operation can produce a result (or stop the pipeline)\n**without processing every element**. Combined with laziness, this lets streams\nwork on **infinite** sources and quit as soon as the answer is known.\n\nShort-circuiting **terminal** ops: `findFirst`, `findAny`, `anyMatch`,\n`allMatch`, `noneMatch`. Short-circuiting **intermediate** op: `limit`.\n\n```java\nStream.iterate(1, n -> n + 1)   \u002F\u002F infinite\n      .filter(n -> n % 7 == 0)\n      .findFirst();             \u002F\u002F stops at 7 — never runs forever\n\nboolean any = list.stream().anyMatch(s -> s.isEmpty()); \u002F\u002F stops at first match\n```\n\n`allMatch` stops at the first element that **fails**, `anyMatch` at the first\nthat **passes** — they rarely scan the whole stream.\n",{"id":44,"difficulty":24,"q":45,"a":46},"filter","What does the filter operation do?","**`filter`** is an intermediate operation that keeps only elements matching a\n**`Predicate`** (a function returning `boolean`); the rest are dropped. It does\nnot change the element type — only how many pass through.\n\n```java\nList\u003CString> longNames = names.stream()\n    .filter(n -> n.length() > 4)   \u002F\u002F keep names longer than 4 chars\n    .collect(Collectors.toList());\n```\n\n`filter` is **stateless** and lazy, so several filters fuse into one pass.\nRule of thumb: `filter` decides *whether* an element survives; `map` decides\n*what* it becomes.\n",{"id":48,"difficulty":24,"q":49,"a":50},"map","What does the map operation do?","**`map`** is an intermediate operation that applies a **`Function`** to each\nelement and replaces it with the result — a **one-to-one transformation**. It can\nchange the element **type** (`Stream\u003CString>` → `Stream\u003CInteger>`).\n\n```java\nList\u003CInteger> lengths = names.stream()\n    .map(String::length)           \u002F\u002F String -> Integer\n    .collect(Collectors.toList());\n```\n\n`map` never changes the **number** of elements (N in, N out); it only transforms\neach one. When the mapping produces *another collection or stream* per element\nand you want them flattened, you need `flatMap` instead.\n",{"id":52,"difficulty":53,"q":54,"a":55},"flatmap","hard","What is flatMap and when do you use it instead of map?","**`flatMap`** maps each element to a **stream** and then **flattens** all those\nstreams into one. Use it when the mapping function yields multiple values per\nelement (a list, an `Optional`, a nested stream) and you want a single flat\nstream rather than a stream-of-streams.\n\n```java\nList\u003CList\u003CInteger>> nested = List.of(List.of(1, 2), List.of(3, 4));\n\n\u002F\u002F map gives Stream\u003CStream\u003CInteger>> — wrong shape\nnested.stream().map(List::stream);\n\n\u002F\u002F flatMap flattens to Stream\u003CInteger> -> [1, 2, 3, 4]\nList\u003CInteger> flat = nested.stream()\n    .flatMap(List::stream)\n    .collect(Collectors.toList());\n```\n\nMental model: use **`map`** for one-to-one (N→N), **`flatMap`** for one-to-many\nthat you want merged (N→M). Splitting sentences into words is the classic\n`flatMap` case.\n",{"id":57,"difficulty":14,"q":58,"a":59},"distinct-sorted","What do distinct and sorted do, and what is special about them?","**`distinct`** removes duplicates (by `equals`\u002F`hashCode`); **`sorted`** orders\nelements (natural order, or a supplied `Comparator`). Both are intermediate but\n**stateful** — they must see elements before they can emit.\n\n```java\nnums.stream()\n    .distinct()                          \u002F\u002F drop duplicates\n    .sorted(Comparator.reverseOrder())   \u002F\u002F sort descending\n    .collect(Collectors.toList());\n```\n\n`sorted` is a **full barrier**: it buffers the entire stream before producing any\noutput, so it cannot short-circuit and **breaks on infinite streams**. Both add\nmemory and ordering overhead, so apply `filter` *before* them to shrink the work.\n",{"id":61,"difficulty":24,"q":62,"a":63},"limit-skip","What do limit and skip do?","**`limit(n)`** truncates the stream to the first `n` elements;\n**`skip(n)`** discards the first `n` and keeps the rest. Together they give\npagination-style slicing.\n\n```java\nStream.iterate(1, x -> x + 1)\n      .limit(10)            \u002F\u002F first 10: 1..10\n      .skip(3)              \u002F\u002F drop 1,2,3 -> 4..10\n      .collect(Collectors.toList());\n```\n\n`limit` is **short-circuiting** — it's what tames infinite streams. On an\n**ordered** stream both are deterministic; on an unordered\u002Fparallel stream they\nmay pick *any* n elements, and `limit` on a parallel stream can actually hurt\nperformance because of the ordering constraint.\n",{"id":65,"difficulty":14,"q":66,"a":67},"peek","What is peek used for and why is it controversial?","**`peek`** is an intermediate operation that runs a side-effecting action on each\nelement **as it flows past**, then passes the element through unchanged. Its\nintended use is **debugging** — logging what moves through each stage.\n\n```java\nlist.stream()\n    .peek(x -> System.out.println(\"before filter: \" + x))\n    .filter(x -> x > 2)\n    .peek(x -> System.out.println(\"after filter: \" + x))\n    .collect(Collectors.toList());\n```\n\nIt's controversial because (1) it's lazy, so elements skipped by\nshort-circuiting **never reach `peek`**, and (2) using it to *mutate* state is an\nanti-pattern. Rule of thumb: use `peek` only for observation, never for logic.\n",{"id":69,"difficulty":53,"q":70,"a":71},"reduce","What is reduce and what are its three forms?","**`reduce`** combines all elements into a **single result** by repeatedly\napplying a binary operator. It comes in three overloads:\n\n```java\n\u002F\u002F 1. accumulator only -> Optional (stream may be empty)\nOptional\u003CInteger> sum = nums.stream().reduce((a, b) -> a + b);\n\n\u002F\u002F 2. identity + accumulator -> a plain value (identity if empty)\nint total = nums.stream().reduce(0, Integer::sum);\n\n\u002F\u002F 3. identity + accumulator + combiner -> for parallel \u002F type change\nint len = words.stream()\n    .reduce(0, (acc, w) -> acc + w.length(), Integer::sum);\n```\n\nThe **identity** must be a true no-op (`0` for sum, `1` for product). The\n**combiner** merges partial results from parallel sub-streams, so it's required\nwhen the accumulator's result type differs from the element type.\n",{"id":73,"difficulty":24,"q":74,"a":75},"count-min-max","How do count, min, and max work as terminal operations?","**`count()`** returns the number of elements as a `long`. **`min`** and **`max`**\ntake a `Comparator` and return an **`Optional`** (empty if the stream is empty).\n\n```java\nlong n = list.stream().filter(s -> s.startsWith(\"a\")).count();\n\nOptional\u003CString> longest = list.stream()\n    .max(Comparator.comparingInt(String::length));\n\nint smallest = nums.stream().min(Integer::compareTo).orElse(0);\n```\n\n`min`\u002F`max` return `Optional` precisely because there's no sensible value for an\nempty stream — handle it with `orElse`\u002F`orElseThrow`. (Note: since Java 9 the JVM\nmay skip the pipeline for `count()` if it can compute the size directly.)\n",{"id":77,"difficulty":14,"q":78,"a":79},"match-operations","What is the difference between anyMatch, allMatch and noneMatch?","All three are **short-circuiting** terminal operations that take a `Predicate`\nand return a `boolean`:\n\n- **`anyMatch`** — `true` if **at least one** element matches (stops at the\n  first match).\n- **`allMatch`** — `true` if **every** element matches (stops at the first\n  failure).\n- **`noneMatch`** — `true` if **no** element matches.\n\n```java\nnums.stream().anyMatch(n -> n \u003C 0);   \u002F\u002F any negatives?\nnums.stream().allMatch(n -> n > 0);   \u002F\u002F all positive?\nnums.stream().noneMatch(n -> n == 0); \u002F\u002F no zeros?\n```\n\nWatch the **empty-stream** edge cases (vacuous truth): on an empty stream\n`allMatch` and `noneMatch` return **`true`**, while `anyMatch` returns\n**`false`**.\n",{"id":81,"difficulty":14,"q":82,"a":83},"findfirst-findany","What is the difference between findFirst and findAny?","Both return an **`Optional`** with *some* element (or empty), and both\nshort-circuit. The difference matters only in **parallel** streams:\n\n- **`findFirst`** — returns the **first element in encounter order**.\n- **`findAny`** — returns **any** element, whichever a worker thread finds\n  first. It frees the runtime from honoring order, so it can be faster in\n  parallel.\n\n```java\nOptional\u003CInteger> a = nums.stream().filter(n -> n > 10).findFirst();\nOptional\u003CInteger> b = nums.parallelStream().filter(n -> n > 10).findAny();\n```\n\nOn a sequential stream they behave identically. Use `findAny` when you genuinely\ndon't care *which* match you get and want maximum parallel performance.\n",{"id":85,"difficulty":14,"q":86,"a":87},"collect-toarray-tolist","How do you turn a stream back into a collection or array?","The main terminal operation is **`collect`** with a `Collector`. There are also\ndirect helpers:\n\n```java\nList\u003CString> list = s.collect(Collectors.toList()); \u002F\u002F mutable-ish, classic\nList\u003CString> imm  = s.toList();                      \u002F\u002F Java 16+, unmodifiable\nSet\u003CString>  set  = s.collect(Collectors.toSet());\n\nString[]     arr  = s.toArray(String[]::new);        \u002F\u002F typed array\nObject[]     objs = s.toArray();                     \u002F\u002F Object[]\nint[]        ints = intStream.toArray();             \u002F\u002F primitive array\n```\n\n**`toList()`** (Java 16+) is the concise modern choice but returns an\n**unmodifiable** list; use `Collectors.toList()` if you need to mutate the\nresult. Pass a generator (`String[]::new`) to `toArray` to get a typed array\ninstead of `Object[]`. Deeper collector recipes (grouping, joining) live on the\nCollectors page.\n",{"id":89,"difficulty":14,"q":90,"a":91},"primitive-streams","What are IntStream, LongStream and DoubleStream and why use them?","They are **specialized primitive streams** that avoid the boxing overhead of\n`Stream\u003CInteger>`\u002F`Stream\u003CLong>`\u002F`Stream\u003CDouble>`. Because elements are raw\nprimitives, they add numeric terminal ops that the object stream lacks.\n\n```java\nint sum      = IntStream.rangeClosed(1, 100).sum();\ndouble avg   = IntStream.of(1, 2, 3).average().orElse(0); \u002F\u002F OptionalDouble\nIntSummaryStatistics st = nums.stream()\n    .mapToInt(Integer::intValue)   \u002F\u002F Stream\u003CInteger> -> IntStream\n    .summaryStatistics();          \u002F\u002F count, sum, min, max, average at once\n```\n\nConvert with **`mapToInt`\u002F`mapToLong`\u002F`mapToDouble`** to enter a primitive\nstream, **`boxed()`** or **`mapToObj(...)`** to go back to an object stream.\nPrefer primitive streams for heavy numeric work — they're faster and offer\n`sum`\u002F`average`\u002F`summaryStatistics` for free.\n",{"id":93,"difficulty":53,"q":94,"a":95},"stateless-vs-stateful","What is the difference between stateless and stateful operations?","A **stateless** operation processes each element **independently** of the others\n(`filter`, `map`, `flatMap`, `peek`) — it needs no memory of what came before.\nA **stateful** operation must consider **other elements** to produce its output\n(`distinct`, `sorted`, `limit`, `skip`).\n\n```java\nstream.filter(x -> x > 0)   \u002F\u002F stateless — each element judged alone\n      .sorted()             \u002F\u002F stateful — needs ALL elements buffered\n      .distinct();          \u002F\u002F stateful — must remember what it has seen\n```\n\nWhy it matters: stateful ops may **buffer** the stream (extra memory), can act as\n**barriers** that prevent short-circuiting (`sorted` on an infinite stream hangs),\nand are harder to **parallelize**. Keep pipelines stateless where you can.\n",{"id":97,"difficulty":14,"q":98,"a":99},"stream-reuse","Why can't a stream be reused, and what happens if you try?","A stream can be **traversed only once**. After a terminal operation runs (or even\nafter some intermediate ops link onto it), the stream is **consumed**; touching it\nagain throws **`IllegalStateException: stream has already been operated upon or\nclosed`**.\n\n```java\nStream\u003CString> s = list.stream();\ns.count();          \u002F\u002F terminal — consumes the stream\ns.forEach(...);     \u002F\u002F IllegalStateException!\n```\n\nStreams are single-use because they hold no data and may be backed by I\u002FO or\ninfinite generators — re-traversal isn't generally possible. If you need to\nprocess the data twice, **re-create the stream from the source** (`list.stream()`\nagain) or use a `Supplier\u003CStream\u003CT>>` that builds a fresh one on demand.\n",{"id":101,"difficulty":53,"q":102,"a":103},"parallel-streams","What are parallel streams and when do they help or hurt?","A **parallel stream** splits its source and processes chunks **concurrently** on\nthe common **ForkJoinPool**, then merges the partial results. You opt in with\n`collection.parallelStream()` or `.parallel()` on an existing stream.\n\n```java\nlong count = bigList.parallelStream()\n                    .filter(this::isExpensive)\n                    .count();\n```\n\nThey **help** when: the data set is large, the per-element work is genuinely\nexpensive (CPU-bound), the source splits cheaply (arrays, `ArrayList`), and\noperations are stateless. They **hurt** when: the data is small, the source is\nhard to split (`LinkedList`, I\u002FO streams), elements are cheap (split\u002Fmerge cost\ndominates), or you rely on order. Rule of thumb: stay sequential by default and\nonly parallelize after measuring a real win.\n",{"id":105,"difficulty":53,"q":106,"a":107},"stream-side-effects","Why should you avoid side effects and stateful lambdas in streams?","Stream operations should be **pure** — depend only on their input and not mutate\nshared state. A **stateful lambda** that reads or writes outside variables breaks\nunder parallelism and even under reordering, producing **non-deterministic** or\ncorrupt results.\n\n```java\n\u002F\u002F BROKEN: shared mutable state, not thread-safe in parallel\nList\u003CInteger> out = new ArrayList\u003C>();\nnums.parallelStream().forEach(out::add);   \u002F\u002F data race \u002F lost updates\n\n\u002F\u002F CORRECT: let the framework collect for you\nList\u003CInteger> safe = nums.parallelStream()\n                         .collect(Collectors.toList());\n```\n\nAlso avoid modifying the stream's **source** during iteration\n(`ConcurrentModificationException`). Rule of thumb: never accumulate into an\nexternal collection from `forEach`\u002F`peek` — express the result with `collect`\nor `reduce`, which are designed to be safe even in parallel.\n",21,null,{"description":11},"Java Stream API interview questions — intermediate vs terminal operations, laziness and short-circuiting, map\u002Ffilter\u002Freduce, flatMap, stream sources, primitive streams, and parallel streams.","java\u002Fstreams-functional\u002Fstreams-api","Stream API","Streams & Functional","streams-functional","2026-06-20","vyPHlLm8MySu2tJjaXRTbOKMIzsd3OepbddECXw20FU",[119,123,124,128],{"subtopic":120,"path":121,"order":122},"Lambdas & Functional Interfaces","\u002Fjava\u002Fstreams-functional\u002Flambdas-functional-interfaces",1,{"subtopic":113,"path":20,"order":12},{"subtopic":125,"path":126,"order":127},"Collectors & Grouping","\u002Fjava\u002Fstreams-functional\u002Fcollectors-grouping",3,{"subtopic":129,"path":130,"order":131},"Optional","\u002Fjava\u002Fstreams-functional\u002Foptional",4,{"path":133,"title":134},"\u002Fblog\u002Fjava-stream-api-guide","Java Stream API — Pipelines, Laziness & the Core Operations Explained",1782244116334]