Java: альтернатива iterator.hasNext() при использовании for-each для циклического перемещения по коллекции

Я пытаюсь заменить петлю на основе итератора над списком Java с помощью оператора for-each, но код использует в некоторой точке iterator.hasNext(), чтобы проверить, достиг ли он последнего элемента в списке.

Есть ли что-то подобное для альтернативы for-each?

for (Object current : objectList) {
   if (last-element) 
      do-something-special
}

Ответы

Ответ 1

для каждого - это просто синтаксический сахар для версии итератора, и если вы проверяете скомпилированный байт-код, то вы заметите, что компилятор действительно изменил его на версию итератора.

С каждой формой вы не можете проверить, будет ли у вас больше элементов или нет. Просто оставайтесь с явным использованием итератора, если вам нужна эта функция.

Ответ 2

В дополнение к Luno ответ:

Iterator<MyClass> it = myCollection.iterator();
while(it.hasNext()) {
  MyClass myClass = it.next():
  // do something with myClass
}

переводит на:

for (MyClass myClass:myCollection) {
  // do something with myClass
}

Ответ 3

Как говорили другие - это невозможно.

Просто помните, что конструкция foreach не является be-all и end-all. Было введено для того, чтобы сделать очень общую задачу выполнения одних и тех же операций над каждым элементом коллекции, более простой для обозначения.

В вашем случае вы не хотите делать то же самое для каждого элемента, и, таким образом, цикл foreach не является правильным инструментом для задания. Попытка "взломать" его в этом глупо, просто используйте явный итератор в классическом для цикла.

Ответ 4

Цикл foreach (или расширенный цикл for) не имеет средств для отслеживания того, какой элемент выполняется в данный момент. Невозможно определить, какой индекс Collection обрабатывается, или есть ли больше элементов для обработки в Iterable.

Тем не менее, одним из способов решения проблемы является сохранение ссылки на объект, который в данный момент повторяется в цикле foreach.

Сохраняя ссылку на то, на что она обрабатывается на текущей итерации, можно было бы сохранить ссылку после завершения цикла foreach, а оставшееся в переменной будет последним элементом.

Это обходное решение будет работать только если и только если последний элемент является единственным элементом, который необходим.

Например:

String lastString = null;

for (String s : new String[] {"a", "b", "c"}) {
    // Do something.

    // Keep the reference to the current object being iterated on.
    lastString = s;
}

System.out.println(lastString);

Вывод:

c

Ответ 5

К сожалению, для каждой идиомы не разрешается проверять, является ли элемент первым или последним в списке. Это известное ограничение для каждого цикла. Я предлагаю вам просто продолжать использовать итератор.

Если вы также можете проверить первый элемент вместо последнего, например, если вы выполняете конкатенацию строк, вы можете изменить на что-то вроде:

boolean first = true;
for (Element e : list) {
  if (!first) {
    //do optional operation
  }
  //do other stuff
  first = false;
}

но я бы предпочел использовать итератор.

Ответ 6

Если вы хотите остановиться с каждым из них, возможно, что-то вроде этого:

if (objectList.indexOf(current)==objectList.size()-1) break;

Ответ 7

int nElts = objectList.size();
int n = 0;
for (...) {
  if (++n == nElts) ...

- лучшее, что я могу придумать.

Ответ 8

Есть два возможных случая, когда вы хотели бы сделать это.

  1. Вам нужно что-то сделать после достижения последнего элемента: в этом случае вам просто нужно поместить свой код за пределы цикла.

    for(Object item:theLinkedList){

    }
    System.out.println("something special")
вам нужно каким-то образом изменить последний элемент или использовать информацию, связанную с последним элементом. В этом случае вы должны использовать ** LinkedList ** для доступа к последнему элементу

    for(Object item:theLinkedList){

    }
    Object last=theLinkedList.getLast();
    System.out.println("last");

Ответ 9

да, вы можете здесь, как бы я это сделал, если вы не хотите использовать явный синтаксис итератора:

for (Object current : objectList) {
   if (objectList.getLast().equals(current)) 
      do-something-special
}

Ответ 10

В дополнение к bayer вам нужно сделать это немного иначе, потому что нет метода getLast(). Но вместо этого вы можете использовать этот objectList.size() - 1.

for (Object current : objectList) {
   if (objectList.get(objectList.size() - 1).equals(current)) 
      do-something-special
}

Ответ 11

Просто сохраните подсчет повторения цикла, образец:

    int loop = 0;

    for(Item item : items) {

        if(loop == 0) {
            //Is First Item
        }

        if(loop != items.size()-1) {
            //Has Next Item
        }

        if(loop == items.size()-1) {
            //Is Last Item
        }

        //Must Be Last Statement 
        loop++;
    }

Он похож на цикл for(int i = 0; i < items.size(); i++);

items.size() используется для списков и items.length для массивов;