1

I am learning Java 8 and came across a situation. Where in I have to iterate over a list of strings and then convert them to upperCase. The possible solutions would be to stream the list. Among many suggestions from Intellij the below two seems to be useful.

list.stream()
.map(String::toUpperCase)

or

list.stream().
forEach(p -> p.toUpperCase())

I am confused on which one to use and the use cases for all the Suggestions. Can I get help regarding which method to use and how to understand using all those suggestions?

2
  • 5
    map() does nothing without a terminal operation. forEach(p -> p.toUpperCase()) is a terminal operation that does nothing. If you're trying to convert a string to uppercase, you'll need to use the return value somehow, which neither snippet does.
    – shmosel
    Commented Aug 14, 2019 at 19:13
  • Strings are immutable, so calling toUpperCase() does not (cannot) modify the string to be uppercase. The method returns a new string with all uppercase letters, it doesn't update the existing string.
    – Andreas
    Commented Aug 14, 2019 at 19:59

2 Answers 2

6

Stream.map() will never run unless you end the pipeline in a terminal operation, like forEach(). But calling toUpperCase() in a forEach() won't do anything either, because strings are immutable. String.toUpperCase() doesn't change the string; it returns a new one.

If you just want to update the list in-place, you can use

list.replaceAll(String::toUpperCase);

which actually replaces each element with the result of the passed function.

If you want the results in a new list, use the map() snippet with a collector:

List<String> list2 = list.stream()
        .map(String::toUpperCase)
        .collect(Collectors.toList());
3
  • 1
    OP, please also take a look at stackoverflow.com/questions/35395317/… Commented Aug 14, 2019 at 19:19
  • Thanks, shmosel for the reply. But I would like to know how do I make a mind map of these functions rather than relying on the Intellij suggestions for a solution ?
    – Navmadhu
    Commented Aug 14, 2019 at 19:25
  • Study? Practice? I'm not really sure what kind of answer you're looking for.
    – shmosel
    Commented Aug 14, 2019 at 19:26
1

forEach is an terminal operation that makes a difference through side effects. map is a non-terminal operation that makes a direct mapping from one element to another. For example, here is a canonical usage of forEach:

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

This will invoke, on each element of the stream, the equivalent of System.out.println(element);. However, the stream will be closed after this, and no operations may be executed on stream afterwards. map, on the other hand, may be used like this:

streamOfObjects.map(Object::toString).collect(Collectors.toList());

In this case, each Object within streamOfObjects is mapped to a String, created by invocation of toString. Then, the stream of Strings produced by map is collected into a List using a Collector.

In any case, I'd suggest using replaceAll for this use case, as suggested by @shmosel.

As for how to understand suggestions provided by autocomplete, I would strongly suggest reading JavaDocs on the related classes.

Not the answer you're looking for? Browse other questions tagged or ask your own question.