2016-07-04 2 views
0

У меня есть абстрактный класс Usuario и ArrayList<Usuario> с объектами его трех подклассов. Теперь я хочу выполнить итерацию через ArrayList и вернуть значение в зависимости от результата использования instanceof против этого объекта.Java use instanceof с итератором

Я получаю ошибку: java.util.NoSuchElementException.

Я полагаю, это из-за того, что итератор является объектом Iterator, а не из любого из подклассов от Usuario. Я прав? есть ли какое-либо решение для этого?

public int comprobarDni(String dniAComprobar, ArrayList<Usuario> listaUsuarios) { 
    Iterator<Usuario> itUsuarios = listaUsuarios.iterator(); 
    while (itUsuarios.hasNext()) { 
     if (dniAComprobar.equals(itUsuarios.next().getDni())) { 
      if (itUsuarios.next() instanceof UsuarioBiblioteca) { 
       return 1; 
      } else if (itUsuarios.next() instanceof Bibliotecario) { 
       return 2; 
      } else if (itUsuarios.next() instanceof BibliotecaExterna) { 
       return 3; 
      } 
     } 
    } 
    return 0; 
} 

ответ

2

Вы призываете itUsuarios.next несколько раз во время итерации.

Поэтому вы можете в конечном итоге вызвать его, а List уже был повторен полностью, что будет вызывать java.util.NoSuchElementException.

Рассмотрим присваивание значения Usuario один раз, и имея в виду, что вместо того, чтобы:

while (itUsuarios.hasNext()) { 
    // reference this instead of itUsuarios.nex() for next references 
    Usuario usuario = itUsuarios.next(); 

Или ...

Go с быстрой перечисления для очистки перспективных кода:

for (Usuario usuario: listaUsuarios) { 
    ... 
+0

Хороший ответ, за исключением расширенной 'for' петли не«быстро». Он делает то же самое, т. Е. Использует итератор. Это простой и понятный код, но это не быстрый код. Быть проще, это может быть быстрее написать, но это не то, как читается ваш текст. – Andreas

+0

@ Аndreas, если память служит, «быстрое перечисление» здесь просто синоним «усиление для цикла». Никаких претензий к каким-либо улучшениям производительности. Фактически, эта идиома на самом деле использует итератор за кулисами ... TL; DR быстрее записывать, такую ​​же производительность. – Mena

4

Iterator.next() возвращает следующий элемент и продвигает курсор. Это не то, что вы хотите, чтобы попробовать это вместо:

Usuario usuario = itUsuarios.next(); 
... 

if (usuario instanceof UsuarioBiblioteca) { 
    return 1; 
} else if (usuario instanceof Bibliotecario) { 
    return 2; 
} else if (usuario instanceof BibliotecaExterna) { 
    return 3; 
} 

С кодом рассмотрит следующий случай: listaUsuarios содержит только два элемента типа BibliotecaExterna. Ваш первый вызов next() вернет первый элемент, но поскольку тип не соответствует вам, вы вызываете второй вызов next(), который возвращает второй элемент. Опять же, тип не соответствует, поэтому вы отправляете третий звонок на next() (itUsuarios.next() instanceof BibliotecaExterna), но нет третьего элемента и, следовательно, вы получите NoSuchElementException.

0

Существует огромное заблуждение в вашем коде:

Если текущий элемент является экземпляром BibliotecaExterna он будет вызывать next() в первой если-заявление и проверить его против UsuarioBiblioteca. Но тогда элемент уже изменился.

Вместо хранить его в начале:

Usuario element = itUsuarios.next(); 
if(element instance of ...) 
...