前回 は、JGraphT というグラフ理論のライブラリを Gradle プロジェクトで実行して、GraphViz で可視化するところまでやりました。
今回は、前回の補足として、サンプルソースの解説と、可視化のソースを完成させようと思います。
それではやっていきます!
- 参考文献
- はじめに
- HelloJGraphT.javaの説明
- dotファイルを出力するようにHelloJGraphT.javaを変更する
- ついでにdotファイルからPNG画像を出力するようにHelloJGraphT.javaを変更する
- おわりに
参考文献
はじめに
「Javaでデザインパターンを学ぶ」の記事一覧です。良かったら参考にしてください。
・第1回:Javaでデザインパターンを学ぶ:Singletonパターン
・第2回:Javaでデザインパターンを学ぶ:Template Methodパターン
・第3回:Javaでデザインパターンを学ぶ:Observerパターン
・第4回:Javaでデザインパターンを学ぶ:Iteratorパターン
・第5回:Javaでデザインパターンを学ぶ:Factory Methodパターン
・第6回:Javaでデザインパターンを学ぶ:Stateパターン
・第7回:Javaでデザインパターンを学ぶ:Visitorパターン
・第8回:Javaでデザインパターンを学ぶ:Adapterパターン
・第9回:Javaでデザインパターンを学ぶ:Prototypeパターン
・番外編:Javaのコンパイル方法(仕組み)をパッケージ含めていろいろ試してみる
・番外編2:Jarの作り方とJarを含んだコンパイル方法をパッケージ含めていろいろ試してみる
・番外編3:GradleでJavaプロジェクトを作ってみる(Ubuntu22.04)
・番外編4:IntelliJを使ってJavaのGradleプロジェクトでデバッグしてみる(Ubuntu22.04)
・番外編5:GradleプロジェクトでJGraphTを使う(Ubuntu22.04)
・番外編6:JGraphTのサンプルソースの解説と可視化の補足(Ubuntu22.04、IntelliJ、Gradle) ← 今回
JGraphT の公式サイトは以下です。
それではやっていきます!
HelloJGraphT.javaの説明
簡単に HelloJGraphT.java のメインの内容を説明しておきます。
HelloJGraphT クラスの先頭です。
final なので、HelloJGraphT クラスを派生させることは出来ません。
また、コンストラクタを private にすることでインスタンス化を防ぎ、クラスメソッドだけを使うようにしています。
public final class HelloJGraphT { private HelloJGraphT() { } // ensure non-instantiability.
クラスメソッドとして、main メソッドの定義です。
最初は、String と DefaultEdge の Graph を作るメソッドの createStringGraph() を実行しています。
DefaultEdge は、名前の通り、特別な用途が必要ないときのデフォルトのエッジ(辺)です。
public static void main(String[] args) throws URISyntaxException, ExportException { Graph<String, DefaultEdge> stringGraph = createStringGraph(); // note undirected edges are printed as: {<v1>,<v2>} System.out.println("-- toString output"); System.out.println(stringGraph.toString()); System.out.println();
次は、URI と DefaultEdge の Graph を作るメソッドの createHrefGraph() を実行しています。
URI(Uniform Resource Indentifier)クラスは、Java に用意されているクラスで、URL と同じくアドレスを扱うクラスです。
その後は難しいですが、次に使うので、ノード(頂点)から "www.jgrapht.org" を検索しています。
// create a graph based on URI objects Graph<URI, DefaultEdge> hrefGraph = createHrefGraph(); // find the vertex corresponding to www.jgrapht.org URI start = hrefGraph .vertexSet().stream().filter(uri -> uri.getHost().equals("www.jgrapht.org")).findAny() .get();
メインの最後です。
先ほど検索したノードを起点として、グラフを深さ優先順に走査して、頂点を出力します。
最後は、前回から使っている可視化のメソッドを実行していまうs。
// perform a graph traversal starting from that vertex System.out.println("-- traverseHrefGraph output"); traverseHrefGraph(hrefGraph, start); System.out.println(); System.out.println("-- renderHrefGraph output"); renderHrefGraph(hrefGraph); System.out.println();
dotファイルを出力するようにHelloJGraphT.javaを変更する
前回 は、標準出力の DOT 形式の内容をファイルに貼り付けて、GraphViz で画像ファイルを作りました。
今回は、HelloJGraphT.java を変更して、DOT ファイルを出力するようにしたいと思います。
HelloJGraphT.java の DOT 形式の内容を作っているのは以下の部分です。
Write として、StringWrite クラスを使っています。
/** * Render a graph in DOT format. * * @param hrefGraph a graph based on URI objects */ private static void renderHrefGraph(Graph<URI, DefaultEdge> hrefGraph) throws ExportException { DOTExporter<URI, DefaultEdge> exporter = new DOTExporter<>(v -> v.getHost().replace('.', '_')); exporter.setVertexAttributeProvider((v) -> { Map<String, Attribute> map = new LinkedHashMap<>(); map.put("label", DefaultAttribute.createAttribute(v.toString())); return map; }); Writer writer = new StringWriter(); exporter.exportGraph(hrefGraph, writer); System.out.println(writer.toString()); }
ファイル出力するには、StringWrite クラスを、FileWrite クラスに変更すればいいです。
//Writer writer = new StringWriter(); Writer writer = new FileWriter("HelloJGraphT.dot");
また、ファイル出力する場合は、try catch で囲う必要があります。
結果としては、以下のように変更しました。
private static void renderHrefGraph(Graph<URI, DefaultEdge> hrefGraph) throws ExportException { DOTExporter<URI, DefaultEdge> exporter = new DOTExporter<>(v -> v.getHost().replace('.', '_')); exporter.setVertexAttributeProvider((v) -> { Map<String, Attribute> map = new LinkedHashMap<>(); map.put("label", DefaultAttribute.createAttribute(v.toString())); return map; }); try { //Writer writer = new StringWriter(); Writer writer = new FileWriter("HelloJGraphT.dot"); exporter.exportGraph(hrefGraph, writer); //System.out.println(writer.toString()); } catch (IOException e) { e.printStackTrace(); } }
これを実行すると、プロジェクトのトップに、HelloJGraphT.dot が作られます。
あとは、前回 と同様に、GraphViz で、画像ファイルを作れば完成です。
$ dot -Tpng HelloJGraphT.dot -oHelloJGraphT.png
前回 と同じく、以下の画像ファイルが出力されます。

ついでにdotファイルからPNG画像を出力するようにHelloJGraphT.javaを変更する
さらに、Java を実行した後に、dot を実行するのは面倒なので、Java の中で、PNG ファイルを出力します。
ChatGPT に教えてもらいました。コマンドで実行するのと同じでいいようですね。
// Graphvizを使ってDOTファイルをPNGに変換 try { ProcessBuilder pb = new ProcessBuilder("dot", "-Tpng", "graph.dot", "-o", "graph.png"); pb.redirectErrorStream(true); Process process = pb.start(); process.waitFor(); } catch (IOException | InterruptedException e) { e.printStackTrace(); }
例外を複数まとめて記述する方法は初めて知りました。ChatGPT は本当に助かります。
最終的に、以下のようになりました。
private static void renderHrefGraph(Graph<URI, DefaultEdge> hrefGraph) throws ExportException { DOTExporter<URI, DefaultEdge> exporter = new DOTExporter<>(v -> v.getHost().replace('.', '_')); exporter.setVertexAttributeProvider((v) -> { Map<String, Attribute> map = new LinkedHashMap<>(); map.put("label", DefaultAttribute.createAttribute(v.toString())); return map; }); try { //Writer writer = new StringWriter(); Writer writer = new FileWriter("HelloJGraphT.dot"); exporter.exportGraph(hrefGraph, writer); //System.out.println(writer.toString()); ProcessBuilder pb = new ProcessBuilder("dot", "-Tpng", "HelloJGraphT.dot", "-o", "HelloJGraphT.png"); pb.redirectErrorStream(true); Process process = pb.start(); process.waitFor(); } catch (IOException | InterruptedException e) { e.printStackTrace(); } }
おわりに
今回は、前回、十分に書けてなかったところを補足しました。
最後になりましたが、エンジニアグループのランキングに参加中です。
気楽にポチッとよろしくお願いいたします🙇
今回は以上です!
最後までお読みいただき、ありがとうございました。