持久化 Guava Graph 的方法

Ways to persist Guava Graph

我正在使用来自 Google Guava in Version 21.0. It suits very well to my usecase without one aspect: Persistence. The graph seems to be in-memory only. The graph-classes does not implement Serializable, it was explained in this issue postscommon.graph

Google 描述 three models to store the topology。第三个选项是:

a separate data repository (for example, a database) stores the topology

但仅此而已。我没有在包中找到任何方法来应用单独的数据存储库。有什么办法吗?或者是使用 nodes()edges() 方法获取节点的 Set 和边缘的 Set 的唯一方法?如果我在此 类 中实现 Serializable 并通过调用 addNode(Node)addEdge(Source, Target, Edge) 恢复图表(没有 addAll 方法),我可以将它们保存在数据库中。但这似乎是一种解决方法。

感谢您的支持!

简要回顾一下 Guava 的 common.graph 类 不是 Serializable 的原因:Java 序列化是脆弱的,因为它取决于实现的细节,并且可以随时更改,因此我们不支持图形类型。

短期内,您建议的解决方法可能是最好的选择,但您需要小心地将边的端点(源和目标)与边对象一起存储,以便您能够按照您的描述重建图表。事实上,从长远来看,这也可能对你有用,如果你有一个你满意的数据库并且你不需要担心与其他任何人的互操作。

正如我在 GitHub issue, another option is to persist your graph to some kind of file format. (Guava itself does not provide a mechanism for doing this, but JUNG 中提到的那样,一旦我可以得到 3.0 就可以得到 common.graph 图表,我仍在努力。)请注意,大多数图表文件格式(至少我熟悉的那些)对存储节点和边缘元数据的支持相当有限,因此您可能需要自己的文件格式(例如,基于协议缓冲区的格式)。

我发现存储图形的一种方法是通过 DOT format,如下所示:

public class DOTWriter<INode, IEdge> {

    public static String write(final Graph graph) {
        StringBuilder sb = new StringBuilder();
        sb.append("strict digraph G {\n");

        for(INode n : graph.nodes()) {
            sb.append("  \"" + n.getId() + "\n");
        }

        for(IEdge e : graph.edges()) {
            sb.append("  \"" + e.getSource().getId() + "\" -> \"" + e.getTarget().getId() + "\" " + "\n");
        }

        sb.append("}");
        return sb.toString();
    }
}

这会产生类似

的东西
strict digraph G {
    node_A;
    node_B;
    node_A -> node_B;
}

阅读本文并在内存中再次构建图形非常容易。

如果您的节点是复杂的对象,您应该单独存储它们。

根据@Maria Ines Parnisari 的精彩回答,我做了一些修改。然后用mermaid(一个markdown插件)画图,在Idea中得到了这样清晰的图像(>=2021.2,支持markdown更好)!

代码

        //noinspection UnstableApiUsage
        MutableGraph<String> graph = GraphBuilder.directed()
                .allowsSelfLoops(false)
                .build();

        //noinspection UnstableApiUsage
        graph.addNode("root");
        graph.putEdge("root", "s1_1");
        graph.putEdge("root", "s1_2");
        graph.putEdge("root", "s1_3");
        graph.putEdge("s1_2", "s2");
        graph.putEdge("s2", "s3");
        graph.putEdge("s3", "s4");
        graph.putEdge("s3", "s5");
        graph.putEdge("s4", "s6");
        graph.putEdge("s5", "s6");
        graph.putEdge("s1_1", "s6");
        graph.putEdge("s1_1", "s2");

        // print mermaid text , then copy it
        StringBuilder sb = new StringBuilder();
        for (EndpointPair<String> edge : graph.edges()) {
            // shoudle be `-->` to draw with mermaid
            sb.append(edge.nodeU() + " --> " + edge.nodeV() + "\n");
        }
        System.out.println(sb);

sorry As < 10 repution, i can't copy image directly that image will be hidden