4

I have a List defined as follows:

List<Integer> list1 = new ArrayList<>();
list1.add(1); 
list1.add(2);

How can I increment each element of the List by one (i.e. end up with a List [2,3]) using Java 8's Stream API without creating new List?

5
  • Why do you not want to create a new list? Commented Jan 5, 2018 at 9:44
  • @ifly6 for example, you may have a method which is expected to work via side-effects. Commented Jan 5, 2018 at 9:48
  • Simple, use .map() for any manipulation. See @bentaye answer Commented Jan 5, 2018 at 11:08
  • DownVoted : lack of research Commented Jan 5, 2018 at 11:10
  • 1
    UpVoted: good question Commented Jan 5, 2018 at 16:28

5 Answers 5

20

When you create a Stream from the List, you are not allowed to modify the source List from the Stream as specified in the “Non-interference” section of the package documentation. Not obeying this constraint can result in a ConcurrentModificationException or, even worse, a corrupted data structure without getting an exception.

The only solution to directly manipulate the list using a Java Stream, is to create a Stream not iterating over the list itself, i.e. a stream iterating over the indices like

IntStream.range(0, list1.size()).forEach(ix -> list1.set(ix, list1.get(ix)+1));

like in Eran’s answer

But it’s not necessary to use a Stream here. The goal can be achieved as simple as

list1.replaceAll(i -> i + 1);

This is a new List method introduced in Java 8, also allowing to smoothly use a lambda expression. Besides that, there are also the probably well-known Iterable.forEach, the nice Collection.removeIf, and the in-place List.sort method, to name other new Collection operations not involving the Stream API. Also, the Map interface got several new methods worth knowing.

See also “New and Enhanced APIs That Take Advantage of Lambda Expressions and Streams in Java SE 8” from the official documentation.

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

Comments

3

Holger's answer is just about perfect. However, if you're concerned with integer overflow, then you can use another utility method that was released in Java 8: Math#incrementExact. This will throw an ArithmeticException if the result overflows an int. A method reference can be used for this as well, as seen below:

list1.replaceAll(Math::incrementExact);

Comments

1

You can iterate over the indices via an IntStream combined with forEach:

IntStream.range(0,list1.size()).forEach(i->list1.set(i,list1.get(i)+1));

However, this is not much different than a normal for loop, and probably less readable.

Comments

0

reassign the result to list1:

list1 = list1.stream().map(i -> i+1).collect(Collectors.toList());

2 Comments

From the OP "without creating new List". You are creating a new List.
To be fair, it is not clear if he means new list like a new variable or new object.
-1
public static Function<Map<String, LinkedList<Long>>, Map<String, LinkedList<Long>>> applyDiscount = (

            objectOfMAp) -> {


        objectOfMAp.values().forEach(listfLong -> {


            LongStream.range(0, ((LinkedList<Long>) listfLong).size()).forEach(index -> {

                Integer position = (int) index;

                Double l = listfLong.get(position) - (10.0 / 100 * listfLong.get(position));

                listfLong.set(position, l.longValue());

            });

        });

        return objectOfMAp;

    };

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.