考虑文件读取方案,其中第一行是标题。当逐行循环文件时,将使用'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万次迭代之后出现,您将如何有效地处理这种情况?
答案 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
,因此任何硬件都可以正常使用
所以不要太担心。你不是在那里浪费周期。
回答你的问题......它已经存在了。它并没有消失,但如果你正确编码它应该非常接近消失