mahesh
mahesh

Reputation: 1633

sub list without modifying original list in java

Below code actually modifies original list x. Is there anyway to sub list the main list considering that modification to sub list should not modify the original list?

List<Integer> x = new ArrayList<Integer>();

x.add(1);
x.add(2);
x.add(3);
x.add(4);
x.add(5);

List<Integer> y = new ArrayList<Integer>();

y.add(1);
y.add(2);
y.add(3);

final List<Integer> z = x.subList(0, 4);

System.out.println("sublist " + z.toString());

z.removeAll(y);

System.out.println("Main list after removing sublist " + x.toString());

Result:

sublist [1, 2, 3, 4]
Main list after removing sublist [4, 5]

Upvotes: 10

Views: 16374

Answers (6)

Trying
Trying

Reputation: 14278

Why not use CopyOnWriteArrayList.

From Docs:

A thread-safe variant of ArrayList in which all mutative operations (add, set, and so on) are implemented by making a fresh copy of the underlying array.

or

final List<Integer> z = new ArrayList<>(x.subList(0, 4));

Upvotes: -1

NickDK
NickDK

Reputation: 5197

Just create a new List using the constructor which copies all the sublist elements in the new List.

final List<Integer> z = new ArrayList<>(x.subList(0, 4));

Upvotes: 0

mtk
mtk

Reputation: 13709

The sublist is kind of view on the main list. If you ever go into debugging a program using some Collection, you'll find 2 variables i.e. offset and length defined, for the sublist. Which means there aren't actual physical list. So there isn't anyway to not update the original list by updating the sublist.

You do have to make copy of the sublist to achieve your requirement. As explained in code by others.

From the javadocs

Returns a view of the portion of this list between the specified fromIndex, inclusive, and toIndex, exclusive. (If fromIndex and toIndex are equal, the returned list is empty.) The returned list is backed by this list, so non-structural changes in the returned list are reflected in this list, and vice-versa. The returned list supports all of the optional list operations supported by this list.

Upvotes: 0

Masudul
Masudul

Reputation: 21961

Try to use List<Integer> z = new ArrayList<>(x.subList(0, 4))

   List<Integer> x = new ArrayList<Integer>();
    x.add(1);
    x.add(2);
    x.add(3);
    x.add(4);
    x.add(5);

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

    final List<Integer> z = new ArrayList<>(x.subList(0, 4));

    System.out.println("sublist " + z.toString());

    z.removeAll(y);

    System.out.println("Main list after removing sublist " + x.toString());

Output:

sublist [1, 2, 3, 4]
Main list after removing sublist [1, 2, 3, 4, 5]

Upvotes: 12

Rahul Gupta
Rahul Gupta

Reputation: 5295

Yes, assignment

        final List<Integer> z = x.subList(0, 4);

will just copy the value of x (which is a reference) to z as you have not created a new object. They will both refer to the same object. So whatever changes you make in either list, same changes will reflect in the other list as well

This is you should do :-

List<Integer> z = new ArrayList<Integer>(//your sublist code);

Upvotes: 0

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726489

If you do not want the sublist to be a "window" into the original, you need to make a copy, like this:

final List<Integer> z = new ArrayList<Integer>(x.subList(0, 4));

If you would rather have an unmodifiable list without making a copy, you could use Collections.unmodifiableList:

final List<Integer> z = Collections.unmodifiableList(x.subList(0, 4));
z.removeAll(y); // <<== This will now fail.

Upvotes: 5

Related Questions