切换案例与If,否则在比较多个字符串时

时间:2016-07-18 22:54:02

标签: java parsing if-statement switch-statement

我有一个关于解析文件的问题。以下是我用以下代码解析文件的一些语句:

while(scan.hasNextLine()){
    line = scan.nextLine();//this gets the whole line
    if(line.contains("SomeDataIKnow"){
        data = new Scanner(line).useDelimiter("=");//scans just the one line
        value = data.next();//sets value to the string right after the =
        this.Data1 = value;
    }
    else if(line.contains("DifferentDataIKnow"){
        data = new Scanner(line).useDelimiter("=");
        value = data.next();
        this.Data2 = value;
 }

请注意,大约有30行在行包含语句中都有不同的字符串。

我知道在每个“=”之前的单词会说出什么,但不会在等于之后。因此,我需要通过查找特定数据进行解析,然后在等号后获取这些值。我知道,当有超过2或3个语句时,你不应该使用if语句。所以我很好奇是否有人有其他方法可以做到这一点?可能是我正在思考的切换语句,但不确定这是否会对某些行提供帮助。此外,如果它有助于可视化文件,总共有400行,但我只需要大约30行。我无法发布文件,但文件中的完整行示例如下:

Device.A一堆其他信息发生了变化。我知道的数据=我需要的价值

所以我解析了多个文件和数据更改,但DATA I KNOW部分除外,它永远不会改变,而是我用它来查找具有我需要的值的行。对不起,如果这听起来很混乱。

3 个答案:

答案 0 :(得分:2)

你不应该这样编码,DRY是编码中最重要的规则 - 当你查看你的switch语句时,你会发现很多冗余。你不应该像这样使用if / elseif链的原因也适用于switch语句 - 它们是一个糟糕的代码味道,因为它们会导致冗余代码。

所以要做的第一件事就是看看每个区块的不同之处。这是您的冗余代码:

if(line.contains("SomeDataIKnow"){
    data = new Scanner(line).useDelimiter("=");//scans just the one line
    value = data.next();//sets value to the string right after the =
    this.Data1 = value;
}
else if(line.contains("DifferentDataIKnow"){
    data = new Scanner(line).useDelimiter("=");
    value = data.next();
    this.Data2 = value;
}

差异是[SomeDataIKnow,Data1] vs [DifferentDataIKnow,Data2]

Scalars不是存储这类数据的好方法 - 它们通常会让你创建像上面这样的代码,因为没有明显的简单方法,所以我通常使用地图。

因此,如果我在代码库中看到这段代码,我的第一个重构就像:

String[] strings=new String[]{"SomeDataIKnow","DifferentDataIKnow"};
Map results=new HashMap<String, String>()

for(String sub:strings)
{
    if(line.contains(sub){
        data = new Scanner(line).useDelimiter("=");
        value = data.next();
        results.put(sub, value);
}

这有一些问题但有效。当有新的字符串要检查时,您不必添加任何代码,您的代码减少了30倍,并且您的if语句/代码的任何补丁都不需要在30个不同的位置重复。

最大的问题是,查找价值不再是微不足道的。你需要一个字符串“SomeDataIKnow”的密钥,在对接中感到痛苦......你曾经有一个变量“Data1”。

如果你想保留“Data1”,你可以使你的字符串像:

String[] strings=new String[]{"SomeDataIKnow:Data1","DifferentDataIKnow:Data2"};

然后执行String [] split = sub.split(“:”)并通过split [0]执行查找,但通过split [1]

将其输入到地图中

在此之后而不是使用this.Data1,你将使用result.get(“Data1”),这是合理的。

有许多其他方法可以为这样的常见操作提供元数据..只要你保持干燥,大多数都可以正常工作。我只使用字符串数组构造,因为它很容易初始化和使用...同样用于拆分。

作为另一种方法的示例,如果你真的想使用标量,你可以像这样设置你的类:

class MyClass{
    @SearchStr("SomeDataIKnow")
    String Data1;
    @SearchStr("DifferentDataIKnow")
    String Data2;
...

现在,注释很容易处理 - 您只需通过类中的所有@SearchStr注释来构建搜索项,以与上面相同的方式循环它们,并将结果值填充到相应的变量中。 / p>

像这样重构模式的技巧只是识别差异并将它们分组 - 任何让你感觉舒适并且不会增加太多复杂性的方法。

顺便说一下,一旦你在地图中得到了结果,就会看看它们的使用位置。您经常会在那里找到可以重构的其他冗余代码 - 像这样的重构可以在您的代码库中节省大量资金。

答案 1 :(得分:0)

一种可能是使用地图。当您扫描每一行时,在地图中添加一个条目,其中键是您知道的部分之前的&#39; =&#39;而值是&#39; =&#39;

之后的部分

然后,在循环之后,您可以编写如下内容:

this.Data1 = map.get("SomeDataIKnow");
this.Data2 = map.get("DifferentDataIKnow");

答案 2 :(得分:0)

您可能需要考虑使用正则表达式Pattern。如果文件不是太大,您可以将整个文件读入内存,然后使用精心设计的Regex模式搜索fetch()并捕获等号前的匹配文本以及{{1}之间的所有内容和下一个换行符。

这样做的主要效果是让您的程序只扫描一次文件的内容而不是40次。如果搜索内容是导致事情进展缓慢的原因,那么这应该会有所帮助。

一旦你知道在等号之前匹配的确切模式,那么你有一个特定的字符串,你可以在postDelayed语句中使用或查找(SomeDataIKnow|DifferentDataIKnow|...)=或其他任何一个比尔K建议的方法。