有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java Clojure和HBase:在扫描上懒洋洋地迭代

假设我想在clojure中打印hbase表扫描的输出

(defmulti scan (fn [table & args] (map class args)))

(defmethod scan [java.lang.String java.lang.String] [table start-key end-key]
    (let [scan (Scan. (Bytes/toBytes start-key) (Bytes/toBytes end-key))]
        (let [scanner (.getScanner table scan)]
            (doseq [result scanner]
                (prn
                    (Bytes/toString (.getRow result))
                    (get-to-map result))))))

在何处获取地图将结果转换为地图。它可以这样运行:

(hbase.table/scan table "key000001" "key999999")

但是如果我想让用户对扫描结果做些什么呢?我可以允许他们将一个函数作为回调传递给每个结果。但我的问题是:如果我希望用户能够懒洋洋地迭代每个结果,我将返回什么

(Bytes/toString (.getRow result))
(get-to-map result)

没有保留之前的结果,这可能会发生在使用lazy seq的简单化实现中


共 (1) 个答案

  1. # 1 楼答案

    如果接受回调参数,可以在doseq内调用它:

    (defmulti scan [f table & args] (mapv class args)) ; mapv returns vector
    
    (defmethod scan [String String] [f table start-key end-key]
                   ; ^- java.lang classes are imported implicitly
      (let [scan ...
            scanner ...] ; no need for two separate lets
        (doseq [result scanner]
          ; call f here, e.g.
          (f result))))
    

    这里f将在每个结果中调用一次。它的返回值以及结果本身将立即被丢弃。当然,您可以使用一些预处理版本的result调用f,例如(f (foo result) (bar result))

    您还可以将结果的序列/向量返回给客户机,并让其自行处理。如果序列是惰性的,则需要确保支持它的任何资源在处理期间保持打开状态(假设它们稍后会关闭,请参见with-open;处理代码需要在with-open内执行,并在返回时完成处理)

    例如,要将预处理结果的向量返回给客户端,可以执行以下操作:

    (defmethod scan ...
      (let [...]
        (mapv (fn preprocess-result [result]
                (result->map result))
              scanner)))
    

    然后客户可以对他们做任何想做的事。使用map返回惰性序列。如果客户端需要打开/关闭一个资源,您可以接受它作为扫描的参数,这样客户端就可以说:

    (with-open [r (some-resource)]
      ; or mapv, dorun+map, doall+for, ...
      (doseq [result (scan r ...)]
        (do-stuff-with result)))