1

I somehow feel stupid to ask this question, BUT

Why is it not possible to change the reference to an object in a List by hand using the EnhancedForStatement?

private static List<String> list = new ArrayList<String>();

public static void main(String[] args) {
    list.add("AAA");
    list.add("BBB");
    list.add("CCC");

    for(String s : list){
        if(s.equals("BBB")) s = "QQQ";
    }

    System.out.println(list);
}

Will print [AAA, BBB, CCC] because the reference to the second element wasn't changed, as one could expect.

But why am I not allowed (or is List the wrong type?) to manually change the reference of the list entry? String in this example could be any complex type, this question is about the changing of references in a List.

edit: OK, maybe it is clear why it works the way it works, but how can I accomplish the reference change? I can't believe there is no way for any subtype of List to change the reference of any element.

edit2: so it is not possible to change the reference when using the EnhancedForStatement?

dasLort
  • 1,264
  • 1
  • 13
  • 28

3 Answers3

5

s is a String variable, and assigning to it doesn't affect the list.

In order to change the list, call list.set(1,"QQQ");, which would put a new String as the second element of the list.

Eran
  • 387,369
  • 54
  • 702
  • 768
  • 1
    however doing that in a loop might cause a ConcurrentModificationException – dkatzel Nov 06 '14 at 15:24
  • You would have to do it in a for loop with your own index so that you know which index to set. Since you are not using the iterator, there will be no ConcurrentModificationException. – user12722 Nov 06 '14 at 15:29
  • I expected this kind of answer. This is not what I am asking, see the edit – dasLort Nov 06 '14 at 15:42
  • since in the EnhancedForStatement I don't have an index, tell me how to change the reference while iterating (leaving aside ConcurrentModificationExceptions) please – dasLort Nov 06 '14 at 16:00
4

Let's dig a bit into how the enhanced for loop works on the background.

for (String s : list) { .. }

is actually translated to:

for (Iterator<String> iter = list.iterator(); iter.hasNext();) {
    String s = iter.next();
    ..
    s = "QQQ";
}

As you can see, passing a new reference to the s variable, just changes it for the scope of the loop, which doesn't have any effect on the list entry.

If you need to modify the current element that's being handled by the iterator, working with ListIterator makes it very easy:

for (ListIterator<String> iter = list.listIterator(); iter.hasNext();) {
    String s = iter.next();
    ..
    iter.set("QQQ");
}

Note that before iter.set(...), we need to call iter.next().

Konstantin Yovkov
  • 62,134
  • 8
  • 100
  • 147
  • and how can I change the reference while iterating over the list? If I can't why? Does Java simply lack this construct? – dasLort Nov 06 '14 at 15:46
  • 1
    It doesn't really have to do with this being a for each; it is fundamental to how variables and references work in java. – Mark Rotteveel Nov 06 '14 at 17:23
  • @dasLort, you can change the refference with the `list.set(index, newReference)` method. :) – Konstantin Yovkov Nov 07 '14 at 07:18
  • also see my comment on the other answer: since in the EnhancedForStatement I don't have an index, tell me how to change the reference while iterating (leaving aside ConcurrentModificationExceptions) please – dasLort Nov 07 '14 at 11:06
  • hahaha OK nice, but that is not the EnhancedForStatement but the regular one ;) – dasLort Nov 10 '14 at 11:21
0

You could make a temporary list.

private static List<String> list = new ArrayList<String>();

public static void main(String[] args) {
    list.add("AAA");
    list.add("BBB");
    list.add("CCC");

    List<String> templist = new ArrayList<String>();   

    for(String s : list){
       if(s.equals("BBB")) s = "QQQ";

       templist.add(s);
    }
    list = templist;

    System.out.println(list);
}
mirvine
  • 126
  • 1
  • 2
  • 14
  • I want to know how to change the reference. I don't want to create a new list – dasLort Nov 06 '14 at 15:43
  • @dasLort If you notice at the end, it says `list = templist`. It does change it. `templist` is just a temporary placeholder so you can edit it. – mirvine Nov 06 '14 at 16:35
  • This code doesn't work. It does nothing with the changes `s` variable and it add `QQQ` for every String in that List. Therefore, the result will be `"QQQ", "QQQ", "QQQ"` instead of `"AAA", "QQQ", "CCC"`. – Tom Nov 12 '14 at 14:16
  • 1
    @Tom sorry, confused myself when I made it. Changed it so now it's better. – mirvine Nov 13 '14 at 15:36