我应该如何在 Java 中表示依赖图?

2024-03-19

我正在编写一些 JavaScript 依赖管理代码,并且我认为有人已经解决了 Java 中的依赖图问题。

我的第一次尝试是在 JSResource 对象上实现比较,但是当存在多个没有依赖性的叶节点时,它会失败,因此没有合理的顺序,除非受到其依赖项的影响。

所以我想我需要一个图表,然后需要一种迭代该图表的方法。这不是一个不可能的问题,但我想在重新发明轮子之前我应该​​在这里发帖。

干杯, 皮特


我发布了一些内容可能可以回答您的问题。链接在这里:http://nicolaecaralicea.blogspot.com/2010/11/dependency-graphs-generic-approach-in.html http://nicolaecaralicea.blogspot.com/2010/11/dependency-graphs-generic-approach-in.html

这是代码:



    package org.madeforall.graph.test;

import java.util.ArrayList;
import java.util.List;

import org.madeforall.graph.Graph;
import org.madeforall.graph.NodeValueListener;

public class TestDependecyGraph {
    public static void main(String[] args) {
        testWithGenericInt();
        testWithGenericString();
    }

    public static void testWithGenericInt() {
        final List<Integer> nodeValueList = new ArrayList<Integer>();
        Graph<Integer> graph = new Graph<Integer>(new NodeValueListener<Integer>() {
            public void evaluating(Integer nodeValue) {
                nodeValueList.add(nodeValue);
            }
        });
        graph.addDependency(1, 2);
        graph.addDependency(1, 3);
        graph.addDependency(3, 4);
        graph.addDependency(3, 5);
        graph.addDependency(5, 8);
        graph.addDependency(2, 7);
        graph.addDependency(2, 9);
        graph.addDependency(2, 8);
        graph.addDependency(9, 10);
        graph.generateDependencies();

        System.out.println(nodeValueList);

    }

    public static void testWithGenericString() {
        final List<String> nodeValueList = new ArrayList<String>();
        Graph<String> graph = new Graph<String>(new NodeValueListener<String>() {
            public void evaluating(String nodeValue) {
                nodeValueList.add(nodeValue);
            }
        });
        graph.addDependency("a", "b");
        graph.addDependency("a", "c");
        graph.addDependency("a", "f");
        graph.addDependency("c", "d");
        graph.addDependency("d", "g");
        graph.addDependency("f", "d");
        graph.addDependency("h", "e");
        graph.generateDependencies();
        System.out.println(nodeValueList);

    }
}

The first and the second argument of the addDependency method of the Graph class are some two arbitrarily chosen nodes of the oriented graph. Watch out for circular dependencies, because I did not take care of them yet.


Here are the classes. 

package org.madeforall.graph;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Set;

/**
 *
 * Represents a graph of nodes. Every node is of GraphNode type and it has set a
 * value of the generic type <T>. It basically derives an evaluation order out
 * of its nodes. A node gets the chance to be evaluated when all the incoming
 * nodes were previously evaluated. The evaluating method of the
 * NodeValueListener is used to notify the outside of the fact that a node just
 * got the chance to be evaluated. A value of the node that is of the generic
 * type <T> is passed as argument to the evaluating method.
 *
 *
 * @author nicolae caralicea
 *
 * @param <T>
 */
final public class Graph<T> {
    /**
     * These are basically the nodes of the graph
     */
    private HashMap<T, GraphNode<T>> nodes = new HashMap<T, GraphNode<T>>();
    /**
     * The callback interface used to notify of the fact that a node just got
     * the evaluation
     */
    private NodeValueListener<T> listener;
    /**
     * It holds a list of the already evaluated nodes
     */
    private List<GraphNode<T>> evaluatedNodes = new ArrayList<GraphNode<T>>();

    /**
     * The main constructor that has one parameter representing the callback
     * mechanism used by this class to notify when a node gets the evaluation.
     *
     * @param listener
     *            The callback interface implemented by the user classes
     */
    public Graph(NodeValueListener<T> listener) {
        this.listener = listener;
    }

