6

I know that for object, we can forEach the collection and update the object as we like but for immutable objects like Strings, how can we update the array with new object without converting it into an array again.

For e.g, I have an array of string. I want to iterate through each string and trim them. I would otherwise have to do something like this:

Arrays.stream(str).map(c -> c.trim()).collect(Collectors.toList())

In the end, I will get a List rather then String[] that I initially gave. Its a whole lot of processing. Is there any way I can do something similar to:

for(int i = 0; i < str.length; i++) {
        str[i] = str[i].trim();
    }

using java streams?

4
  • 1
    and you are worried about what? Speed? Memory Allocation? GC calls? Commented Dec 15, 2016 at 10:05
  • 7
    Arrays.setAll(arr, i -> arr[i].trim())); maybe. Commented Dec 15, 2016 at 10:13
  • @AlexisC. awesome! totally forgot about it, i think it should be an answer.. Commented Dec 15, 2016 at 10:21
  • @Eugene, not speed or memory but finding a more simpler way of doing it. Commented Dec 15, 2016 at 10:24

3 Answers 3

10

Streams are not intended for manipulating other data structures, especially not for updating their source. But the Java API consists of more than the Stream API.

As Alexis C. has shown in a comment, you could use Arrays.setAll(arr, i -> arr[i].trim());

There’s even a parallelSetAll that you could use when you have a really large array.

However, it might be easier to use just Arrays.asList(arr).replaceAll(String::trim);.

Keep in mind that the wrapper returned by Arrays.asList allows modifications of the wrapped array through the List interface. Only adding and removing is not supported.

Sign up to request clarification or add additional context in comments.

Comments

5

Use toArray :

str = Arrays.stream(str).map(c -> c.trim()).toArray(String[]::new);

The disadvantage here (over your original Java 7 loop) is that a new array is created to store the result.

To update the original array, you can re-write your loop with Streams, though I'm not sure what's the point :

IntStream.range (0, str.length).forEach (i -> {str[i] = str[i].trim();});

1 Comment

In addition, maybe trim by method reference: Arrays.stream(str).map(String::trim).toArray(String[]::new);
2

It's not that much processing as you might think, the array has a known size and the spliterator from it will be SIZED, thus the resulting collection size will be known before processing and the space for it can be allocated ahead of time, without having to re-size the collection.

It's also always interesting that in the absence of actual tests we almost always assume that this is slow or memory hungry.

of course if you want an array as the result there is a method for that :

 .toArray(String[]::new);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.