Convert an loop (while and for) to stream

As was stated above, using streams here doesn't really add value since it makes the code harder to read/understand. I get that you're doing it more as a learning exercise. That being said, doing something like this is a slightly more functional-style approach as it doesn't have a side effect of adding to the list from within the stream itself:

list = oldList.stream().flatMap(line->
            map.entrySet().stream()
                    .filter(e->line.startsWith(e.getKey()))
                    .map(filteredEntry->line.replace(filteredEntry.getKey(),filteredEntry.getValue()))
        ).collect(Collectors.toList());

You can achieve it with a stream nested in a stream created from oldList list. Nested stream plays role of mapping current value from oldList with a mapper defined in map, e.g.

public static void main(String[] args) {
    final List<String> oldList = Arrays.asList("asd-qwe", "zxc", "123");
    final Map<String, String> map = new HashMap<String, String>() {{
        put("asd", "zcx");
        put("12", "09");
        put("qq", "aa");
    }};

    List<String> result = oldList.stream()
            .map(line -> map.entrySet()
                    .stream()
                    .filter(entry -> line.startsWith(entry.getKey()))
                    .map(entry -> line.replace(entry.getKey(), entry.getValue()))
                    .collect(Collectors.toList())
            )
            .flatMap(Collection::stream)
            .collect(Collectors.toList());


    System.out.println(result);
}

Following example produces output like:

[zcx-qwe, 093]

Suggested solution can be easily parallelized if needed. Functional approach with no side effects.


I don't see why you would want to use streams here, but it is possible.

Create some test input:

List<String> oldList = Arrays.asList("adda","bddb","cddc");
Map<String,String> map = new HashMap<>();
map.put("a", "x");
map.put("b", "y");
map.put("c", "z");

List<String> list = new ArrayList<>();

The actual code:

oldList.stream()
    .forEach(line -> map.entrySet().stream()
            .filter(entry -> line.startsWith(entry.getKey()))
            .forEach(entry -> list.add(line.replace(entry.getKey(),entry.getValue()))));

Print the outcome:

list.forEach(System.out::println);

Which is:

xddx
yddy
zddz

To answer your question, it's a 1-liner:

List<String> list = oldList.stream()
    .filter(line -> map.keySet().stream().anyMatch(line::startsWith))
    .map(line -> map.entrySet().stream()
        .filter(entry -> line.startsWith(entry.getKey()))
        .map(entry -> line.replace(entry.getKey(), entry.getValue()))
        .findFirst().get())
    .collect(Collectors.toList());