    /**
     * Allows adding of new dependicies to the graph. "evalFirstValue" needs to
     * be evaluated before "evalAfterValue"
     *
     * @param evalFirstValue
     *            The parameter that needs to be evaluated first
     * @param evalAfterValue
     *            The parameter that needs to be evaluated after
     */
    public void addDependency(T evalFirstValue, T evalAfterValue) {
        GraphNode<T> firstNode = null;
        GraphNode<T> afterNode = null;
        if (nodes.containsKey(evalFirstValue)) {
            firstNode = nodes.get(evalFirstValue);
        } else {
            firstNode = createNode(evalFirstValue);
            nodes.put(evalFirstValue, firstNode);
        }
        if (nodes.containsKey(evalAfterValue)) {
            afterNode = nodes.get(evalAfterValue);
        } else {
            afterNode = createNode(evalAfterValue);
            nodes.put(evalAfterValue, afterNode);
        }
        firstNode.addGoingOutNode(afterNode);
        afterNode.addComingInNode(firstNode);
    }

    /**
     * Creates a graph node of the <T> generic type
     *
     * @param value
     *            The value that is hosted by the node
     * @return a generic GraphNode object
     */
    private GraphNode<T> createNode(T value) {
        GraphNode<T> node = new GraphNode<T>();
        node.value = value;
        return node;
    }

    /**
     *
     * Takes all the nodes and calculates the dependency order for them.
     *
     */
    public void generateDependencies() {
        List<GraphNode<T>> orphanNodes = getOrphanNodes();
        List<GraphNode<T>> nextNodesToDisplay = new ArrayList<GraphNode<T>>();
        for (GraphNode<T> node : orphanNodes) {
            listener.evaluating(node.value);
            evaluatedNodes.add(node);
            nextNodesToDisplay.addAll(node.getGoingOutNodes());
        }
        generateDependencies(nextNodesToDisplay);
    }

    /**
     * Generates the dependency order of the nodes passed in as parameter
     *
     * @param nodes
     *            The nodes for which the dependency order order is executed
     */
    private void generateDependencies(List<GraphNode<T>> nodes) {
        List<GraphNode<T>> nextNodesToDisplay = null;
        for (GraphNode<T> node : nodes) {
            if (!isAlreadyEvaluated(node)) {
                List<GraphNode<T>> comingInNodes = node.getComingInNodes();
                if (areAlreadyEvaluated(comingInNodes)) {
                    listener.evaluating(node.value);
                    evaluatedNodes.add(node);
                    List<GraphNode<T>> goingOutNodes = node.getGoingOutNodes();
                    if (goingOutNodes != null) {
                        if (nextNodesToDisplay == null)
                            nextNodesToDisplay = new ArrayList<GraphNode<T>>();
                        // add these too, so they get a chance to be displayed
                        // as well
                        nextNodesToDisplay.addAll(goingOutNodes);
                    }
                } else {
                    if (nextNodesToDisplay == null)
                        nextNodesToDisplay = new ArrayList<GraphNode<T>>();
                    // the checked node should be carried
                    nextNodesToDisplay.add(node);
                }
            }
        }
        if (nextNodesToDisplay != null) {
            generateDependencies(nextNodesToDisplay);
        }
        // here the recursive call ends
    }

    /**
     * Checks to see if the passed in node was aready evaluated A node defined
     * as already evaluated means that its incoming nodes were already evaluated
     * as well
     *
     * @param node
     *            The Node to be checked
     * @return The return value represents the node evaluation status
     */
    private boolean isAlreadyEvaluated(GraphNode<T> node) {
        return evaluatedNodes.contains(node);
    }

    /**
     * Check to see if all the passed nodes were already evaluated. This could
     * be thought as an and logic between every node evaluation status
     *
     * @param nodes
     *            The nodes to be checked
     * @return The return value represents the evaluation status for all the
     *         nodes
     */
    private boolean areAlreadyEvaluated(List<GraphNode<T>> nodes) {
        return evaluatedNodes.containsAll(nodes);
    }

    /**
     *
     * These nodes represent the starting nodes. They are firstly evaluated.
     * They have no incoming nodes. The order they are evaluated does not
     * matter.
     *
     * @return It returns a list of graph nodes
     */
    private List<GraphNode<T>> getOrphanNodes() {
        List<GraphNode<T>> orphanNodes = null;
        Set<T> keys = nodes.keySet();
        for (T key : keys) {
            GraphNode<T> node = nodes.get(key);
            if (node.getComingInNodes() == null) {
                if (orphanNodes == null)
                    orphanNodes = new ArrayList<GraphNode<T>>();
                orphanNodes.add(node);
            }
        }
        return orphanNodes;
    }
}

package org.madeforall.graph;

import java.util.ArrayList;
import java.util.List;

