生成笛卡尔积Java

时间:2019-08-11 20:01:53

标签: java java-8 java-stream cartesian

我正在尝试对后端服务器进行负载测试,并将一些配置解析为Label对象。我正在尝试生成Label对象的笛卡尔积,该对象将是Metric对象。

Label {
   String name;
   String labe;
}

我有一个从yaml配置转换的List<List<Label>> labelList,需要通过笛卡尔积将其转换为List<Metric>。这是一个例子。

[[name: "office_instance"value: "office_instance_0", name: "office_instance"value: "office_instance_1", name: "office_instance"value: "office_instance_2", name: "office_instance"value: "office_instance_3"], [name: "office_type"value: "office_type_0", name: "office_type"value: "office_type_1", name: "office_type"value: "office_type_2", name: "office_type"value: "office_type_3"], [name: "resource_type"value: "resource_type_0", name: "resource_type"value: "resource_type_1", name: "resource_type"value: "resource_type_2", name: "resource_type"value: "resource_type_3"], [name: "resource"value: "resource_0", name: "resource"value: "resource_1", name: "resource"value: "resource_2", name: "resource"value: "resource_3"], [name: "resource_group_name"value: "resource_group_name_0", name: "resource_group_name"value: "resource_group_name_1", name: "resource_group_name"value: "resource_group_name_2", name: "resource_group_name"value: "resource_group_name_3"], [name: "scope"value: "scope_0", name: "scope"value: "scope_1", name: "scope"value: "scope_2", name: "scope"value: "scope_3"]]

由于这是从配置生成的,因此用于生成时间序列的代码必须是动态的。在此示例中,labelList的大小为5,每个列表列出4个标签。因此,度量对象的总数将为4 * 4 * 4 * 4 * 4。

度量对象的示例将

[[ name: "office_instance"value: "office_instance_0", name: "office_type"value: "office_type_0", name: "resource_type"value: "resource_type_0", name: "resource"value: "resource_0", name: "resource_group_name"value: "resource_group_name_0", name: "scope"value: "scope_0"][name: "office_instance"value: "office_instance_0", name: "office_type"value: "office_type_0", name: "resource_type"value: "resource_type_0", name: "resource"value: "resource_0", name: "resource_group_name"value: "resource_group_name_0", name: "scope"value: "scope_1"]......]

有两种方法可以生成度量标准:通过addLabels方法一次添加一个标签

 Metric.newBuilder().addLabels(Label obj).build()

或通过addAllLabels方法添加

 Metric.newBuilder().addAllLabels(List<Label> obj).build()

我尝试迭代/递归地执行此操作,但是它变得非常复杂且混乱。我检查了是否有java8替代方法。如果在第一遍之后我可以得到List<Label>Collection<Label>,则可以使用the addAlLabels方法创建Metric对象,并将其添加到最终列表中创建Metric对象并添加每个label

的过程

我在这里Cartesian product of streams in Java 8 as stream (using streams only)中提到了一些示例。但仍然无法弄清楚。任何帮助将不胜感激。

编辑:发现guava具有cartesianProduct Api,不确定其是否最优化可能会有帮助。

1 个答案:

答案 0 :(得分:1)

我认为您需要递归函数。 这是我想出的:

public class Cartesian {

    public static void main(String[] args) {
        List<List<Label>> labelList = Arrays.asList(//
                Arrays.asList( //
                        new Label("office_instance", "office_instance_0"), //
                        new Label("office_instance", "office_instance_1") //
                ), //
                Arrays.asList( //
                        new Label("office_type", "office_type_0"), //
                        new Label("office_type", "office_type_1") //
                ), //
                Arrays.asList( //
                        new Label("resource_type", "resource_type_0"), //
                        new Label("resource_type", "resource_type_1") //
                )//

        );
        List<List<Label>> result = generateCombinations(labelList);

        System.out.println(result);
    }

    private static List<List<Label>> generateCombinations(List<List<Label>> labels) {
        List<List<Label>> result = new ArrayList<>();
        // for each label in first list
        // generate combinations of labels from the rest of the list
        for (Label label : labels.get(0)) {
            if (labels.size() > 1) {
                for (List<Label> entry : generateCombinations(labels.subList(1, labels.size()))) {
                    entry.add(label);
                    result.add(entry);
                }
            } else {
                // base case
                result.add(new ArrayList<>(Arrays.asList(label)));
            }
        }
        return result;
    }

    private static class Label {
        String name;
        String label;

        Label(String name, String label) {
            this.name = name;
            this.label = label;
        }

        @Override
        public String toString() {
            return "(name: " + name + ", label: " + label + ")";
        }
    }
}

为简洁起见,我没有使用完整列表。

输出(手动格式化):

[
    [
        (name: resource_type, label: resource_type_0),
        (name: office_type, label: office_type_0),
        (name: office_instance, label: office_instance_0)
    ],
    [
        (name: resource_type, label: resource_type_1),
        (name: office_type, label: office_type_0),
        (name: office_instance, label: office_instance_0)
    ],
    [
        (name: resource_type, label: resource_type_0),
        (name: office_type, label: office_type_1),
        (name: office_instance, label: office_instance_0)
    ],
    [
        (name: resource_type, label: resource_type_1),
        (name: office_type, label: office_type_1),
        (name: office_instance, label: office_instance_0)
    ],
    [
        (name: resource_type, label: resource_type_0),
        (name: office_type, label: office_type_0),
        (name: office_instance, label: office_instance_1)
    ],
    [
        (name: resource_type, label: resource_type_1),
        (name: office_type, label: office_type_0),
        (name: office_instance, label: office_instance_1)
    ],
    [
        (name: resource_type, label: resource_type_0),
        (name: office_type, label: office_type_1),
        (name: office_instance, label: office_instance_1)
    ],
    [
        (name: resource_type, label: resource_type_1),
        (name: office_type, label: office_type_1),
        (name: office_instance, label: office_instance_1)
    ]
]