如何在java中创建一个条件块只执行一次?

时间:2018-03-07 08:57:42

标签: java if-statement

考虑文件读取方案,其中第一行是标题。当逐行循环文件时,将使用'if条件'来检查当前行是否是第一行。

for(Line line : Lines)
{
     if(firstLine)
     {
         //parse the headers
     }else
     {
         //parse the body
     }
}

既然控制已进入'if block',在所有其他事件中,检查'if condition'是浪费。

java中是否有任何概念,一旦执行后,特定的代码行就会消失?

我认为如果引入它会是一个很棒的功能还是已经存在?

修改:谢谢您的回答。我认为,基于“划分数据集”的方法很多。因此,不要使用“第一行”,而应考虑有一条“特殊线”..

for(Line line : Lines) //1 million lines
{
     if(specialLine)
     {
         //handle the special line
     }else
     {
         //handle the rest
     }
}

在上面的代码块中,假设特殊线仅在经过一半到100万次迭代之后出现,您将如何有效地处理这种情况?

7 个答案:

答案 0 :(得分:4)

如何稍微改变逻辑呢?

因为标题是第一行,你可以获得firstLine并单独解析它,然后从第二行开始解析正文:

List firstLine = Lines.get(0);
//parse the headers        ^------------------Get the first line
for (int i = 1; i < Lines.size(); i++) {
    //       ^--------------------------------Parse the body starting from the 2nd line
    //parse the body
}

在这种情况下,您不需要任何验证。

答案 1 :(得分:2)

你可以(伪代码)简单地改变一些事情:

// parse headers
for(Line line: remainingLines)
{

但是接下来:你将使用一个简单的布尔标志进行检查。如果检查几乎是免费的,甚至更多:这个循环看到如此多的重复以至于值得优化时,JIT将启动并为其创建优化的代码

如果JIT没有启动,那么值得优化它。当然,硬件级别还有分支预测 - 换句话说:您可以期待现代硬件/软件确保最佳状态发生。除了编写清晰简单的代码之外,没有其他许多工作。

从这个意义上说,你的问题是过早优化的一个典型例子。你担心错误的方面。专注于编写干净,简单的代码来完成工作。因为这是使JIT能够完成运行时魔术的原因。您在jave源代码级别应用的大多数优化在运行时都无关紧要。

答案 2 :(得分:2)

尝试分割数据集。

public List head(List list) {
    return list.subList(0, 1);
}

public List tail(List list) {
    return list.subList(1, list.size());
}

head(lines).foreach( lambda: //parse the header)
tail(lines).foreach( lambda: //parse the body)

答案 3 :(得分:1)

最简单的答案是使用某种标志来确保您只将第一行解析为标题一次。

boolean isHeaderParsed = false

for(Line line: Lines)
{
 if(!isHeaderParsed && firstLine)
 {
     //parse the headers
     isHeaderParsed = true
 }else
 {
     //parse the body
 }
}

这将实现您的目标。但是如果你正在寻找更有趣的东西,接口就是你所需要的。

Parser parser = new HeaderParser()
for(Line line: Lines)
{
  parser = parser.parse();
}

// Implementations for Parser
public class HeaderParser implements Parser{
    public Parser parse() {
         // your business logic
         return new BodyParser();
    }
}

public class BodyParser implements Parser{
    public Parser parse() {
         // your logic
         return this;
    }
}

这些通常被称为Thunks

答案 4 :(得分:1)

因为其他人都发布了一些奇怪的答案。你可以有一个界面。

interface StringConsumer{
    void consume(String s);
}

然后在第一次尝试后更改接口。

StringConsumer firstLine = s->{System.out.printf("first line: %s\n", s);};
StringConsumer rest = s->{System.out.printf("more: %s\n", s);};

StringConsumer consumer = firstLine;

for(String line: lines){
    consumer.consume(line);
    consumer = rest;        
}

如果你不喜欢这个作业,你可以让消费者成为一个字段,并在第一个消费者消费方法中改变它的价值。

class StringProvider{
    StringConsumer consumer;
    List<String> lines;
    //assume this is initialized and populated somewhere.

    void process(){
        StringConsumer rest = s->{System.out.printf("more: %s\n", s);};
        consumer = s->{
            System.out.printf("firstline: %s\n", s);
            consumer = rest;
        };
        for(String line: lines){
            consumer.consume(line);
        }
    }

}

现在,第一个消费呼叫将切换正在使用的消费者。以及随后的电话将会休息。消费者。

答案 5 :(得分:0)

在if-else外面有一个布尔标志,并在方法中输入时更改flag的状态。还会评估此标志以及条件

boolean flag=true;

for(Line line: Lines)
{
     if(firstLine && flag)
     {
 flag=false;
         //parse the headers
     }else
     {
         //parse the body
     }
}

答案 6 :(得分:0)

由于没有人这么说,我会继续说这个额外的if声明实际上相当便宜,性能明智。

在您机器的最低级别,有一个名为分支预测的东西。当硬件无法预测其结果时,if语句往往相当昂贵。但是当它确实正确时,使用if测试一个布尔值几乎是免费的。由于您的if将99.99%的时间评估为false,因此任何硬件都可以正常使用

所以不要太担心。你不是在那里浪费周期。

回答你的问题......它已经存在了。它并没有消失,但如果你正确编码它应该非常接近消失