<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Maurice Naftalin&#039;s Lambda FAQ &#187; bgoetz</title>
	<atom:link href="https://www.lambdafaq.org/author/bgoetz/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.lambdafaq.org</link>
	<description>Your questions answered: all about Lambdas and friends</description>
	<lastBuildDate>Tue, 04 May 2021 15:50:56 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=4.2.38</generator>
	<item>
		<title>Why are Stream operations not defined directly on Collection?</title>
		<link>https://www.lambdafaq.org/why-are-stream-operations-not-defined-directly-on-collection/</link>
		<comments>https://www.lambdafaq.org/why-are-stream-operations-not-defined-directly-on-collection/#comments</comments>
		<pubDate>Mon, 19 Nov 2012 12:00:14 +0000</pubDate>
		<dc:creator><![CDATA[bgoetz]]></dc:creator>
				<category><![CDATA[Design Rationale]]></category>

		<guid isPermaLink="false">http://www.lambdafaq.org/?p=748</guid>
		<description><![CDATA[<p>Early drafts of the API exposed methods like filter, map, and reduce on Collection or Iterable. However, user experience with this design led to a more formal separation of the &#8220;stream&#8221; methods into their own abstraction. Reasons included: Methods on Collection such as removeAll make in-place modifications, in contrast to the new methods which are [...]]]></description>
				<content:encoded><![CDATA[<p>Early drafts of the API exposed methods like <code>filter</code>, <code>map</code>, and <code>reduce</code> on <code>Collection</code> or <code>Iterable</code>.  However, user experience with this design led to a more formal separation of the &#8220;stream&#8221; methods into their own abstraction.  Reasons included:
<ul>
<li>Methods on <code>Collection</code> such as <code>removeAll</code> make in-place modifications, in contrast to the new methods which are more functional in nature. Mixing two different kinds of methods on the same abstraction forces the user to keep track of which are which.  For example, given the declaration
<pre><code>    Collection<String> strings;
</code></pre>
<p>the two very similar-looking method calls</p>
<pre><code>    strings.removeAll(s -> s.length() == 0);
    strings.filter(s -> s.length() == 0);          // not supported in the current API
</code></pre>
<p>would have surprisingly different results; the first would remove all empty <code>String</code> objects from the collection, whereas the second would return a stream containing all the non-empty <code>String</code>s, while having no effect on the collection.</p>
<p>Instead, the current design ensures that only an explicitly-obtained stream can be filtered:</p>
<pre><code>    strings.stream().filter(s.length() == 0)...;
</code></pre>
<p>where the ellipsis represents further stream operations, ending with a terminating operation.  This gives the reader a much clearer intuition about the action of <code>filter</code>;
</li>
<li>
<p>With lazy methods added to <code>Collection</code>, users were confused by a perceived&mdash;but erroneous&mdash;need to reason about whether the collection was in &#8220;lazy mode&#8221; or &#8220;eager mode&#8221;.  Rather than burdening <code>Collection</code> with new and different functionality, it is cleaner to provide a <code>Stream</code> view with the new functionality;</li>
<li>
<p>The more methods added to <code>Collection</code>, the greater the chance of name collisions with existing third-party implementations.  By only adding a few methods (<code>stream</code>, <code>parallel</code>) the chance for conflict is greatly reduced;</li>
<li>A view transformation is still needed to access a parallel view; the asymmetry between the sequential and the parallel stream views was unnatural. Compare, for example
<pre style="margin-bottom:0"><code>    coll.filter(...).map(...).reduce(...);
</code></pre>
<p style="margin:0">with</p>
<pre style="margin-top:0"><code>    coll.parallel().filter(...).map(...).reduce(...);
</code></pre>
<p>This asymmetry would be particularly obvious in the API documentation, where <code>Collection</code> would have many new methods to produce sequential streams, but only one to produce parallel streams, which would then have all the same methods as <code>Collection</code>. Factoring these into a separate interface, <code>StreamOps</code> say, would not help; that would still, counterintuitively, need to be implemented by both <code>Stream</code> and <code>Collection</code>;</li>
<li>A uniform treatment of views also leaves room for other additional views in the future.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>https://www.lambdafaq.org/why-are-stream-operations-not-defined-directly-on-collection/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
