流口水的禁忌之一包括手动遍历结果中的集合(then子句)。我需要写一个有效地在地图上迭代的口水,同时为该地图中的每个键值对做一些事情。换句话说,我需要在流口水中复制for-each循环的行为,而无需实际编写for-each循环。

现在,我意识到我可以在结果中编写一个for-each循环。我想让我的代码尽可能接近Drools-standard。我在下面提供了一个更具体的示例。

我有一张字符串和颜色的地图。

Map<String, Color> colorMap


对于地图中的每种颜色,我想检查一个不同的集合以找到该颜色的确切代码。

Map<Color, ColorCode> colorCodes


Java方言方法如下所示:

for (Map.Entry<String, Color> entry : colorMap.entrySet())
{
    ColorCode code = colorCodes.get(entry.getValue());

    thenconsequence.do(code);
}


用流口水方言怎么做类似的事情?

更新:
我对这个问题的思考越多,我就越应该担心在流口水的情况下不应该进行这种地图查找/迭代。正确的做法可能是将这些集合的事实对象表示形式插入工作内存中。例如,我可以将每种颜色都包装在colorFact中,其中将Color包裹起来,并在一个字段中指示颜色名称。与代码相同。然后,我可以按照以下方式写流口水:

when
Color(name=="blue", $c:color)
ColorCode(name == "blue", $code:colorCode)
then
  $code.printCode();
end


如果这是解决问题的最佳方法,那么我担心我要补充的事实之多。我已经有成千上万了。这将创造数万个。我不担心记忆。相反,我担心需要遍历所有这些集合并将它们的元素添加到工作内存中所需的时间。任何人都可以评论这是否是最好的方法,或者是否存在更好的方法?

最佳答案

尽管可以使用一组简单的Java语句来完成此操作,但是这是在单个规则中执行此操作的方法,并且插入等方面的开销最少(我认为):

rule "matchcolorcode"
when
    $cm: ColorMap()
    Map.Entry( $key: key, $color: value ) from $cm.entrySet()
    $ccm: ColorCodeMap( $ccm.containsKey($key) )
then
    System.out.println( $key + ": " + $color + ", " + $ccm.get($key) );
end


事实是HashMap的通用实例的简单包装器,例如:

class ColorMap extends HashMap<String,Color> {}

10-06 07:17