/**
 *
 * It represents the node of the graph. It holds a user value that is passed
 * back to the user when a node gets the chance to be evaluated.
 *
 * @author nicolae caralicea
 *
 * @param <T>
 */
final class GraphNode<T> {
    public T value;
    private List<GraphNode<T>> comingInNodes;
    private List<GraphNode<T>> goingOutNodes;

    /**
     * Adds an incoming node to the current node
     *
     * @param node
     *            The incoming node
     */
    public void addComingInNode(GraphNode<T> node) {
        if (comingInNodes == null)
            comingInNodes = new ArrayList<GraphNode<T>>();
        comingInNodes.add(node);
    }

    /**
     * Adds an outgoing node from the current node
     *
     * @param node
     *            The outgoing node
     */
    public void addGoingOutNode(GraphNode<T> node) {
        if (goingOutNodes == null)
            goingOutNodes = new ArrayList<GraphNode<T>>();
        goingOutNodes.add(node);
    }

    /**
     * Provides all the coming in nodes
     *
     * @return The coming in nodes
     */
    public List<GraphNode<T>> getComingInNodes() {
        return comingInNodes;
    }

    /**
     * Provides all the going out nodes
     *
     * @return The going out nodes
     */
    public List<GraphNode<T>> getGoingOutNodes() {
        return goingOutNodes;
    }
}


package org.madeforall.graph;

/**
 * The main mechanism used for notifying the outside of the fact that a node
 * just got its evaluation
 *
 * @author nicolae caralicea
 *
 * @param <T>
 */
public interface NodeValueListener<T> {
    /**
     *
     * The callback method used to notify the fact that a node that has assigned
     * the nodeValue value just got its evaluation
     *
     * @param nodeValue
     *            The user set value of the node that just got the evaluation
     */
    void evaluating(T nodeValue);
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

我应该如何在 Java 中表示依赖图? 的相关文章

  • 策略模式还是命令模式?

    假设我有一个金融交易列表 我需要针对这些交易执行一系列验证规则 一个例子是我有一笔购买产品的交易 但是首先我需要验证交易中的帐户是否有足够的可用资金 产品没有售完等 由于这些规则 交易将是标记为拒绝 并应指定错误代码 当然 我正在考虑用一个
  • 将构造函数作为参数传递给方法

    我是java新手 开始研究构造函数 我看到一些构造函数作为参数传递给方法的示例 请告诉我当构造函数作为参数传递给方法时会发生什么 或者建议我一些链接 我可以在其中获得有关使用构造函数的足够知识 根据您需要传递构造函数的目的 您可以考虑传递供
  • 在 Java 正则表达式中获取多个模式的重叠匹配

    我有同样的问题这个链接 https stackoverflow com questions 18751486 matching one string multiple times using regex in java 但有多种模式 我的正
  • 使类只能从特定类实例化

    假设我有 3 节课class1 class2 and class3 我怎样才能拥有它class1只能通过实例化class2 class1 object new class1 但不是 class3 或任何其他类 我认为它应该与修饰符一起使用
  • 最快的高斯模糊实现

    如何以最快的速度实施高斯模糊 http en wikipedia org wiki Gaussian blur算法 我要用Java来实现它 所以GPU http en wikipedia org wiki Graphics processi
  • 迭代函数可以调用自身吗?

    当观看下面的 MIT 6 001 课程视频时 讲师在 28 00 将此算法标记为迭代 但是 在 30 27 他说这个算法和实际的 递归 算法都是递归的 该函数正在使用基本情况调用自身 那么这次迭代情况如何 private int itera
  • 记录共享和映射的诊断上下文

    据我所知 其他人做了什么来解决 Commons Logging 项目 针对 NET 和 Java 不支持映射或嵌套诊断上下文这一事实 执行摘要 我们选择直接使用实现者日志框架 在我们的例子中为 log4j 长答案 您是否需要一个抽象日志框架
  • 以有效的方式从 Map 中删除多个键?

    我有一个Map
  • 这个等待通知线程语义的真正目的是什么?

    我刚刚遇到一些代码 它使用等待通知构造通过其其他成员方法与类中定义的线程进行通信 有趣的是 获取锁后 同步范围内的所有线程都会在同一锁上进行定时等待 请参见下面的代码片段 随后 在非同步作用域中 线程执行其关键函数 即 做一些有用的事情1
  • 如何在 HandlerInterceptorAdapter 中添加 HttpServletRequest 标头?

