将 Gremlin Groovy 转换为 Gremlin Java 应该不是很困难。我总是反对这样做:
- 大大增加代码的大小
- 降低代码的可读性
- 让你的代码更难维护
如果您在一个不会听说过外部编程语言的“Java 商店”工作,我认为仅通过几个 Gremlin 在 groovy 和 java 中的差异示例(易于阅读一个衬里与可能是数百行代码的内容)。此外,Groovy 可以与 java 一起放入标准 Maven 项目中的同一模块中,也可以放入其他项目所依赖的单独独立模块中。在大多数情况下,我更喜欢后者,因为您将 groovy 隔离在一个包中,并且可以在多个用例中作为 DSL 重用(例如,应用程序、gremlin 控制台中的附加库等)。
也就是说,如果您仍然必须使用 Java,我仍然会从编写 Groovy 开始。使用 Gremlin 控制台并正确设置遍历算法。听起来好像您的两个用例都涉及循环,所以我们只会说您的遍历看起来像:
g.v(1).out.loop(1){true}{it.object.someProperty=="emitIfThis"}
所以这将从顶点“1”遍历链,直到我用完链,在第一个闭包中用“true”表示,然后在第二个闭包中发出符合我的标准的任何顶点。一旦定义并测试了这么多 Gremlin,就该转换为 Java。
如您所知,以 a 开头,GremlinPipeline
第一部分很容易用于转换目的:
new GremlinPipeline(g.getVertex(1)).out()
如您所见,Groovy 方法几乎可以相当干净地映射到 Java,直到您需要闭包并且loop
是需要闭包的步骤之一。要使用Gremlin Java,您可能会发现查看GremlinPipeline
.
我使用了三个参数版本loop
- 一个标记为“已弃用”的版本(但这对于我们的目的来说是可以的) - 你可以在这里看到它。第一个参数很简单 - 一个整数,所以翻译的第一部分是:
new GremlinPipeline(g.getVertex(1)).out().loop(1, closure, closure)
我已经为我们拥有的另外两个闭包留下了占位符。如果你这样看,它与我们的 Groovy 版本并没有太大区别——语法略有不同。
在 Java 8 之前,Java 语言中没有内置闭包的概念。请注意,在TinkerPop3中,Gremlin 发生了巨大变化,以利用我们现在拥有 lambda 的事实。但是当你在 TinkerPop2 中时,你必须使用内置的,PipeFunction
它基本上代表了我们 groovy 闭包的类型化版本。循环的PipeFunction
两个参数是:
PipeFunction<LoopPipe.LoopBundle<E>,Boolean>
所以基本上,这是一个将 aLoopPipe.LoopBundle
作为对象的函数,其中包含有关循环的元数据,并期望您返回一个布尔值。如果你理解了这个概念,那么所有 Gremlin Java 都会为你打开,因为你在任何地方看到一个 groovy 闭包,你就知道它下面只是PipeFunction
java 中的某种形式,并且你现在可以PipeFunction
从javadocs,做这些语言翻译应该很简单。
我们要做的第一个闭包翻译很简单——我们只需要我们PipeFunction
的 return true
:
new GremlinPipeline(g.getVertex(1)).out().loop(1,
new PipeFunction<LoopPipe.LoopBundle<Vertex>,Boolean>() {
public Boolean compute(LoopPipe.LoopBundle<Vertex> argument) {
return true;
}
}, closure)
因此,对于第二个参数,loop
我们必须构造一个 new PipeFunction
,它有一个名为 的方法compute
。从那个方法我们返回true
。现在处理PipeFunction
控制要发射的顶点的第二个参数:
new GremlinPipeline(g.getVertex(1)).out().loop(1,
new PipeFunction<LoopPipe.LoopBundle<Vertex>,Boolean>() {
public Boolean compute(LoopPipe.LoopBundle<Vertex> argument) {
return true;
}
},
new PipeFunction<LoopPipe.LoopBundle<Vertex>,Boolean>() {
public Boolean compute(LoopPipe.LoopBundle<Vertex> argument) {
return argument.getObject().getProperty("someProperty").equals("emitIfThis");
}
})
这就是转换。由于这是一篇很长的文章,让我们将原始的 groovy 放在更靠近上面的地方,以便清楚区别:
g.v(1).out.loop(1){true}{it.object.someProperty=="emitIfThis"}
我们从上面的一行代码变成了近十几个原本非常简单的遍历。Gremlin Java 在 TinkerPop3 中得到了它自己的 lambdas 和对语言本身的大修,但是当 Groovy 可以使事情变得非常整洁时,这些以前的版本产生的 Java 代码真的不值得努力生成或维护。