I have an abstract class Usuarioand an ArrayList<Usuario> with objects of its three subclasses. I now want to iterate through the ArrayList and return a value depending of the result of using instanceof against that object.
I get an error: java.util.NoSuchElementException.
I suppose it is because of the iterator being an object of Iterator and not from any of the subclasses from Usuario. Am I right? is there any solution for that?
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;
}
Iterator.next() returns the next item and advances the cursor. That's not what you want so try this instead:
Usuario usuario = itUsuarios.next();
...
if (usuario instanceof UsuarioBiblioteca) {
return 1;
} else if (usuario instanceof Bibliotecario) {
return 2;
} else if (usuario instanceof BibliotecaExterna) {
return 3;
}
With your code consider the following case: listaUsuarios only contains two elements of type BibliotecaExterna. Your first call to next() will return the first element but since the type doesn't match you issue the second call to next() which returns the second element. Again the type doesn't match so you issue a third call to next() (itUsuarios.next() instanceof BibliotecaExterna) but there is no third element and hence you'll get the NoSuchElementException.
You are invoking itUsuarios.next multiple times during your iteration.
Therefore you might end up invoking it while the List has already been iterated fully, which will throw java.util.NoSuchElementException.
Consider assigning a Usuario value once, and referring to that instead:
while (itUsuarios.hasNext()) {
// reference this instead of itUsuarios.nex() for next references
Usuario usuario = itUsuarios.next();
Or...
Go with fast enumeration for cleaner looking code:
for (Usuario usuario: listaUsuarios) {
...
There is a huge misconception in your code:
If your current element is an instance of BibliotecaExterna it will call next() in the first if-statement and check it against UsuarioBiblioteca. But then the element has already changed.
Instead store it at the beginning:
Usuario element = itUsuarios.next();
if(element instance of ...)
...
Related
How to check whether the list has only one non-null element and if so retrieve the same using java 8 or Streams?
One of my method return list of objects which needs to check whether the returned list contains only one non null object, If so it creates a map as defined below else, needs to log an error as below.
`public void myMethod() {
List<MyClass> tst = getAll();
if(!tst.isEmpty() ) {
if( tst.size() == 1) {
if(tst.get(0)!= null) {
MyClass class1 = tst.get(0);
Map<Integer,MyClass> m =
Stream.of(class1).collect(Collectors.toMap(MyClass:: getId,
Function.identity()));
}
}
else {
LOGGER.error("Multiple object found - {} object", tst.size());
}
}`
I'm looking for a way to write in a clean and standard format as I have three If conditions
Something like that should do the trick but it's not using streams. If you really need to use streams say so and I'll give it a try with it :)
int notNullCount = 0;
Object myNotNullElement;
for (Object element : myArray){
if (notNullCount > 1){
//Throw exception or do whaterver you need to do to signal this
break;
}
if (element != null){
myNotNullElement = element;
notNullCount++;
}
}
How do I check if the next element in the list is null ?
while(it.hasNext()){
System.out.println(it.next()+"\n");
}
this is how I tried, but when the last element is null it prints it as null.
I tried to change it
while(it.hasNext()){
if(it.next()==null){
}else
System.out.println(it.next()+"\n");
}
but this just makes it worst because some of the elements don't even print!
This is my Iteration method/anonymous class
public Iterator<Filmi> iterator3DFilms ()throws FilmiException{
if(filmList.isEmpty())
throw new FilmiException("No Films on the list");
return new Iterator<Filmi>(){
private int index=0;
public boolean hasNext(){
return index <filmList.size();
}
public Filmi next(){
Filmi lb = filmList.get(index++);
if(lb.is3D()== true)
return lb;
if(hasNext())
return next();
return null;
}
public void remove(){}
};
}
The null print only happens at the last element
Thank you.
Naturally, code like
if (it.next() == null){
} else {
System.out.println(it.next()+"\n");
}
will consume every other non-null element, as you are observing. Plus calling it.next() without checking it.hasNext() is a recipe for disaster.
Why not write
Foo/*ToDo - use the correct type here*/ foo = it.next()
if (foo != null){
/*ToDo*/
}
instead?
No it cannot work this way because if it.next() is not null you call it.next() twice which will make you skip a value that could not even be available.
Use a variable instead as next:
Object o = it.next();
if (o != null) {
...
}
you should use stream instead of iterator.
filmList.stream().filter(film->film!=null).filter(film->film.is3D())
Edit:
or, if you'r not in Java 8 :
Predicate<Film> isNotNullAnd3D = new Predicate<Person>() {
public boolean apply(Film f) {
return f != null && f.is3D();
}
};
Collection2.filter(filmList, isNotNullAnd3D)
You never mentioned why you use iterators explicitly in the first place.
Why not use implicit iterator notation like this ? :
for (Film film : filmList) {
if (film != null ){
....
}
}
Additionally to what others said: in case you are doing a for-each loop with a primitive type like int
for (int node : input) {
doSomething(node);
}
you might want to consider using the Wrapper class instead:
for (Integer node : input) {
if (node == null) throw new IllegalArgumentException();
doSomething(node);
}
For my data structures class, we have to create our own Stack data type and the implementation for it as a project. The problem I'm running into is when the professor asked us to implement an equals(Object object) method. Heres what I have so far...
package stack;
import list.*;
public class Stack <E>
implements StackADT<E>//the interface
{
List <E> values;
public Stack()
{
values = new ArrayList<E>();
}
public E push(E value)
{
values.add(value);
return value;
}
public E pop()
{
return values.remove(values.size()-1);
}
public E peek()
{
return values.get(values.size()-1);
}
/** #return true only if this Stack is empty */
public boolean isEmpty()
{
return (values.size()==0);
}
/** Clear this stack, to make it an empty stack */
public void clear()
{
for (int i = 0; i < values.size()-1; i++)
{
pop();
}
}
public String toString()
{
String result = "[";
for (int i = 0; i<values.size(); i++)
{
if (i == values.size()-1)
{
result = result + values.get(i);
}
else
{
result = result + values.get(i) +",";
}
}
result = result + "]";
return result;
}
public boolean equals (Object object)
{
if (!(object instanceof StackADT))
{
return false;
}
StackADT <E> otherStack = new Stack<E>();
for(Object o: object)//heres where i run into trouble
{
otherStack.push(o);
}
for (int i=0;i<values.size()-1;i++)
{
if (!(values.get(i).equals(otherStack.pop())))
{
return false;
}
}
return true;
}
}
Our Stack is pretty much an ArrayList which we also built in our class. the problem is, I cant add the Object object into a stack because its not something thats iteratable(?able to be iterated over). Is there a better way to do this? I would think a get() would work, since the Stack I create is an ArrayList, but whenever I use get() on otherStack, it can't find the method. I had a temporary solution when I tried casting object as a stack(I hope im using the right terminology). It looked something like this
Stack otherStack = (Stack) object;
for (int i=0;i<values.size()-1;i++)
{
if (!(values.get(i).equals(otherStack.pop())))
{
return false;
}
}
return true;
}
this seemed to work, but when pop() was called on otherStack, the values in the original list(the one that becomes otherStack) that was passed into the equals() method we're also popped from the original list, leading to an incorrect result. Is there a better way to do this without adding in any other methods? I'm trying to stick as close to the formula set up by my professor as possible, so I dont want to add any extra fields or methods.
any and all help is appreciated
An equals method is not supposed to create anything, not even a temporary object. Rather than creating a new otherStack, cast the object that you have checked to be StackADT, like this:
// This should be the first line of any equals() implementation:
if (object == this) {
return true;
}
// You've got this part right: you need to check the other object's type
if (!(object instanceof StackADT)) {
return false;
}
// Now that you know the type, cast the other object to StackADT<E>
StackADT<E> otherStack = (StackADT<E>)object;
// The next step is to check the sizes:
if (values.size() != otherStack.values.size()) {
return false;
}
// Finally, go through the individual elements in a loop
In the loop that follows, do not pop the other stack. Do not do anything that can modify it. Simply go through the underlying storage (i.e. values), and check elements one by one.
Don't forget to override hashCode as well: you need to do it every time when you override equals for the object to fulfill the contract specified by java.lang.Object.
I am trying to create hasnext() has next() methods for a iterator so that the output of a collection will be:
"printing","elements","in","order","from","collection"
input:
[A] - ["printing", "elements", "in"]
[B] - ["order"]
[C] - ["from", "collection"]
At the moment I have my methods looking like:
public MyIterator(Collection<Collection<Object>> myColl) {
_myColl = myColl;
}
public boolean hasNext() {
if(myColl.next != null)
{
return true
}
return !queue.isEmpty();
}
public Object next() throws java.util.NoSuchElementException {
//Dont really know what to put in here....
}
Any pointers would be appreciated
The best way to do is declare a counter and increment when you are accessing the has next. In the logic if i will express, then that will be like this.
private int counter = 0;
public boolean hasNext(){
counter = counter < collection.size()? counter + 1: counter;// increment
return counter < collection.size();// check and give the appropriate boolean value
}
public T next(){
return collection.get(counter);// to get the counter number of element
}
where counter is the private variable in the class and T is the generic type on which type of object the collection is build up. like
Collection<String>
This answer is all about logic. it may or may not contain the exact code.
Well, i don't understand your question really.. why you can't just use the normal iterator?
I will say to you how to create a basic iterator, to let you understand how things works in basic then adapt your solution:
Suppose we need to iterate over a List<T> and you want to create an helper class to do it.
class ListIterator<T>
You need two private fields
The list to iterate
The pointers to the last item
and 3 methods + 1 constructor
hasNext() -> Boolean, returns true if there are more items to iterate
next() -> Return the next element in the list
reset() -> Reset the interal pointer
constructor -> Just takes as argument the list to iterate
How will look the fields?
private final List<T> list; // The list where this call will iterate
private int pointer; // The pointer to the next iterable item
As said in the description, the constructor will take the reference to the list so it will just be
public ListIterator(List<T> list)
{
this.list = list;
pointer = 0;
}
save the reference and set pointer to 0 (start).
Let's talk about the methods:
hasNext should check if our current pointer has reached the size of the list.
So it will just be (pointer != list.size())
public boolean hasNext()
{
return (pointer != list.size());
}
Will be true if more items are avaitable, false otherwise.
next return the next item if any. Could be simplified by using our hasNext method so it will be
public T next()
{
if (!hasNext())
throw new NoSuchElementException("no field");
return list.get(pointer++);
}
Things to notice:
T is the return because our list is type T
list.get(pointer++) we first get the item from the list in position pointer then we add 1 to the pointer
The reset method is just a pointer = 0.
public void reset()
{
pointer = 0;
}
How to use it?
Like other iterators, create a new object of type ListIterator and pass the list to iterate.
List<String> test = new ArrayList<String>();
test.add("Hello");
test.add("World");
test.add("Whatsapp");
ListIterator<String> iterator = new ListIterator<String>(test);
while (iterator.hasNext())
{
System.out.println(iterator.next());
}
I've got an object of type DocObject that contains an arraylist of DocObjects within it called children, each of which may or not contain children themselves. I'm writing a function for this object called replace() that takes a child to be searched for, and if the DocObject contains that child then the child should be replaced with newObj. I have looked around the site and searched google but nothing I've seen is working. The code below shows what I've tried:
public void replace(DocObject oldObj, DocObject newObj) {
for (DocObject child : children ) {
if (child == oldObj) {
child = newObj;
}
}
}
And this (this causes an overflow exception):
public void replace(DocObject oldObj, DocObject newObj) {
if (children.indexOf(oldObj) != -1)
children.set(children.indexOf(oldObj), newObj);
for (DocObject child : children)
child.replace(oldObj, newObj);
}
This isn't replacing the child, however, and I have checked to see that the if statement is working correctly and its condition met. How can I replace oldObj with newObj?
I would not recommend looping using the for (X x: thingWithXs) construct while manipulating the list. I would recommend using indexOf to search for the desired object and if it cannot be found, recursively calling replace on the children of the object you are looking at.
Note that you'll have to modify your replace method to accept the list of objects as an argument:
public boolean replace(List<E> list, E oldE, E newE) {
if (list == null) {
return false;
}
int index = list.indexOf(oldE);
if (index > 0) {
list.set(index, newE);
return true;
}
for (int i = 0, l = list.size(); i < l; i++) {
List<E> children = list.get(i).children;
if (replace(children, oldE, newE)) {
return true;
}
}
return false;
}
Disclaimer: The above code has not been tested. It should give you an idea as to how it can be done. Essentially what it comes down to is checking if the element you are looking for is in the list, and if not, iterating over the list and checking each set of children.