Search code examples
java-8java-streamstringbuilder

StringBuilder manipulation via Java 8 Streams API


I'm struggling to delete some characters from StringBuilder. The method works fine. However, I want to achieve the same via Java-8 streams API. Current code is verbose. Is there any way to refactor second method removeCarryReturnsCharacters() via Java 8 streams API?

private static StringBuilder readEntireFileUsingStream(Path filePath) throws IOException {

    StringBuilder data = new StringBuilder(String.valueOf(Files.readAllLines(filePath, StandardCharsets.ISO_8859_1)));

    return removeCarryReturnsCharacters(data);

}

private static StringBuilder removeCarryReturnsCharacters(StringBuilder fileData){

    int endIndex = 1012;
    String needToRemove = "";
    long totDataChunkCount = fileData.length()/1014;
    long delCounter = 1;
    try{
        while (delCounter < totDataChunkCount) {
            needToRemove = fileData.substring(endIndex, endIndex + 2);
            if (needToRemove.equals("^^")) {
                fileData.delete(endIndex, endIndex + 2);
            }
            endIndex += 1012;
            delCounter++;
        }
    }catch(StringIndexOutOfBoundsException exp){
        throw exp;
    }
    return fileData;
}

Solution

  • The current code is not verbose due to the lack of the Stream API, but tons of unnecessary operations:

    • the initial assignment needToRemove = ""; is obsolete
    • you are maintaining two redundant loop variables, delCounter and endIndex
    • you are using a while loop despite you have a classical counting loop with initial statement, condition and increment operation, the exact thing, for loops are made for
    • you are using long variables for values which definitely never exceed the int value range
    • you have an obsolete try … catch block just re-throwing the caught exception
    • you don’t need the needToRemove variable to hold an object for a single use; you could simply check if(fileData.substring(endIndex, endIndex + 2).equals("^^")) or, as I would prefer for checking just two characters,
      if(fileData.charAt(endIndex)=='^' && fileData.charAt(endIndex+1)=='^')

    Fixing all these issues will turn the method to

    private static StringBuilder removeCarryReturnsCharacters(StringBuilder fileData) {
        for(int endIndex = 1012; endIndex < fileData.length(); endIndex += 1012)
            if(fileData.charAt(endIndex) == '^' && fileData.charAt(endIndex+1) == '^')
                fileData.delete(endIndex, endIndex + 2);
        return fileData;
    }
    

    I don’t think that there will be any additional benefit from rewriting the loop to use the Stream API.