Reputation: 23
I have a tradition for loop below and I just wondering what the equivalent loop would be for each loop.
for (int i = 0; i < words.size(); i++)
{
words.set(i, words.get(i).toUpperCase());
}
In addition, for those, who are wondering, words is an arrayList of type String.
Upvotes: 1
Views: 173
Reputation: 140534
I'm surprised that nobody has pointed out the following structure, using an enhanced for loop:
int i = 0;
for (String str : words) {
words.set(i++, str.toUpperCase());
}
Now, this is pretty gross, and inefficient unless words
is an instance of RandomAccess
; I'd much prefer to use the ListIterator
approach proposed by Weston.
This works for ArrayList
and LinkedList
etc without a ConcurrentModificationException
because that is only thrown following structural modification of the list:
A structural modification is any operation that adds or deletes one or more elements, or explicitly resizes the backing array; merely setting the value of an element is not a structural modification.
Note that there is no safe approach for a general List
implementation (including the basic for loop in the original question): set
is an optional operation, and you can't tell if it is implemented for a List
without trying it.
Upvotes: 1
Reputation: 54811
The for
loop with indexes is fine, but just so you know, you can also use a ListIterator
which allows replacing of the current item via set
:
for (ListIterator<String> iterator = words.listIterator(); iterator.hasNext();) {
String word = iterator.next();
iterator.set(word.toUpperCase());
}
Which is not an enhanced for-loop, but is very close to what an enhanced for loop actually is with non-array Iterable
s.
Upvotes: 3
Reputation: 5103
Perhaps you would be interested in the java 8 way of doing this:
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class Class {
public static void main(String... args) {
List<String> words = new ArrayList<String>();
words.add("hello");
words = words.stream()
.map(String::toUpperCase)
.collect(Collectors.toList());
System.out.println(words);
}
}
Upvotes: 1
Reputation: 133639
for-each construct doesn't allow you to set an element. This because the syntactic sugar it provides hides the Iterator<E>
completely.
for (String word : words)
...
is equivalent to
for (Iterator<String> it = words.iterator(); it.hasNext(); /**/) {
String word = it.next();
...
}
This could work if String
instances were mutable object such that you can modify the content without modifying the reference but that's not the case. To be able to do what you need with a for-each you'd need a wrapper class, eg:
List<AtomicReference<String>> words = ...;
for (AtomicReference<String> word : words)
word.set(word.get().toUpperCase());
Upvotes: 3