convert another blog (replace images)
diff --git a/site/src/site/blog/fruity-eclipse-collections.adoc b/site/src/site/blog/fruity-eclipse-collections.adoc
index 47b7fa2..77ea556 100644
--- a/site/src/site/blog/fruity-eclipse-collections.adoc
+++ b/site/src/site/blog/fruity-eclipse-collections.adoc
@@ -4,7 +4,7 @@
:keywords: datascience, eclipse collections, groovy, kmeans, emoji, virtual threads, scala integration
:description: This post looks at using KMeans to compare fruit nominated color with the colors used in its emoji.
-This blog post continues on to some degree from the
+This blog post continues on the theme of using fruit emoji from the
https://blogs.apache.org/groovy/entry/deep-learning-and-eclipse-collections[previous post],
but instead of deep learning, we'll look at clustering using k-means after first exploring some top methods of https://www.eclipse.org/collections/[Eclipse Collections] with fruit emoji examples.
@@ -13,11 +13,69 @@
First, we'll define a Fruit enum (it adds one additional fruit compared to the related
https://github.com/eclipse/eclipse-collections-kata/tree/master/top-methods-kata-solutions[Eclipse Collections kata]):
-image:https://blogs.apache.org/groovy/mediaresource/8d0d5468-f58a-445a-8e79-854c7815d861[code for fruit enum]
+[source,groovy]
+----
+enum Fruit {
+ APPLE('🍎', Color.RED),
+ PEACH('🍑', Color.ORANGE),
+ BANANA('🍌', Color.YELLOW),
+ CHERRY('🍒', Color.RED),
+ ORANGE('🍊', Color.ORANGE),
+ GRAPE('🍇', Color.MAGENTA)
+
+ public static ImmutableList<Fruit> ALL = Lists.immutable.with(values())
+ public static ImmutableList<String> ALL_EMOJI = Lists.immutable.with(*values()*.emoji)
+ final String emoji
+ final Color color
+
+ Fruit(String emoji, Color color) {
+ this.emoji = emoji
+ this.color = color
+ }
+
+ static Fruit of(String emoji) {
+ values().find{it.emoji == emoji }
+ }
+}
+----
We can use this enum in the following examples which show off numerous common Eclipse Collections methods:
-image:https://blogs.apache.org/groovy/mediaresource/c272dd74-9d35-49b7-8857-c7fccf1989f0[exploring common eclipse collections methods]
+[source,groovy]
+----
+assert Lists.mutable.with('🍎', '🍎', '🍌', '🍌').distinct() ==
+ Lists.mutable.with('🍎', '🍌')
+
+var onlyBanana = Sets.immutable.with('🍌')
+
+assert Fruit.ALL_EMOJI.select(onlyBanana::contains) == List.of('🍌')
+
+assert Fruit.ALL_EMOJI.reject(onlyBanana::contains) ==
+ List.of('🍎', '🍑', '🍒', '🍊', '🍇')
+
+assert Fruit.ALL.groupBy(Fruit::getColor) ==
+ Multimaps.mutable.list.empty()
+ .withKeyMultiValues(RED, Fruit.of('🍎'), Fruit.of('🍒'))
+ .withKeyMultiValues(YELLOW, Fruit.of('🍌'))
+ .withKeyMultiValues(ORANGE, Fruit.of('🍑'), Fruit.of('🍊'))
+ .withKeyMultiValues(MAGENTA, Fruit.of('🍇'))
+
+assert Fruit.ALL.countBy(Fruit::getColor) ==
+ Bags.immutable.withOccurrences(RED, 2, YELLOW, 1, ORANGE, 2, MAGENTA, 1)
+
+Fruit.ALL_EMOJI.chunk(4).with {
+ assert first == Lists.mutable.with('🍎', '🍑', '🍌', '🍒')
+ assert last == Lists.mutable.with('🍊', '🍇')
+}
+
+// For normal threads, replace 'withExistingPool' line of code with:
+//GParsExecutorsPool.withPool { pool ->
+GParsExecutorsPool.withExistingPool(Executors.newVirtualThreadPerTaskExecutor()) { pool ->
+ var parallelFruit = Fruit.ALL.asParallel(pool, 1)
+ var redFruit = parallelFruit.select(fruit -> fruit.color == RED).toList()
+ assert redFruit == Lists.mutable.with(Fruit.of('🍎'), Fruit.of('🍒'))
+}
+----
The last example calculates red fruit in parallel threads.
As coded, it uses virtual threads when run on JDK19 with preview features enabled.
@@ -31,7 +89,7 @@
of the related emoji. As in the previous blog, we'll use the slightly nicer
https://fonts.google.com/noto/specimen/Noto+Color+Emoji?preview.text=%F0%9F%8D%8E%F0%9F%8D%91%F0%9F%8D%8C%F0%9F%8D%92%F0%9F%8D%8A%F0%9F%8D%87&preview.text_type=custom[Noto Color Emoji]
fonts for our fruit as shown here:
-image:https://blogs.apache.org/groovy/mediaresource/4e4f1abe-0775-442d-ba17-7488e3eeca49[Noto Color Emoji]
+image:img/fruit_emoji.png[Noto Color Emoji]
We'll use an Eclipse Collection `BiMap` to switch back and forth between the color names
and java.awt colors:
@@ -99,7 +157,7 @@
We used a https://plotly.com/javascript/[Plotly] 3D interactive scatterplot
(as supported by the https://jtablesaw.github.io/tablesaw/userguide/Introduction_to_Plotting[Tablesaw] Java dataframe and visualization library to visualize our emoji colors (as degrees on the color spectrum) vs the XY coordinates:
-image:https://blogs.apache.org/groovy/mediaresource/85b4c127-52a3-4cc6-a7fc-1e72aa49e8b8[Color vs xy plot]
+image:img/fruity_eclipse_collections_color_vs_xy.png[Color vs xy plot]
We are going to try out 3 approaches for determining the predominant color of each emoji:
@@ -110,27 +168,27 @@
=== Most Common Color
Ignoring the background white color, the most common color for our PEACH emoji is a shade of orange. The graph below shows the count of each color:
-image:https://blogs.apache.org/groovy/mediaresource/b9f82465-62e2-45c0-926f-634568381be8[Color histogram for PEACH]
+image:img/fruity_eclipse_collections_peach_color_histogram.png[Color histogram for PEACH]
=== Most Common Range
If instead of counting each color, we group colors into their range and count the numbers in each range, we get the following graph for PEACH:
-image:https://blogs.apache.org/groovy/mediaresource/4ce2ac0e-87ac-4509-9fa8-10928419f4a0[Range histogram for PEACH]
+image:img/fruity_eclipse_collections_peach_range_histogram.png[Range histogram for PEACH]
=== K-Means
K-Means is an algorithm for finding cluster centroids. For k=3, we would start by picking
3 random points as our starting centroids.
-image:https://blogs.apache.org/groovy/mediaresource/6192d3b7-a3c7-4ce5-b0c0-a3286619dd12[kmeans step 1]
+image:img/kmeans_step1.png[kmeans step 1]
We allocate all points to their closest centroid:
-image:https://blogs.apache.org/groovy/mediaresource/751eaac0-5ba2-448d-8f67-6ebf53613ac9[kmeans step 2]
+image:img/kmeans_step2.png[kmeans step 2]
Given this allocation, we re-calculate each centroid from all of its points:
-image:https://blogs.apache.org/groovy/mediaresource/daa9530e-fc5d-458d-8029-a1fd8a62d521[kmeans step 3]
+image:img/kmeans_step3.png[kmeans step 3]
We repeat this process until either a stable centroid selection
is found, or we have reached a certain number of iterations.
@@ -143,11 +201,11 @@
The centroid with the most points allocated to it should be the
most predominant color. (This is another interactive 3D scatterplot.)
-image:https://blogs.apache.org/groovy/mediaresource/f6bf5f7e-f384-4316-a1da-f8ec62ebae47[RgbPeach3d]
+image:img/rgb_peach3d.png[RgbPeach3d]
We can plot the number of points allocated to each cluster as a
bar chart. (We used a https://github.com/alexarchambault/plotly-scala[Scala plotting library]
to show Groovy integration with Scala.)
-image:https://blogs.apache.org/groovy/mediaresource/9bfd0a6e-85a8-4615-b0d7-f719a9459ad3[Peach colour centroid sizes]
+image:img/peach_centroid_sizes.png[Peach colour centroid sizes]
The code for drawing the above chart looks like this:
@@ -265,12 +323,12 @@
Here are the resulting images:
-image:https://blogs.apache.org/groovy/mediaresource/442d7100-5023-43ce-a525-0db682fc7b60[peach images]
-image:https://blogs.apache.org/groovy/mediaresource/1fc50ff2-7881-4bd3-a8c7-a6283222d91d[banana images]
-image:https://blogs.apache.org/groovy/mediaresource/6b35338d-be4b-40a4-81dc-e317a68fbb1e[cherry images]
-image:https://blogs.apache.org/groovy/mediaresource/d3ff8625-d429-4c7c-bfcd-531df53a8256[orange images]
-image:https://blogs.apache.org/groovy/mediaresource/1f1b755a-7dcf-4c53-b930-07c3ef8f0a2f[grape images]
-image:https://blogs.apache.org/groovy/mediaresource/d166e557-2ba2-4058-9bde-fb8b682d4c4b[apple images]
+image:img/peach_images.png[peach images]
+image:img/banana_images.png[banana images]
+image:img/cherry_images.png[cherry images]
+image:img/orange_images.png[orange images]
+image:img/grape_images.png[grape images]
+image:img/apple_images.png[apple images]
And, here are the final results: