2017-01-26 4 views
1

У меня есть традиция для цикла ниже, и мне просто интересно, какой эквивалентный цикл будет для каждого цикла.Что эквивалентно этой традиции для цикла для a для каждого цикла

for (int i = 0; i < words.size(); i++) 
{ 
    words.set(i, words.get(i).toUpperCase()); 
} 

Кроме того, для тех, кто задается вопросом, слова - это массивList типа String.

+0

Вы используете arraylists, foreach не работает для кода, написанного выше ... –

+0

Другими словами ничего не происходит –

+0

Итак, вы не можете использовать a для каждого цикла для arrayList только для массива – user7471732

ответ

3

для каждой конструкции не позволяет установить элемент. Это потому, что синтаксический сахар, который он обеспечивает, полностью скрывает Iterator<E>.

for (String word : words) 
... 

эквивалентно

for (Iterator<String> it = words.iterator(); it.hasNext(); /**/) { 
    String word = it.next(); 
    ... 
} 

Это может работать, если String экземпляры были изменяемый объект таким образом, что вы можете изменить содержание без изменения ссылки, но это не так. Для того, чтобы быть в состоянии делать то, что вам нужно с для каждого, вам потребуется класс-оболочку, например:

List<AtomicReference<String>> words = ...; 
for (AtomicReference<String> word : words) 
    word.set(word.get().toUpperCase()); 
+0

отсутствует точка с запятой в вашем втором коде, если 'for' loop –

3

for петля с индексами это хорошо, но только так вы знаете, вы можете также использовать ListIterator которая позволяет замену текущего элемента с помощью set:

for (ListIterator<String> iterator = words.listIterator(); iterator.hasNext();) { 
    String word = iterator.next(); 
    iterator.set(word.toUpperCase()); 
} 

Что не расширенная для цикла, но очень близко к тому, что улучшенный цикл на самом деле с не-массив Iterable с.

+0

Это не для каждого цикла, как запрошено OP, но это более эффективный базовый цикл (например, для' LinkedList'). +1. –

1

Возможно, вы были бы заинтересованы в способ сделать это Java 8:

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); 
    } 
} 
+0

Это не эквивалентно: базовый для цикла выше делает верхний регистр без выделения нового списка. (Тем не менее, он все еще выделяет новые строки, obvs). –

1

Я удивлен, что никто не указал следующую структуру, используя улучшенный цикл:

int i = 0; 
for (String str : words) { 
    words.set(i++, str.toUpperCase()); 
} 

Теперь это довольно грубо и неэффективно, если words не является экземпляром RandomAccess; Я бы предпочел использовать ListIterator approach proposed by Weston.

Это работает для ArrayList и LinkedList и т.д. без ConcurrentModificationException, потому что только выброшены следующие structural modification of the list:

структурная модификация любая операция, которая добавляет или удаляет один или несколько элементов, или явно изменяет размер массива подкладочный; просто установка значения элемента не является структурной модификацией.

Обратите внимание, что не существует безопасного подхода к общему List реализации (в том числе основной цикл в исходном вопросе): set является дополнительной операцией, и вы не можете сказать, если он реализован на List без пытаясь это сделать.

+0

Я предполагаю, что никто не указал на это решение, потому что он действительно хрупкий и заставляет вас сделать много дополнений к основной реализации (что всегда плохо в объектно-ориентированном программировании). На самом деле лучшим решением было бы просто использовать поток и собрать результат: 'list = list.stream(). Map (s -> s.toUpperCase()). Collect (Collectors.toList())'. Может быть, медленнее (возможно, не из-за того, что параллелизация полностью применима здесь), но, безусловно, более безопасна и удобочитаема. – Jack