2016-12-16 4678 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中處理異常。 –