{"id":13086,"date":"2017-08-23T14:25:21","date_gmt":"2017-08-23T12:25:21","guid":{"rendered":"https:\/\/touk.pl\/blog\/?p=13086"},"modified":"2022-08-02T12:19:39","modified_gmt":"2022-08-02T10:19:39","slug":"vavr-collections-and-java-stream-api-collectors","status":"publish","type":"post","link":"https:\/\/touk.pl\/blog\/2017\/08\/23\/vavr-collections-and-java-stream-api-collectors\/","title":{"rendered":"Vavr, Collections, and Java Stream API Collectors"},"content":{"rendered":"<p><a href=\"http:\/\/www.vavr.io\">Vavr<\/a> is now <strong>a must-have for every modern Java 8+ project.<\/strong> It encourages writing code in a functional manner by providing a new persistent Collections API along with a set of new Functional Interfaces and monadic tools like <em>Option, Try, Either,<\/em> etc.<\/p>\n<p>You can read more about it <a href=\"http:\/\/www.baeldung.com\/javaslang\">here<\/a>.<\/p>\n<h2 id=\"vavrs-persistent-collections-api\"><strong>Vavr&#8217;s Persistent Collections API<\/strong><\/h2>\n<p>To provide useable immutable data structures, <strong>the whole Collections API needed to be redesigned from scratch.<\/strong><\/p>\n<p>The standard <em>java.util.Collection<\/em> interface contains methods that discourage immutability such as:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\">boolean add(E e);\r\nboolean remove(Object o);\r\nboolean addAll(Collection&lt;? extends E&gt; c);\r\nboolean removeAll(Collection&lt;?&gt; c);<\/pre>\n<p>One might think that the problem is that those methods allow modifications of the particular collection instance, but this is not entirely true &#8211; with immutable data structures, each mutating operation needs to derive a new collection from the existing one. Simply put, <strong>each of those methods should be able to return a new instance of the collection.<\/strong><\/p>\n<p>Here, the whole collections hierarchy is restricted to returning <em>boolean<\/em> or <em>void<\/em> from mutating methods &#8211; which makes them suitable only for mutable implementations.<\/p>\n<p>Of course, immutable implementations of <em>java.util.Collection<\/em> exist, but above-mentioned methods are simply forbidden. That&#8217;s how it looks like in the\u00a0<em>com.google.common.collect.ImmutableList<\/em>:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\">\/**\r\n * Guaranteed to throw an exception and leave the list unmodified.\r\n *\r\n * @throws UnsupportedOperationException always\r\n * @deprecated Unsupported operation.\r\n *\/\r\n@Deprecated\r\n@Override\r\npublic final void add(int index, E element) {\r\n  throw new UnsupportedOperationException();\r\n}<\/pre>\n<p>And this is far from perfect &#8211; even the simplest <em>add()<\/em> operation <a href=\"https:\/\/stackoverflow.com\/questions\/10354286\/what-is-an-efficient-and-elegant-way-to-add-a-single-element-to-an-immutable-set\">becomes a ceremony:<\/a><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\">ImmutableList&lt;Integer&gt; original = ImmutableList.of(1);\r\n\r\nList&lt;Integer&gt; modified = new ImmutableList.Builder&lt;Integer&gt;()\r\n  .addAll(original)\r\n  .add(2)\r\n  .build();<\/pre>\n<p><strong>A major redesign made it possible to interact with immutable collections more naturally and add some new exciting features:<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\">import io.vavr.collection.List;\r\n\/\/ ...\r\n\r\nList&lt;Integer&gt; original = List.of(1);\r\nList&lt;Integer&gt; modified = original.append(2);\r\n\r\nmodified.dropWhile(i -&gt; i &lt; 42);\r\nmodified.combinations();\r\nmodified.foldLeft(0 , Integer::sum)<\/pre>\n<h2 id=\"collecting-vavrs-collections\"><strong>Collecting Vavr&#8217;s Collections<\/strong><\/h2>\n<p>One of the key features of the Java Stream API was the <em>collect()<\/em> API that made it possible to take elements from <em>Stream<\/em> and apply the provided strategy to them &#8211; in most cases that would be simply placing all elements in some collection.<\/p>\n<p>Vavr&#8217;s collections have a method that provides the similar(but limited) functionality but it&#8217;s not being used often because\u00a0<strong>almost all operations that were available only using Stream API, are available on the collection level in Vavr.<\/strong><\/p>\n<p>But&#8230; one of the method signatures of Vavr&#8217;s <em>collect()<\/em> is especially intriguing:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\">&lt;R, A&gt; R collect(java.util.stream.Collector&lt;? super T, A, R&gt; collector)<\/pre>\n<p>As you can see, <strong>Vavr&#8217;s collections are fully compatible with Stream API Collectors and we can use our favourite\u00a0<em>Collectors<\/em> easily:<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\">list.collect(Collectors.toList());\r\nlist.collect(Collectors.groupingBy(Integer::byteValue));<\/pre>\n<p>That might not be super useful for everyday use-cases because the most common operations are accessible without using <em>Collectors<\/em> but it&#8217;s comforting to know that Vavr&#8217;s functionality is a superset of Stream API&#8217;s (at least in terms of <em>collect()<\/em> semantics)<\/p>\n<h2 id=\"collecting-everything\"><strong>Collecting Everything<\/strong><\/h2>\n<p>The interesting realization happens when we decide to investigate the type hierarchy in Vavr:<\/p>\n<figure id=\"attachment_181\" aria-describedby=\"caption-attachment-181\" style=\"width: 1215px\" class=\"wp-caption aligncenter\"><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-181 size-full\" src=\"http:\/\/4comprehension.com\/wp-content\/uploads\/2017\/08\/vavr-overview.png\" alt=\"\" width=\"1215\" height=\"286\" \/><figcaption id=\"caption-attachment-181\" class=\"wp-caption-text\">source: http:\/\/www.vavr.io\/vavr-docs\/<\/figcaption><\/figure>\n<p>We can notice here that the\u00a0<em><a href=\"https:\/\/static.javadoc.io\/io.vavr\/vavr\/0.9.0\/io\/vavr\/Value.html\">Value<\/a><\/em> resides on top collections hierarchy and this is where the <em>collect()<\/em> method mentioned above is defined.<\/p>\n<p><strong>If we look closer, it&#8217;s clear that classes like <em>Option, Try, Either, Future, Lazy<\/em> also implement the <em>Value<\/em> interface.<\/strong>\u00a0The reasoning behind this is that they are all essentially containers for values &#8211; containers that can hold max up to one element.<strong>\u00a0\u00a0<\/strong><\/p>\n<p>This makes them compatible with Stream API Collectors, as well:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\">Option.of(42)\r\n  .collect(Collectors.toList());\r\n\r\nTry.of(() -&gt; URI.create(\"4comprehension.com\"))\r\n  .collect(Collectors.partitioningBy(URI::isAbsolute));<\/pre>\n<h2 id=\"summary\"><strong>Summary<\/strong><\/h2>\n<p>The redesign of the Collections API allowed the introduction of cool new methods, as well as achieving full interoperability with Java Stream API Collectors &#8211; which can also be applied to Vavr&#8217;s functional control structures like <em>Option, Try, Either, Future,<\/em> or <em>Lazy.<\/em><\/p>\n<p>The examples above use:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\">&lt;dependency&gt;\r\n    &lt;groupId&gt;io.vavr&lt;\/groupId&gt;\r\n    &lt;artifactId&gt;vavr-test&lt;\/artifactId&gt;\r\n    &lt;version&gt;0.9.0&lt;\/version&gt;\r\n&lt;\/dependency&gt;<\/pre>\n","protected":false},"excerpt":{"rendered":"Vavr is now a must-have for every modern Java 8+ project. It encourages writing code in a functional&hellip;\n","protected":false},"author":68,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[11],"tags":[594,68],"class_list":{"0":"post-13086","1":"post","2":"type-post","3":"status-publish","4":"format-standard","6":"category-development-design","7":"tag-api","8":"tag-java"},"_links":{"self":[{"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/posts\/13086","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/users\/68"}],"replies":[{"embeddable":true,"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/comments?post=13086"}],"version-history":[{"count":12,"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/posts\/13086\/revisions"}],"predecessor-version":[{"id":14817,"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/posts\/13086\/revisions\/14817"}],"wp:attachment":[{"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/media?parent=13086"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/categories?post=13086"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/tags?post=13086"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}