    我正在尝试将授权标头添加到我的请求中 作为我们切换环境时的临时解决方法 我试图在扩展 HandlerInterceptorAdapter 的拦截器中处理它 我使用 MutableHttpServletRequest 类制作here http
  • 可访问数据的 Java 约定。 (公共访问器和 Getter/命名)

    通过 Java API 您会看到大量冲突的命名和实践 这让我感到非常困惑 例如 The String http grepcode com file repository grepcode com java root jdk openjdk
  • 无法在 Java 中输出正确的哈希值。怎么了?

    在我的 Android 应用程序中 我有一个 SHA256 哈希值 我必须使用 RIPEMD160 消息摘要算法进一步对其进行哈希值 我可以输出任何字符串的正确 sha256 和ripemd160 哈希值 但是当我尝试使用ripemd160
  • Java:SortedMap、TreeMap、可比较?如何使用?

    我有一个对象列表 需要根据其中一个字段的属性进行排序 我听说 SortedMap 和 Comparator 是实现此目的的最佳方法 我是否要与正在排序的类实现 Comparable 还是创建一个新类 如何实例化 SortedMap 并传入
  • 具有 JPA 持久性的 Spring 状态机 - 存储库使用

    我试图弄清楚如何轻松使用 Spring 状态机 包括使用 JPA 进行持久化 这是我正在处理的问题 不兼容的数据类型 工厂和持久性 在程序的某个时刻 我想使用连接到用户的状态机 有用于此目的的存储库 项目spring statemachin
  • 为什么无法从 WEB-INF 文件夹内加载 POSModel 文件?

    我在我的 Web 项目中使用 Spring MVC 我将模型文件放在 WEB INF 目录中 String taggerModelPath WEB INF lib en pos maxent bin String chunkerModelP
  • 如何从 JavaFX 中的另一个控制器类访问 UI 元素?

    我有一个使用 NetBeans 8 编写的 JavaFX Java 8 应用程序 没有SceneBuilder 我的应用程序有一个主窗口 该窗口有自己的 FXML 文件 primary fxml 和自己的控制器类 FXMLPrimaryCo
  • spring data jpa复合键重复键记录插入导致更新

    我有一个具有复合键的实体 我试图通过使用 spring data jpa 存储库到 mysql 数据库来持久化它 如下所示 Embeddable public class MobileVerificationKey implements S
  • 在实现使用原始类型的接口时如何避免警告?

    我正在实施流程工厂 http help eclipse org ganymede index jsp topic org eclipse platform doc isv reference api org eclipse debug co
  • 受信任的 1.5 小程序可以执行系统命令吗?

    如果是的话 这个能力有什么限制吗 具体来说 我需要以 Mac OSX 为目标 我以前用过这个在 Windows 系统上启动东西 但从未在 Mac 上尝试过 public void launchScript String args Strin
  • 如何建立与 FileZilla Server 1.2.0 的 FTPS 数据连接

    使用 Apache commons net 的 Java FTPSClient 进行会话恢复是一个已知问题 会话恢复是 FTPS 服务器数据连接所需的一项安全功能 Apache FTPSClient 不支持会话恢复 并且 JDK API 使

随机推荐

  • 如何 git add 仅匹配模式的行?

    我正在使用 git 跟踪一些配置文件 我通常会进行互动git add p但我正在寻找一种方法来自动添加与模式匹配的所有新 修改 删除行 否则 我将花费很长时间来完成所有交互式拆分和添加 git add有文件名的模式匹配 但我找不到有关内容的
  • MS ACCESS 与 LAN 上的桌面应用程序

    在不使用共享文件夹的情况下通过 LAN 托管 MS ACCESS 和桌面应用程序的最佳方式是什么 您可以使用一些终端服务器 TS 例如微软的终端服务器 这是 ms windows 操作系统服务器版本的一项功能 还有其他可用的 TS Citr
  • R - 以 1 为增量的循环函数

    我有以下功能 position tab lt filter Tall Time point 2 gt group by Object gt summarise minimum min Pixel pos maximum max Pixel
  • 子菜单的 javascript 悬停功能

    我在尝试理解 javascript 方面还很陌生 我一直在收集多个示例 试图找出我做错了什么 但无法让它正常工作 在某一时刻 我曾使用过 onmouseover mouseout 但它只适用于其中一个菜单 我确信这是我忽略的简单事情 但任何
  • 如何获取jqGrid当前的搜索条件?

