In order to improve performance it may be better to use intermediate ByteArrayOutputStream
+ OutputStreamWriter
to concatenate the values.
The byte array of the concatenated result is returned by ByteArrayOutputStream::toByteArray
private ByteArrayInputStream getInputStreamFromContactFile(MyDTO contacts) throws IOException {
long start = System.currentTimeMillis();
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
Writer writer = new OutputStreamWriter(bos);
writer.write(contacts.getHeader());
writer.write("\n");
contacts.getLines().forEach(line -> {
try {
writer.write(line.value);
writer.write("\n");
} catch (IOException ioex) { throw new RuntimeException(ioex);}
});
writer.flush();
return new ByteArrayInputStream(bos.toByteArray());
} finally {
log.info("Duration is {}ms", System.currentTimeMillis() - start);
}
}
Another approach could be to use Collectors.joining
with prefix and suffix:
private ByteArrayInputStream getInputStreamFromContactFile(MyDTO contacts) {
long start = System.currentTimeMillis();
try {
return new ByteArrayInputStream(
contacts.getLines()
.stream()
.map(item -> item.value)
.collect(Collectors.joining("\n", contacts.getHeader().concat("\n"), "\n"))
.getBytes()
);
} finally {
log.info("Duration is {}ms", System.currentTimeMillis() - start);
}
}
If it is really necessary to use Stream::reduce
operation (due to some reason) with StringBuilder
, the following approach may be applied:
private static ByteArrayInputStream getInputStreamFromContactFileReducing(MyDTO contacts) {
long start = System.currentTimeMillis();
try {
byte[] bytes = contacts.getLines()
.stream()
.map(lineItem -> lineItem.value)
.reduce(new StringBuilder().append(contacts.getHeader()).append("\n"),
(sb, line) -> sb.append(line).append('\n'),
(sb1, sb2) -> sb1.append(sb2))
.toString()
.getBytes();
return new ByteArrayInputStream(bytes);
} finally {
log.info("Reducing: Duration is {}ms", System.currentTimeMillis() - start);
}
}