Question: 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;
}

```

Answer: 
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.
It looks like you are trying to remove `^^` from individual lines of the original file. You might solve this using only `File.lines` and `Stream.map`:

```
List<String> lines = Files.lines(filePath, StandardCharsets.ISO_8859_1)
.map(line -> {
    if (line.charAt(endIndex) == '^' && line.charAt(endIndex + 1) == '^') {
        return new StringBuilder(line).delete(endIndex, endIndex + 2).toString();
    } else {
        return line;
    }
})
.collect(Collectors.toList());

```

I guess this might have worse performance in comparison with 

```
new StringBuilder(String.valueOf(Files.readAllLines(...)))

```

> 
> However [readAllLines](https://docs.oracle.com/javase/8/docs/api/java/nio/file/Files.html#readAllLines-java.nio.file.Path-java.nio.charset.Charset-) read all lines into a List, but [lines](https://docs.oracle.com/javase/8/docs/api/java/nio/file/Files.html#lines-java.nio.file.Path-java.nio.charset.Charset-)
>  populates lazily as the stream is consumed.
> 
> 
> 

In this case if we use one big 
`StringBuilder` - all data is read **first** and processed **later**. On the contrary - in case of `File.lines` data is processed and read at **the same time**. After the last line of the file is read and processed by stream pipeline - there will be a list of file lines with `^^` characters removed.