{"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\u2019s 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<? extends E> c);\r\nboolean removeAll(Collection<?> 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 \u2013 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 \u2013 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\u2019s 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 \u2013 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<Integer> original = ImmutableList.of(1);\r\n\r\nList<Integer> modified = new ImmutableList.Builder<Integer>()\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<Integer> original = List.of(1);\r\nList<Integer> modified = original.append(2);\r\n\r\nmodified.dropWhile(i -> i < 42);\r\nmodified.combinations();\r\nmodified.foldLeft(0 , Integer::sum)<\/pre>\n<h2 id=\"collecting-vavrs-collections\"><strong>Collecting Vavr\u2019s 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 \u2013 in most cases that would be simply placing all elements in some collection.<\/p>\n<p>Vavr\u2019s collections have a method that provides the similar(but limited) functionality but it\u2019s 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\u2026 one of the method signatures of Vavr\u2019s <em>collect()<\/em> is especially intriguing:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\"><R, A> R collect(java.util.stream.Collector<? super T, A, R> collector)<\/pre>\n<p>As you can see, <strong>Vavr\u2019s 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\u2019s comforting to know that Vavr\u2019s functionality is a superset of Stream API\u2019s (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\u2019s 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 \u2013 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(() -> 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 \u2013 which can also be applied to Vavr\u2019s 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\"><dependency>\r\n    <groupId>io.vavr<\/groupId>\r\n    <artifactId>vavr-test<\/artifactId>\r\n    <version>0.9.0<\/version>\r\n<\/dependency><\/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}]}}