Java – How to Prepend an Element to Each List in a List Using Java Streams

javajava-streamspread-syntax

Let's say we have the following base list:

[["foo"],["bar"]]

and the input string "a"

I want to prepend the input string to each list in the list, which results in:

[["a", "foo"], ["a", "bar"]]

The Javascript equivalent would be:

const base = [["foo"], ["bar"]]
const prefix = "a"
const prefixedBase = base.map(it => [prefix, ...it])

How can this be achieved using a similar idiomatic format with Java streams?

Best Answer

The idiomatic solution using Java streams I found for this is as follows:

var base = List.of(List.of("foo"), List.of("bar"));
var prefix = "a";
var prefixedBase = base.stream()
        .map(it -> Stream.concat(Stream.of(prefix), it.stream()).toList())
        .toList();

While not as concise as Javascript, it does the job without much code. However, it's important to note that using Java streams requires an important trade-off between conciseness and readability.

For the sake of completeness, the equivalent code without Java streams would be:

var base = List.of(List.of("foo"), List.of("bar"));
var prefix = "a";
var prefixedBase = new ArrayList<List<String>>();
for (var subList: base) {
    var newSubList = new ArrayList<String>();
    newSubList.add(prefix);
    newSubList.addAll(subList);
    prefixedBase.add(newSubList);
}

EDIT: Based on other answers and comments, if the base list is mutable, addFirst or add(0, prefix) can also be used as a very concise solution:

for (var subList: base) {
    subList.addFirst(prefix); // add(0, prefix) before Java 21
}