来自文本文件的Java输入格式不正常

时间:2016-10-19 17:50:54

标签: java graph io

所以我意识到这种文本格式可能并不常见。但是,我一直在尝试许多想法,将其正确地读入所需的对象,并且知道必须有更好的方法。这是文件的样子:

S S n
B 1 E 2

B N n
C 2 F 3

C N n
D 2 GA 4

D N n
GA 1

E N n
B 1 F 3 H 6

F N n
I 3 GA 3 C 1

A N g

H B b
U 2 GB 2 F 1

I N n
GA 2 GB 2

GB N g 

所以每对的第一行是节点S的名称,无论是起始节点N / s,还是它的目标节点g / n 第二行是节点S的子节点和它们的距离权重。 例如,节点S具有距离为1的子节点B和距离为2

的子节点E.

我正在处理两种对象类型,节点和边缘。 以下示例。 (建筑师省略)

有没有人有关于如何有效阅读此类输入的提示?

public class Edge {
public String start;
public String end;
public int weight;


public class Node {

public String name;
public boolean start = false;
public boolean goal = false;
public ArrayList<Edge> adjecentNodes = new ArrayList<Edge>();

1 个答案:

答案 0 :(得分:1)

实际上你的问题几乎是过于宽泛和不明确,但我很乐意给你一些起点。但请理解,您可以轻松填写​​几个小时的计算机科学讲座;这不会发生在这里。

首先,你必须澄清一些要求(为你自己;或者与在这个项目上工作的人一起):

  1. 您是否真的需要专注于高效阅读/构建图表?我更怀疑:构建图表会发生一次;但是你以后可能会做的计算可能会运行更长的时间。因此,主要关注的是设计对象/类模型,使您能够有效地解决您想要在该图上解决的问题!例如:在创建图形时,按距离/重量已经排序边缘可能是有益的。或者可能不是。取决于以后的用例!即使你在谈论需要高效处理的巨大的文件......这仍然意味着:你在谈论巨大的图表;所以更有理由为该图找到一个好的模型
  2. 您对该文件的描述不明确。例如:这是一个(非)有向图吗?含义 - 您可以在两个方向的任何边缘旅行吗?对不起,我没有得到什么&#34;目标&#34;节点应该是。 (我猜你有定向的边缘只有一种方式,因为这可以解释示例中那些节点没有任何子节点的行)。当然,在您开始编写实际代码的那一刻,有时需求会变得清晰。但这里真的是关于概念/数据/算法。所以你越早回答所有这些问题,对你来说就越好。
  3. 其次,建议顺序做事:

    1. 如上所述,澄清您的所有要求。花一些时间来思考关于你正在处理的图的属性;以及你以后必须解决的问题。
    2. 开始编码;理想情况下,您可以在此处使用TDD /单元测试。因为你要做的所有事情都可以很好地切成小工作包,每一个都可以用单元测试进行测试。在第一次实验运行2天后,首先写下您的所有代码!你编写的第一件事:你的Node / Edge类...因为你想要玩这样的事情:我的构造函数需要什么参数?如何使我的类不可变(数据仅由构造函数推入)?我是否希望距离成为我边缘的属性;或者我可以使用节点对象(并将边缘表示为Map<Node, Integer> - 意味着每个节点只知道它的邻居以及到达那里的距离!)
    3. 然后,当您确信该Node / Edge适合您的问题时,您就开始编写采用字符串的代码,并从这些字符串中构建Node / Edges。
    4. 您还花了一些时间编写好的 dump 方法;理想情况下,您调用graph.dump()...并生成一个与您的输入格式匹配的字符串(稍后进行一个很好的测试:读取+转储应该会生成相同的文件!)
    5. 然后,当&#34;从字符串&#34;工作...然后你写了几行&#34;文件解析代码&#34;它使用一些BufferedReader,FileReader,Scanner,Whatever机制将您的输入文件分解为字符串......然后将其输入您在上面为第3步创建的方法。
    6. 并且,严肃地说:如果这是为了学校/学习:

      • 经常尝试与同伴交谈。让他们看看你在做什么。不太早,但也不会太晚。
      • 真的,认真:考虑丢掉东西;并从头开始。对于上述每个步骤,或在完成整个序列之后。这样做是一种难以置信的经历;因为通常情况下,每次执行此操作时,您都会想出新的,不同的,有趣的想法。

      最后,一些具体的提示:

      很有可能使用&#34; public&#34; (可写)字段,如类中的start / end / ....但是:考虑不这样做。尝试隐藏尽可能多的类的内部。因为这样可以更容易(或可能!)以后更改程序的一部分,而无需更改任何其他内容。

      示例:

      class Edge {
        private final int distance;
        private final Node target;
      
        public Edge(int distance, Node target) {
          this.distance = distance; this.target = target;
        }
        ...
      

      这会创建一个不可变的对象 - 您无法在创建对象后更改其核心内部属性。这通常很有帮助。

      然后:覆盖方法,例如 toString() equals() hashCode() ;并使用它们。例如,toString()可用于创建一个漂亮的,人类可读的节点转储。

      最后:如果您喜欢所有这些,请考虑记住我的用户ID;当你在&#34; upvote&#34;中获得足够的声誉时,请回来并投票; - )