最新在看xwork的源代码,XmlConfigurationProvider这个类,用来实现解析xwork.xml配置文件。该类使用了有向图这种数据结构,来判断是否存在<include>元素的循环包含。
有向图的实现如下:
import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.NoSuchElementException; import java.util.Set; public final class DirectedGraph<T> implements Iterable<T> { private final Map<T, Set<T>> mGraph = new HashMap<T, Set<T>>(); /** * Adds a new node to the graph. If the node already exists, this function is a no-op. * * @param node * The node to add. * @return Whether or not the node was added. */ public boolean addNode(T node) { /* If the node already exists, don't do anything. */ if (mGraph.containsKey(node)) return false; /* Otherwise, add the node with an empty set of outgoing edges. */ mGraph.put(node, new HashSet<T>()); return true; } /** * Given a start node, and a destination, adds an arc from the start node to the destination. If an arc already exists, this operation is a no-op. * If either endpoint does not exist in the graph, throws a NoSuchElementException. * * @param start * The start node. * @param dest * The destination node. * @throws NoSuchElementException * If either the start or destination nodes do not exist. */ public void addEdge(T start, T dest) { /* Confirm both endpoints exist. */ if (!mGraph.containsKey(start)) { throw new NoSuchElementException("The start node does not exist in the graph."); } else if (!mGraph.containsKey(dest)) { throw new NoSuchElementException("The destination node does not exist in the graph."); } /* Add the edge. */ mGraph.get(start).add(dest); } /** * Removes the edge from start to dest from the graph. If the edge does not exist, this operation is a no-op. If either endpoint does not exist, * this throws a NoSuchElementException. * * @param start * The start node. * @param dest * The destination node. * @throws NoSuchElementException * If either node is not in the graph. */ public void removeEdge(T start, T dest) { /* Confirm both endpoints exist. */ if (!mGraph.containsKey(start)) { throw new NoSuchElementException("The start node does not exist in the graph."); } else if (!mGraph.containsKey(dest)) { throw new NoSuchElementException("The destination node does not exist in the graph."); } mGraph.get(start).remove(dest); } /** * Given two nodes in the graph, returns whether there is an edge from the first node to the second node. If either node does not exist in the * graph, throws a NoSuchElementException. * * @param start * The start node. * @param end * The destination node. * @return Whether there is an edge from start to end. * @throws NoSuchElementException * If either endpoint does not exist. */ public boolean edgeExists(T start, T end) { /* Confirm both endpoints exist. */ if (!mGraph.containsKey(start)) { throw new NoSuchElementException("The start node does not exist in the graph."); } else if (!mGraph.containsKey(end)) { throw new NoSuchElementException("The end node does not exist in the graph."); } return mGraph.get(start).contains(end); } /** * Given a node in the graph, returns an immutable view of the edges leaving that node as a set of endpoints. * * @param node * The node whose edges should be queried. * @return An immutable view of the edges leaving that node. * @throws NoSuchElementException * If the node does not exist. */ public Set<T> edgesFrom(T node) { /* Check that the node exists. */ Set<T> arcs = mGraph.get(node); if (arcs == null) throw new NoSuchElementException("Source node does not exist."); return Collections.unmodifiableSet(arcs); } /** * Returns an iterator that can traverse the nodes in the graph. * * @return An iterator that traverses the nodes in the graph. */ public Iterator<T> iterator() { return mGraph.keySet().iterator(); } /** * Returns the number of nodes in the graph. * * @return The number of nodes in the graph. */ public int size() { return mGraph.size(); } /** * Returns whether the graph is empty. * * @return Whether the graph is empty. */ public boolean isEmpty() { return mGraph.isEmpty(); } }
通过上述源码发现:xwork框架采用的是有向图的邻接表方法进行存储的。
xwork使用CycleDetector用来判断有向图是否存在循环,实现如下:
public class CycleDetector<T> { private static final String marked = "marked"; private static final String complete = "complete"; private DirectedGraph<T> graph; private Map<T, String> marks; private List<T> verticesInCycles; public CycleDetector(DirectedGraph<T> graph) { this.graph = graph; marks = new HashMap<T, String>(); verticesInCycles = new ArrayList<T>(); } public boolean containsCycle() { for (T v : graph) { // 如果v正在遍历或者遍历完成,不需要进入mark(),因为mark是一个递归调用,使用的是深度优先搜索算法; // 这是为了保证1个顶点只会遍历一次 if (!marks.containsKey(v)) { if (mark(v)) { // return true; } } } return !verticesInCycles.isEmpty(); } //DFS算法,遍历顶点vertex // @return 当前顶点是否在环上 private boolean mark(T vertex) { List<T> localCycles = new ArrayList<T>(); // 当前顶点vertex,遍历开始 marks.put(vertex, marked); for (T u : graph.edgesFrom(vertex)) { // u的遍历还没有结束,说明存在u->vertex的通路,也存在vertex->u的通路,形成了循环 if (marks.containsKey(u) && marks.get(u).equals(marked)) { localCycles.add(vertex); // return true; } else if (!marks.containsKey(u)) { if (mark(u)) { localCycles.add(vertex); // return true; } } } // 当前顶点vertex,遍历完成 marks.put(vertex, complete); verticesInCycles.addAll(localCycles); return !localCycles.isEmpty(); } public List<T> getVerticesInCycles() { return verticesInCycles; } }
相关推荐
1. **Java基础**:首先,我们需要了解Java的基本语法,包括变量声明、条件语句(如if-else)、循环结构(如for和while)、方法定义以及类的创建。这些是编写任何Java程序的基础。 2. **字符串操作**:在回文判断中...
强连通图是指有向图中任意两个顶点都相互可达的图。也就是说,如果存在一条从顶点A到顶点B的路径,同时也存在一条从顶点B回顶点A的路径,那么这两个顶点是强连通的。如果图中所有顶点都满足此条件,该图则被称为强...
- **实现思路**:使用循环遍历数组,对于每个数,检查是否存在另一个数满足条件。 #### 29. 二维数组对角线元素求和 - **题目解析**:对于一个3*3的矩阵,求对角线元素的和。 - **实现思路**:使用双重for循环,...
总结起来,这个Java程序通过深度优先搜索算法解决了无向图中环路检测的问题,利用了邻接表数据结构以及记录父节点的方法来判断是否存在环。这种方法简洁且直观,是图论和算法学习中的一个经典实例。
- 目标分类:`classify()`函数基于提取的特征对每个块进行分类,判断是否存在目标。 - 定位目标:`retrieveTargetRect()`函数根据分类结果确定目标位置,生成边界框矩形`Rect`。 3. **后处理**: - 结果合并:将...
6. **循环与判断**:在BFS搜索和猫咪移动的过程中,不断循环,直到游戏结束。在每次循环时,检查游戏状态,判断是否结束。 7. **用户交互**:为了增加游戏趣味性,可以添加用户交互功能,让用户决定下一步移动,...
通过上述步骤和代码示例,我们可以清晰地了解到如何使用Java实现文件下载功能。这种能力对于构建功能丰富的Web应用程序至关重要,尤其是在需要提供文档、图片、视频等多媒体资源下载的情况下。掌握这些技术细节,将...
- 使用循环和条件判断确保输入的数据符合拓扑排序的要求:不存在自环且没有重复的边。 ##### 4. 排序方法 sort 该方法实现了拓扑排序的核心逻辑: - 首先遍历所有的边并将它们添加到 `HashSet array` 中,以便去除...
在Java中实现俄罗斯方块,首先需要一个游戏循环来处理游戏的更新和渲染。游戏循环通常包括三个主要部分:更新(Update)、渲染(Render)和输入处理(Input Handling)。在Java中,我们可以使用JavaFX或Swing库创建...
在JAVA中实现Caesar加密算法,可以深入了解字符编码、字符串处理和循环结构等编程基础知识。 首先,我们需要了解Java的基础语法,包括类、对象和方法的定义。在Java中,我们可以创建一个名为`CaesarCipher`的类,...
AOV网(Activity On Vertex 网)是一种特殊的有向图,用于描述活动之间的相互关系。拓扑排序是AOV网中的一种基本操作,用于将网中的顶点排序,使得每个顶点的入度值为0。拓扑排序是一种非常重要的算法,它广泛应用于...
本项目"基于Java实现的圣诞树"旨在利用Java语言的特性,展示如何通过代码生成一个可视化的圣诞树图形,这通常是编程学习过程中的一个经典练习,用于提升对控制流、循环和字符串操作的理解。 在Java中,我们可以通过...
为了解决这个问题,我们通常会创建一个析取函数(First集合)和一个跟随函数(Follow集合),来帮助判断是否存在冲突。 First集合表示一个非终结符可以开始的所有可能的终结符序列。对于一个非终结符A,First(A)...
在Java中实现俄罗斯方块,首先需要理解游戏的基本逻辑和规则。以下是一些关键知识点: 1. **图形用户界面(GUI)**:Java提供了丰富的GUI库,如JavaFX和Swing,用于构建游戏界面。你可以使用这些库创建一个包含游戏...
HelloNativeTest.java 测试本地化是否成功的类文件 instanceVar.java 定义一个实例成员变量 invokeByObject.java 对象实参传递示例程序 invokeByValue.java 传值调用示例程序 invokeMethod.java 同一个类中调用...
其基本思想是对于有向图中的每条边 (u, v),确保顶点 u 在排序序列中位于顶点 v 之前。这种排序方式常被用于处理有先后顺序依赖的任务安排问题中,例如课程选修、项目依赖等场景。 #### 拓扑排序的实现步骤 拓扑...
Java实现的俄罗斯方块是一款经典的桌面游戏,它利用了编程语言的强大功能来模拟游戏的逻辑。在这个项目中,开发者使用Java编程语言,结合外部的多媒体库(可能是用于处理图形和声音),来创建了一个完整的可玩版本。...
6. **游戏逻辑**:五子棋的逻辑包括合法走法判断(不能在已有棋子的位置落子,不能走出棋盘范围)、胜负检测(连续五个相同颜色的棋子横向、纵向或斜向连成一线为胜)等,这些都是用Java算法实现的。 7. **事件监听...
### Java基础知识概述 #### 1. 前言 Java是一种广泛使用的面向对象的编程语言,因其跨平台性、安全性和强大的功能而受到欢迎。...掌握这些核心概念和技术将有助于开发者更好地利用Java来解决问题。
这通常是一个无限循环,不断地检查游戏状态,更新蛇的位置,判断是否吃到食物,以及检查蛇是否撞到边界或自身。在Java中,我们可以使用`while(true)`循环来实现这一点,并通过`Thread.sleep()`方法控制游戏的帧率,...