StringBuilder manipulation via Java 8 Streams API

StringBuilder manipulation via Java 8 Streams API

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.

private static StringBuilder removeCarryReturnsCharacters(StringBuilder fileData) {
    Stream.iterate(1012, i -> i + 1012)
          .limit(fileData.length() / 1014)
          .sorted(Collections.reverseOrder())
          .forEach(e -> {
                if (fileData.substring(e, e + 2).equals(^^)) {
                    fileData.delete(e, e + 2);
                }
          });
    return fileData;
}

StringBuilder manipulation via Java 8 Streams 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 read all lines into a List, but lines
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.

Leave a Reply

Your email address will not be published. Required fields are marked *