- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我目前正在研究将 Valve Map 格式(.vmf 文件)解析为 Java 可读对象的“代码解析器”。
在 vmf 文件中,
因此我创建了一个VMFClass
对象类和一个VMFProperty
对象类。我用自己创建的 HierarchyObject
创建了一个列表,其中包含 VMFClass
/VMFProperty
对象、一个 UUID 和 parentUUID。VMFClass
对象包含 2 个列表,一个带有子 VMFClass
es,一个带有属性。
我的问题是我不知道如何实现一个类包含它的所有子类,因为我不知道子类有多少子类等等...
这是我的代码(Github):
层次对象
:
package net.minecraft.sourcecraftreloaded.utils;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class HierarchyObject {
private static Map<Long, Long> usedUUIDs = new HashMap<>();
private long parentUUID;
private long UUID;
private Object object;
/**
*
* @param Object
* @param parent -1 is maximum level
*/
public HierarchyObject(Object object, long parent) {
this.object = object;
this.parentUUID = parent;
while (true) {
long random = (long) (Math.random() * Long.MAX_VALUE);
if (usedUUIDs.containsKey(random)) {
this.UUID = random;
usedUUIDs.put(random, parent);
break;
}
}
}
public long getUUID() {
return UUID;
}
public long getParentUUID() {
return parentUUID;
}
public static long getParentUUIDbyUUID(long UUID) {
if (usedUUIDs.containsKey(UUID)) {
return usedUUIDs.get(UUID);
}
return -1;
}
public Object getObject() {
return object;
}
public static boolean hasChild(long UUID){
if(usedUUIDs.containsValue(UUID)){
return true;
}
if(UUID == -1){
return true;
}
return false;
}
public boolean hasChild(){
return hasChild(this.UUID);
}
public static long[] getChildUUIDs(long UUID){
if(hasChild(UUID)){
List<Long> cUUIDs = new ArrayList<>();
for(int i = 0; i < usedUUIDs.size(); i++){
for (Map.Entry<Long, Long> e : usedUUIDs.entrySet()) {
if(e.getValue().longValue() == UUID){
cUUIDs.add(e.getKey());
}
}
}
return ListUtils.toPrimitivebyList(cUUIDs);
}
return null;
}
}
VMFProperty
:
package net.minecraft.sourcecraftreloaded.source;
public class VMFProperty{
private String name;
private String[] values;
public VMFProperty(String name, String... values) {
this.name = name;
this.values = values;
}
public String getName() {
return name;
}
public String[] getValues() {
return values;
}
@Override
public boolean equals(Object paramObject){
if(paramObject instanceof VMFProperty){
return ((VMFProperty)paramObject).name.equals(this.name) && ((VMFProperty)paramObject).values.equals(this.values);
}
return false;
}
}
VMFClass
:
package net.minecraft.sourcecraftreloaded.source;
import java.util.List;
public class VMFClass{
private List<VMFClass> classes;
private List<VMFProperty> properties;
private String name;
public VMFClass(String name, List<VMFClass> classes, List<VMFProperty> properties) {
this.name = name;
this.classes = classes;
this.properties = properties;
}
public String getName() {
return name;
}
public List<VMFClass> getClasses() {
return classes;
}
public List<VMFProperty> getProperties() {
return properties;
}
public void add(VMFClass vmfclass) {
classes.add(vmfclass);
}
public void add(VMFProperty vmfproperty) {
properties.add(vmfproperty);
}
public void remove(VMFClass vmfclass) {
classes.remove(vmfclass);
}
public void remove(VMFProperty vmfproperty) {
properties.remove(vmfproperty);
}
@Override
public boolean equals(Object paramObject){
if(paramObject instanceof VMFClass){
return ((VMFClass)paramObject).properties.equals(this.properties) && ((VMFClass)paramObject).classes.equals(this.classes) && ((VMFClass)paramObject).name.equals(this.name);
}
return false;
}
}
VMFObject
(执行所有代码的类):
package net.minecraft.sourcecraftreloaded.source;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import net.minecraft.sourcecraftreloaded.utils.HierarchyObject;
public class VMFObject {
private String rawfile = "";
private List<VMFClass> toplevelclasses;
private static final String INVALID_CHARS = "\\*,;<>|?=`´#'+~^°!§$%&()[].:-_";
public VMFObject(List<VMFClass> toplevelclasses) {
this.toplevelclasses = toplevelclasses;
}
public VMFObject() {
this(new ArrayList<VMFClass>());
}
public void write(File file) {
VMFWriter.write(file, rawfile);
}
public VMFObject read(File file) throws VMFParsingException {
this.rawfile = VMFReader.read(file);
parse();
return this;
}
public List<VMFClass> getClasses() {
return toplevelclasses;
}
private void parse() throws VMFParsingException {
evaluate();
get();
}
private void evaluate() throws VMFParsingException {
char[] textchars = rawfile.toCharArray();
int[] c = new int[]{0, 0, 0};
int line = 0;
int linepos = 0;
for (int i : textchars) {
linepos++;
if (textchars[i] == '\n') {
line++;
linepos = 0;
c[3] = 0;
if (c[3] % 2 != 0) {
throw new VMFParsingException("Invalid quotes on line" + line + ":" + linepos);
}
}
if (textchars[i] == '{') {
c[1]++;
}
if (textchars[i] == '}') {
c[2]++;
}
if (textchars[i] == '"') {
c[3]++;
if (c[1] - c[2] == 0) {
}
}
if (textchars[i] == '/' && textchars[i + 1] == '/') {
while (true) {
i++;
if (textchars[i] == '\n') {
break;
}
}
}
if (textchars[i] == '/' && textchars[i + 1] == ' ') {
throw new VMFParsingException("Invalid Character '/' on line" + line + ":" + linepos);
}
if (INVALID_CHARS.indexOf(textchars[i]) != -1) {
throw new VMFParsingException("Invalid Character '" + textchars[i] + "' on line" + line + ":" + linepos);
}
}
if (c[1] != c[2]) {
throw new VMFParsingException("Unbalanced brackets in vmf File");
}
}
public void add(VMFClass vmfclass) {
toplevelclasses.add(vmfclass);
}
private void get() throws VMFParsingException {
List<HierarchyObject> content = new ArrayList<>();
long curparent = -1;
String[] text = rawfile.split("\n");
for (int i = 0; i < text.length; i++) {
String line = text[i].trim();
if (line.startsWith("//")) {
continue;
} else {
byte quotec = 0;
char[] linechar = line.toCharArray();
boolean readp = false;
List<String> reads = new ArrayList<>();
byte creads = 0;
for (int y = 0; y < linechar.length; y++) {
if (linechar[y] == '/' && linechar[y + 1] == '/') {
break;
}
if (linechar[y] == '"') {
quotec++;
if (quotec % 2 == 0) {
readp = false;
creads++;
} else {
readp = true;
}
}
if (readp) {
reads.set(creads, reads.get(creads) + linechar[y]);
}
if (linechar[y] == '{') {
HierarchyObject object = new HierarchyObject(new VMFClass(line.substring(line.substring(0, y).lastIndexOf(' '), y).trim(), null, null), curparent);
content.add(object);
curparent = object.getUUID();
}
if (linechar[y] == '}') {
curparent = HierarchyObject.getParentUUIDbyUUID(curparent);
}
}
content.add(new HierarchyObject(new VMFProperty(reads.remove(0), reads.toArray(new String[reads.size()])), curparent));
}
}
buildObject(content);
}
private void buildObject(List<HierarchyObject> content) {
long curUUID = -1;
for(int i = 0; i < HierarchyObject.getChildUUIDs(curUUID).length; i++){
HierarchyObject.getChildUUIDs(curUUID);
}
//TODO implement
}
}
//TODO 部分是层次结构对象应该“转换”为实际对象的地方。
最佳答案
在我看来,您的类布局过于复杂。
让我们尝试简化它...
您所描述的 VMF 模型本质上是一个链表树。
这是模型的样子:
[.vmf file] (root)
/ \
_____/ \ _____
/ \
/ \
(VMFClass) (VMFClass)
/ \ / \
/ \ / \
/ \ / \
(VMFClass) (VMFProperties) (VMFClass) (VMFProperties)
/ \
/ \
/ \
(VMFClass) (VMFProperties)
您需要什么:
VMFObject
,但我们称这个类为 VMFParser
)。VMFClass
和 VMFProperty
类没问题。你不需要的:
HierarchyObject
类。 VMFParser
可以是层次结构(例如 public class VMFClass
{
// name of the class
private String name;
// reference back up to the parent
private VMFClass parentClass = null;
// all direct children go here
private List<VMFClass> children = new ArrayList<VMFClass>();
// I don't think you need a list of properties here since your VMFProperty class holds onto an array of properties
private VMFProperty properties;
// set the parent of this class
public void setParent (VMFClass parent)
{
this.parentClass = parent;
}
// get the direct children
public List<VMFClass> getChildren()
{
return this.children;
}
// rest of methods...
}
class VMFParser
{
private String rawfile = "";
// this is really the container for everything - think of it as the file shell
private VMFClass root = new VMFClass("root", null, null);
// construct yourself with the file
public VMFParser (String fileName)
{
this.rawfile = fileName;
}
public void parse ()
{
// all the parsing code goes here
read();
evaluate();
get();
// now at this point your hierarchy is built and stored in the
// root object in this class.
// Use the traverse method to go through it
}
private void get() throws VMFParsingException
{
// keep a reference to the current VMFClass parent
// starts out as root
VMFClass currParentClass = root;
// main parse loop
for (...)
{
// if you find a class
VMFClass currClass = new VMFClass(/* params here */);
// add this class to the parent
currParentClass.add(currClass);
// set the parent of this class
currClass.setParent(currParentClass);
// if you find a property
// parse and add all the properties to the property
VMFProperty property = new VMFProperty (/* value params here */);
// attach this property to the last VMF class that got parsed
currClass.setPoperties(property);
// If you nest deeper into classes, then the parent becomes the current class
currParentClass = currClass;
// If you go back out of a class
currParentClass = currClass.getParent();
}
}
// Traverse the hierarchy
public void traverse ()
{
traverseTree(root);
}
private void traverseTree (VMFClass root)
{
System.out.println("Class Name: " + root.getName());
// print out any properties
VMFProperty prop = root.getProperty();
if (prop != null)
{
System.out.println("Property Name: " + prop.getName());
String [] props = prop.getValues();
for (String s: props)
{
System.out.println("Value: " + s);
}
}
// get all child classes
List<VMFClass> children = root.getChildren();
for (VMFClass c: children)
{
traverseTree(c);
}
}
}
示例
public static void main(String[] args)
{
VMFParser vmfParser = null;
try
{
vmfParser = new VMFParser("myFile.vmf");
vmfParser.parse();
// access the vmfParser for the hierarchy
vmfParser.traverse();
}
catch (VMFParsingException vpe)
{
// do something here
vpe.printStackTrace();
}
finally
{
// clean up...
}
}
关于java - 创建具有未定义数量的子对象的层次结构对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36810400/
我目前正在尝试基于哈希表构建字典。逻辑是:有一个名为 HashTable 的结构,其中包含以下内容: HashFunc HashFunc; PrintFunc PrintEntry; CompareF
如果我有一个指向结构/对象的指针,并且该结构/对象包含另外两个指向其他对象的指针,并且我想删除“包含这两个指针的对象而不破坏它所持有的指针”——我该怎么做这样做吗? 指向对象 A 的指针(包含指向对象
像这样的代码 package main import "fmt" type Hello struct { ID int Raw string } type World []*Hell
我有一个采用以下格式的 CSV: Module, Topic, Sub-topic 它需要能够导入到具有以下格式的 MySQL 数据库中: CREATE TABLE `modules` ( `id
通常我使用类似的东西 copy((uint8_t*)&POD, (uint8_t*)(&POD + 1 ), back_inserter(rawData)); copy((uint8_t*)&PODV
错误 : 联合只能在具有兼容列类型的表上执行。 结构(层:字符串,skyward_number:字符串,skyward_points:字符串)<> 结构(skyward_number:字符串,层:字符
我有一个指向结构的指针数组,我正在尝试使用它们进行 while 循环。我对如何准确初始化它并不完全有信心,但我一直这样做: Entry *newEntry = malloc(sizeof(Entry)
我正在学习 C,我的问题可能很愚蠢,但我很困惑。在这样的函数中: int afunction(somevariables) { if (someconditions)
我现在正在做一项编程作业,我并没有真正完全掌握链接,因为我们还没有涉及它。但是我觉得我需要它来做我想做的事情,因为数组还不够 我创建了一个结构,如下 struct node { float coef;
给定以下代码片段: #include #include #define MAX_SIZE 15 typedef struct{ int touchdowns; int intercepti
struct contact list[3]; int checknullarray() { for(int x=0;x<10;x++) { if(strlen(con
这个问题在这里已经有了答案: 关闭 11 年前。 Possible Duplicate: Empty “for” loop in Facebook ajax what does AJAX call
我刚刚在反射器中浏览了一个文件,并在结构构造函数中看到了这个: this = new Binder.SyntaxNodeOrToken(); 我以前从未见过该术语。有人能解释一下这个赋值在 C# 中的
我经常使用字符串常量,例如: DICT_KEY1 = 'DICT_KEY1' DICT_KEY2 = 'DICT_KEY2' ... 很多时候我不介意实际的文字是什么,只要它们是独一无二的并且对人类读
我是 C 的新手,我不明白为什么下面的代码不起作用: typedef struct{ uint8_t a; uint8_t* b; } test_struct; test_struct
您能否制作一个行为类似于内置类之一的结构,您可以在其中直接分配值而无需调用属性? 前任: RoundedDouble count; count = 5; 而不是使用 RoundedDouble cou
这是我的代码: #include typedef struct { const char *description; float value; int age; } swag
在创建嵌套列表时,我认为 R 具有对列表元素有用的命名结构。我有一个列表列表,并希望应用包含在任何列表中的每个向量的函数。 lapply这样做但随后剥离了列表的命名结构。我该怎么办 lapply嵌套列
我正在做一个用于学习目的的个人组织者,我从来没有使用过 XML,所以我不确定我的解决方案是否是最好的。这是我附带的 XML 文件的基本结构:
我是新来的 nosql概念,所以当我开始学习时 PouchDB ,我找到了这个转换表。我的困惑是,如何PouchDB如果可以说我有多个表,是否意味着我需要创建多个数据库?因为根据我在 pouchdb
我是一名优秀的程序员,十分优秀!