CLOVER🍀

That was when it all began.

HazelcastのGetting Startedを、Scala、Groovy、Clojureで書き直してみた

Hazelcastの開発者の方と、Java上の多言語の話をしていて、なんとなくHazelcastのGetting Startedを他の言語で書き直してみたくなりまして。

Getting Started Tutorial
http://www.hazelcast.org/getting-started/

Java

ほぼ、オフィシャルと同じ。クラス名とimportを変えたくらい。
*クラス名は、結果として変わっただけですが。

pom.xmlの定義は、省略しています。

src/main/java/HazelcastGettingStarted.java

// Execution Command: $ mvn compile exec:java -Dexec.mainClass=HazelcastGettingStarted

import java.util.Map;
import java.util.Queue;

import com.hazelcast.config.Config;
import com.hazelcast.core.Hazelcast;
import com.hazelcast.core.HazelcastInstance;

public class HazelcastGettingStarted {
    public static void main(String... args) {
        Config cfg = new Config();
        HazelcastInstance instance = Hazelcast.newHazelcastInstance(cfg);

        Map<Integer, String> mapCustomers = instance.getMap("customers");

        mapCustomers.put(1, "Joe");
        mapCustomers.put(2, "Ali");
        mapCustomers.put(3, "Avi");
 
        System.out.println("Customer with key 1: "+ mapCustomers.get(1));
        System.out.println("Map Size:" + mapCustomers.size());

        Queue<String> queueCustomers = instance.getQueue("customers");
        
        queueCustomers.offer("Tom");
        queueCustomers.offer("Mary");
        queueCustomers.offer("Jane");

        System.out.println("First customer: " + queueCustomers.poll());
        System.out.println("Second customer: "+ queueCustomers.peek());
        System.out.println("Queue size: " + queueCustomers.size());

        instance.getLifecycleService().shutdown();
    }
}

そういえば本家の方は、HazelcastInstance#getLifecycleService#shutdownとかHazelcast#shutdownAllがないので、サンプルが終了しないんですよね。

Scala

最近は、HazelcastはScalaで書いていることが多いですね。

sbt利用ですが、build.sbtは省略しています。

src/main/scala/HazelcastGettingStarted.scala

// Execution Command: $ sbt run

import com.hazelcast.config.Config
import com.hazelcast.core.Hazelcast

object HazelcastGettingStarted {
  def main(args: Array[String]): Unit = {
    val cfg = new Config
    val instance = Hazelcast.newHazelcastInstance(cfg)

    val mapCustomers = instance.getMap[Int, String]("customers")

    for ((i, name) <- Array((1, "Joe"),
                            (2, "Ali"),
                            (3, "Avi"))) {
      mapCustomers.put(i, name)
    }

    println(s"Customer with key 1: ${mapCustomers.get(1)}")
    println(s"Map Size: ${mapCustomers.size}")


    val queueCustomers = instance.getQueue[String]("customers")

    Array("Tom", "Mary", "Jane").foreach(queueCustomers.offer)

    println(s"First Customer: ${queueCustomers.poll()}")
    println(s"Second Customer: ${queueCustomers.peek}")
    println(s"Queue size: ${queueCustomers.size}")

    instance.getLifecycleService.shutdown()
  }
}

なぜか、for式とforeachを使いましたが。

依存関係とかJavaとの相互運用でハマらなければ、個人的には今はScalaが書きやすいです。

Groovy

初めて、GroovyでHazelcastを使ってみました。

こちらは、Grapeを使用したのでgroovyコマンドとスクリプト単体で実行できます。

hazelcast-getting-started.groovy

// Execution Command: $ groovy hazelcast-getting-started.groovy

@Grab('com.hazelcast:hazelcast:3.2')
import com.hazelcast.config.Config
import com.hazelcast.core.Hazelcast

def cfg = new Config()
def instance = Hazelcast.newHazelcastInstance(cfg)

def mapCustomers = instance.getMap("customers")

[[1, "Joe"], [2, "Ali"], [3, "Avi"]].each { i, name ->
    mapCustomers.put(i, name)
}

println("Customer with key 1: ${mapCustomers.get(1)}")
println("Map Size: ${mapCustomers.size()}")

def queueCustomers = instance.getQueue("customers")
["Tom", "Mary", "Jane"].each { queueCustomers.offer(it) }

println("First Customer: ${queueCustomers.poll()}")
println("Second Customer: ${queueCustomers.peek()}")
println("Queue size: ${queueCustomers.size()}")

instance.lifecycleService.shutdown()

Javaから移るなら、最初の敷居としてはGroovyはかなり低いと思うのですが。

今の自分の使い方だと、コード量が増えてきたらScalaで書きたいです。

Clojure

最初にHazelcastを使い始めた頃は、勉強を兼ねてずっとClojureで書いていました。

が、リスナーとか増えてきた時に、Classベースのライブラリとはやっぱり相性悪めで、だんだんつらくなっていったのでScalaに今は移行しています。

もうちょっと関数指向に使えると、Clojureでも取り回しやすくなると思いますが、それはHazelcastに限った話ではありません。

スクリプトは、Leiningen+lein-execプラグインを使用することで、スクリプトのみで実行することができます。

hazelcast-getting-started.clj

;; Execution Command: $ lein exec hazelcast-getting-started.clj

(require '[leiningen.exec :as exec])

(exec/deps '[[com.hazelcast/hazelcast "3.2"]])

(import '(com.hazelcast.config Config)
        '(com.hazelcast.core Hazelcast))

(let [cfg (Config.)
      instance (Hazelcast/newHazelcastInstance cfg)]

  (let [map-customers (. instance getMap "customers")]
    (doseq [[i name] '([1 "Joe"] [2 "Ali"] [3 "Avi"])]
      (. map-customers put i name))
    (println (str "Customer with key 1: " (. map-customers get 1)))
    (println (str "Map Size: " (. map-customers size))))

  (let [queue-customers (. instance getQueue "customers")]
    (doseq [name ["Tom" "Mary" "Jane"]]
      (. queue-customers offer name))
    (println (str "First customer: " (. queue-customers poll)))
    (println (str "Second customer: " (. queue-customers peek)))
    (println (str "Queue size: " (. queue-customers size))))

  (.. instance getLifecycleService shutdown))

やるなら、どれがいいでしょうね。

今回書いたコードは、こちらにアップしています。

https://github.com/kazuhira-r/hazelcast-examples/tree/master/hazelcast-getting-started-eachlanguage