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?

shmosel
  • 49,289
  • 6
  • 73
  • 138
Navmadhu
  • 15
  • 4
  • 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 Aug 14 '19 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 Aug 14 '19 at 19:59

2 Answers2

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());
shmosel
  • 49,289
  • 6
  • 73
  • 138
  • 1
    OP, please also take a look at https://stackoverflow.com/questions/35395317/transform-all-elements-of-a-list-of-strings-to-upper-case – Gabriel Robaina Aug 14 '19 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 Aug 14 '19 at 19:25
  • Study? Practice? I'm not really sure what kind of answer you're looking for. – shmosel Aug 14 '19 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.

Avi
  • 2,611
  • 1
  • 14
  • 26