    我需要获得与 jqGrid 在 GET POST search 参数上传递的完全相同的东西 我怎样才能做到这一点 为了结束这个问题 我做了以下几行 grid getGridParam postData filters 这样我就得到了当我们对
  • AngularJS 禁用 ngClick

    在 AngularJS 中 有什么办法可以制作一个ng click依赖于布尔值 例如 我希望以下文本 Click 可点击 但是only当某些范围属性 例如 rootScope enableClick is true div Click di
  • 从套接字读取时如何检测客户端何时完成发送请求?

    我现在正在编写一个 http 服务器 但从套接字读取时遇到问题 我的问题是inputStream来自客户端的数据永远不会结束 它会一直读取 直到客户端关闭 我知道客户端发送http请求后并不会立即关闭与服务器的连接 我怎样才能退出while
  • 是否可以更改请求方法来转发请求?

    我正在研究一个网关 它只允许 GET 请求 而其背后的 REST 端点能够接受各种方法 POST PUT DELETE OPTIONS 因此 我尝试将请求方法作为参数传递 并有一个过滤器 它用正确的方法转发请求 从我在规范中看到的 只允许转
  • 使用 YamlDotNet 序列化动态模型时更改用于所有多行字符串的标量样式

    我使用以下代码片段将项目的动态模型序列化为字符串 最终导出到 YAML 文件 dynamic exportModel exportModelConvertor ToDynamicModel project var serializerBui
  • 带有identified(by:)的SwiftUI列表初始值设定项

    我正在学习 Apple 的 SwiftUI 教程构建列表和导航 https developer apple com tutorials swiftui building lists and navigation make the list
  • 为什么你可以在 Java 和 .Net 中反射并调用一个(不那么)私有方法

    在 Java 和 C 中 都可以通过反射调用私有方法 如下所示 为什么这是允许的 这样做会产生什么后果 是否应该在该语言的未来版本中删除它 其他语言 平台是否允许这样做 如果我在 Java 和 C 中都有此类 这是例子 public cla
  • Python 中的 Youtube 数据 API nextPageToken 循环

    我根据在网上找到的许多不同示例将其拼凑在一起 目标是 在 youtube api 中搜索 将多个页面的搜索结果转换为 csv 文件 编辑 由于提供的答案之一 这是搜索循环的工作示例 现在按预期循环了最大次数 10 但是执行时的问题是CSV
  • 如何在 Rust 中迭代数组时更改数组内的值

    我想像评论中那样更改循环内的值 它应该很简单 但我没有看到解决方案 fn main let mut grid i32 10 10 5 10 10 for i row in grid iter mut enumerate for y col
  • 我尝试使用 htaccess 从 url 中删除文件夹/文件夹名称

    我想更改网址 My Url http localhost MotoMate corporate company kenstar http localhost MotoMate corporate company kenstar 我的目标网址
  • 在提交事务之前传送 JMS 消息

    我有一个非常简单的场景 涉及database and a JMS在应用程序服务器 Glassfish 中 场景非常简单 1 an EJB inserts a row in the database and sends a message 2
  • 使用 javascript/jquery 触发文件上传对话框

    而不是使用
  • java jstack工具内存不足或权限不足无法附加

    我真的很困惑 在我的windows 2008r2中 我有一个windows服务 实际上它是一个java进程 运行为SYSTEM用户 现在 我用Jstack原始的服务 但出现错误 insufficient memory or insuffic
  • 如何在 Firebase Analytics 中查看所有设备列表?

    在我们的应用程序中 我们使用 FCM 因此 Firebase 分析也可以正常工作 然而 从仪表板中 我们只能看到顶级设备 有没有办法查看有关设备的更多详细信息 所有型号 All OS 所有设备的区域 ETC 例如 我们想要验证某些用户是否在
  • 在客户端的 JavaScript 中访问 JPEG EXIF 旋转数据

    我想根据相机在 JPEG EXIF 图像数据中设置的原始旋转来旋转照片 诀窍在于 所有这一切都应该在浏览器中发生 使用 JavaScript 和
  • 我应该如何在 Java 中表示依赖图?

    我正在编写一些 JavaScript 依赖管理代码 并且我认为有人已经解决了 Java 中的依赖图问题 我的第一次尝试是在 JSResource 对象上实现比较 但是当存在多个没有依赖性的叶节点时 它会失败 因此没有合理的顺序 除非受到其依