2016-12-16 4680 views
4

我正在使用java 8流,并且我不能在流的foreach中抛出异常。在java 8流foreach中抛出异常

stream.forEach(m -> { 
     try { 

      if (isInitial) { 
       isInitial = false; 
       String outputName = new SimpleDateFormat(Constants.HMDBConstants.HMDB_SDF_FILE_NAME).format(new Date()); 
       if (location.endsWith(Constants.LOCATION_SEPARATOR)) { 
        savedPath = location + outputName; 
       } else { 
        savedPath = location + Constants.LOCATION_SEPARATOR + outputName; 
       } 
       File output = new File(savedPath); 
       FileWriter fileWriter = null; 
       fileWriter = new FileWriter(output); 
       writer = new SDFWriter(fileWriter); 
      } 

      writer.write(m); 

     } catch (IOException e) { 
      throw new ChemIDException(e.getMessage(),e); 
     } 

    }); 

,这是我的异常类

public class ChemIDException extends Exception { 
public ChemIDException(String message, Exception e) { 
    super(message, e); 
} 

}

我使用记录器登录上级的错误。所以我想抛出异常顶部。由于

enter image description here

+1

从代码我可以看到,它看起来像你应该使用'for'循环而不是流。您试图在功能性环境中放置命令式代码。 – 4castle

+0

我想读取大文件并将一些元素写入另一个文件。这里我正在做的是用过滤器读取文件。所以我认为最好的方法是使用流 –

回答

2

尝试,而不是延长RuntimeException。创建的提供给foreach的方法没有该类型为throwable,因此您需要某些运行时可抛出的东西。

警告:这可能不是一个很好的主意

但它可能会工作。

+0

你或许应该解释为什么这是一个坏主意,而不是帮助他们继续在没有其他选择的情况下自己在脚下开枪。 – 4castle

+0

感谢您的回复。但抛出泛型异常而不是抛出专用异常是否好? –

+0

没有理由不能抛出'RuntimeException'的扩展,这是我推荐的。另外,如果你确保在'foreach'附近捕捉到异常,你就可以防止出现令人惊讶的错误冒泡到执行顶端。 – PaulProgrammer

0

你为什么要使用forEach,设计用来处理元素的方法,当你想要做的,是处理第一元素?我们并没有意识到forEach是该作业的错误方法(或者Stream API中的方法比forEach多),您可以使用isInitial标志来克服这一点。

试想:

Optional<String> o = stream.findFirst(); 
if(o.isPresent()) try { 
    String outputName = new SimpleDateFormat(Constants.HMDBConstants.HMDB_SDF_FILE_NAME) 
         .format(new Date()); 
    if (location.endsWith(Constants.LOCATION_SEPARATOR)) { 
     savedPath = location + outputName; 
    } else { 
     savedPath = location + Constants.LOCATION_SEPARATOR + outputName; 
    } 
    File output = new File(savedPath); 
    FileWriter fileWriter = null; 
    fileWriter = new FileWriter(output); 
    writer = new SDFWriter(fileWriter); 
    writer.write(o.get()); 
} catch (IOException e) { 
    throw new ChemIDException(e.getMessage(),e); 
} 

这与异常处理没有问题。此示例假定Stream的元素类型为String。否则,您必须修改Optional<String>类型。


但是,如果你的isInitial标志应该流处理过程中改变不止一次,你是绝对使用为作业错误的工具。在使用Streams之前,您应该先阅读并理解Stream API文档的“Stateless behaviors” and “Side-effects” sections以及“Non-interference” section。只是将循环转换为forEach Stream上的调用不会改进代码。

+0

在这里,我正在做的是在给定的位置在isInitial if块内创建文件,然后我将流的每个元素写入创建的文件。 –

+0

创建文件isInitial后将为false,然后执行其余的行。 –

+0

我不想写流的第一个元素。我想写全部。我想你误解了我的问题。问题是在流的foreach中处理异常。 –