Вопросы:
Для чего нужен foreach
, если можно перебирать массив к примеру через цикл for
?
Можно ли сделать задачу с массивами например на foreach
и на цикле for
обычном, чтобы получить по итогу один и тот же результат?
foreach
если есть for
?Нашел вот такой пример, но почему-то не получается реализовать его на foreach:
public class Test {
public static void main(String[] args) {
int numer[] = {4, 8, 16, 32, 64, 128};
int denom[] = {2, 2, 4, 4, 2, 8};
for (int i = 0; i < numer.length; i++) {
System.out.println(numer[i] + " / " + denom[i] + " равно " + numer[i] / denom[i]);
}
}
}
foreach
укорачивает код для перебора коллекций (списки, массивы и т.п.), когда нам нужно только получить элементы из них, без работы с индексами.
Примеры для foreach
:
int numer[] = {4, 8, 16, 32, 64, 128};
for (int i : numer) {
System.out.println(i);
}
List<String> items = Arrays.asList("1", "abc");
for (String word : items) {
System.out.println(word);
}
Map<String, String> nameByValue = new HashMap<>();
nameByValue.put("name", "Vasya");
nameByValue.put("email", "pupkin@email.mail");
for (Map.Entry<String, String> entry : nameByValue.entrySet()) {
System.out.println(entry.getKey() + " = " + entry.getValue());
}
Через стандартный цикл:
int numer[] = {4, 8, 16, 32, 64, 128};
for (int i = 0; i < numer.length; i++) {
System.out.println(numer[i]);
}
List<String> items = Arrays.asList("1", "abc");
for (int i = 0; i < items.size(); i++) {
String word = items.get(i);
System.out.println(word);
}
Map<String, String> nameByValue = new HashMap<>();
nameByValue.put("name", "Vasya");
nameByValue.put("email", "pupkin@email.mail");
// Через for:
// for (Iterator<Map.Entry<String, String>> it = nameByValue.entrySet().iterator(); it.hasNext();) {
//
// Через while более предпочтительнее чем через for
Iterator<Map.Entry<String, String>> it = nameByValue.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, String> entry = it.next();
System.out.println(entry.getKey() + " = " + entry.getValue());
}
Можно. Но придется для foreach
сгенерировать коллекцию с индексами.
Чтобы код перебора коллекции был короче. Пример:
int numer[] = {4, 8, 16, 32, 64, 128};
for (int i = 0; i < numer.length; i++) {
System.out.println(numer[i] + " * 2 -> " + numer[i] * 2);
}
System.out.println();
for (int i : numer) {
System.out.println(i + " * 2 -> " + i * 2);
}
Код:
static List<Integer> getRange(int length) {
List<Integer> items = new ArrayList<>();
for (int i = 0; i < length; i++) {
items.add(i);
}
return items;
}
public static void main(String[] args) throws Exception {
int numer[] = {4, 8, 16, 32, 64, 128};
int denom[] = {2, 2, 4, 4, 2, 8};
for (int i = 0; i < numer.length; i++) {
System.out.println(numer[i] + " / " + denom[i] + " равно " + numer[i] / denom[i]);
}
System.out.println();
for (int i : getRange(numer.length)) {
System.out.println(numer[i] + " / " + denom[i] + " равно " + numer[i] / denom[i]);
}
}
Консоль:
4 / 2 равно 2
8 / 2 равно 4
16 / 4 равно 4
32 / 4 равно 8
64 / 2 равно 32
128 / 8 равно 16
4 / 2 равно 2
8 / 2 равно 4
16 / 4 равно 4
32 / 4 равно 8
64 / 2 равно 32
128 / 8 равно 16
foreach
работает c итераторами.
List<String> someIterable = List.of("1", "2");
for (Iterator<String> i = someIterable.iterator(); i.hasNext();) {
String item = i.next();
System.out.println(item);
}
Этот цикл эквивалентен записи:
for(String str : someIterable){
System.out.println(item);
}
У обычного массива итератор отсутствует.
Запись вида:
for (int numeri : numer) {
System.out.println(numeri);
}
Является синтаксическим сахаром, так как преобразуется в следующий вид
int len = numer.length;
for (int i = 0; i < len; i++) {
int numeri = numer[i];
System.out.println(numeri);
}
Но тем не менее, foreach
спроектирован для работы с текущим элементом одной структуры, а вам необходимо взять i-ый элемент у двух массивов numer
и denom
Дополню ответ @gil9red информацией по другим сценариям использования for-each.
for-each, а точнее усовершенствованный цикл for (enhanced for loop), задумывался в первую очередь для облегчения работы с коллекциями через итератор. Поддержка массивов добавлена для единообразия кода.
Не все коллекции, которые поддерживают перебор через итератор, поддерживают обращение по индексу. Например, множество можно перебрать через for-each:
Set<String> letters = new HashSet<>(Arrays.asList("a", "b"));
for(String letter : letters) {
//...
}
При этом цикл пройдет по всем элементам множества, но порядок элементов не гарантируется. Обращение к элементу множества по индексу не имеет смысла:
for(int i=0; i<letters.size(); i++) {
letters.get(i); //такого метода нет
}
Т.о. как минимум для коллекций for-each нельзя заменить циклом for по индексу. Для коллекций for-each соответствует циклу for с итератором:
Collection c = ... ;
for (Iterator i = c.iterator(); i.hasNext(); ) {
String s = (String) i.next();
}
Перебор коллекции это операция, которая выполняется очень часто, поэтому в язык и ввели синтаксический сахар, который позволяет сократить код и, соответственно, избежать трудноуловимых ошибок при постоянном использовании одного и того же шаблонного кода. Такое обоснование дается в поправке к спецификации Java (JSR-201) в которой был введен усовершенствованный цикл for:
Enhanced for loops allow convenient iteration over collections, without the need for an explicitly defined iterator. This reduces the need for boilerplate iteration code and the corresponding opportunities for errors.
Усовершенствованный цикл for предостваляет удобный способ перебора коллекций, без необходимости явного указания итератора. Это сокращает необходимость создания шаблонного кода для перебора и снижает вероятность возникновения связанных с ним ошибок.
Собственно, по такой же причине в Java имеется три разных оператора цикла (for, while, do-while) хотя, технически, можно было бы обойтись любым из них.
Можно вывернуться конечно, используя список индексов, как в ответе @gil9red, либо используя счетчик:
int counter = 0;
for (int n : numer) {
System.out.println(n + " / " + denom[counter] + " равно " + n / denom[counter]);
counter++;
}
либо создав целую иерархию классов:
DivisionBatch divisions = new DivisionBatch(numer, denom);
for(Division division : divisions) {
System.out.println(division.getNumerator() + "/" + division.getDenominator() + " равно " + divison.getResult());
}
Но, по-моему, в данном примере преимущества for-each (сокращение кода для перебора) не проявляются и целесообразнее использовать for.
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Давненько не брал в руки шашку, как то решил переписать свою аппу под Android на толстого десктоп клиента и обнаружил, что Swing типа как бы умер
Есть две базы(PostgreSQL) дублирующие полностью друг другаВ нашем апи приложении раньше использовался один датасурс, т
Прошу объяснить, как работает указатель стека при рекурсивном вызове метода из самого себяПишу морской на Java
Мне нужно сделать, чтобы у меня три label были вверху окна (друг за другом) в полную ширину, один внизу окна, а в центре находилась формаМожет...