I have generic class MyArray where private member is ArrayList, and inside is implemented iterator.
In Main is given some MyArray with strings and I want to delete all "test" from it... Problem is in iterator which method remove doesn't work
Here is how class looks like:
public class MyArray<E> {
private ArrayList<E> list;
public MyArray() {
list = new ArrayList<E>();
}
public int length() { return list.size(); }
public E at(int pos) { return list.get(pos); }
public void add(E val) { list.add(val); }
public void remove(int pos) { list.remove(pos); }
public class MyIterator implements Iterator<E>{
int index;
#Override
public boolean hasNext() {
return index < list.size();
}
#Override
public E next() {
if (!hasNext())
throw new NoSuchElementException("no next value");
E tmp = list.get(index);
index++;
return tmp;
}
}
public Iterator<E> iterator() {
return new MyIterator();
}
public static void main(String[] args) {
MyArray<String> b = new MyArray<String>();
b.add("This");
b.add("is");
b.add("test");
b.add("please");
b.add("delete");
b.add("all");
b.add("test");
Iterator<String> iter = b.iterator();
while(iter.hasNext())
System.out.println(iter.next());
for(Iterator<String> i = b.iterator(); i.hasNext(); ) {
String tmp = i.next();
if (tmp.equals("test"))
i.remove();
}
Iterator<String> ite = b.iterator();
while(ite.hasNext())
System.out.println(ite.next());
}
}
Exception that I get is:
Exception in thread "main" java.lang.UnsupportedOperationException: remove
at java.util.Iterator.remove(Unknown Source)
at cas1.MyArray.main(MyArray.java:71)
You need to override remove() in your Iterator.
However, it'd be easiest to make your iterator() method return list.iterator(), rather than implementing it yourself:
public Iterator<E> iterator() {
return list.iterator();
}
Iterator in an interface, and you need to implement each of the Iterator methods in MyIterator that you intend to call.
MyIterator that you defined doesn't override Iterator.remove() and
the remove() defined in the Iterator interface is defined as a default method that throws UnsupportedOperationException :
default void remove() {
throw new UnsupportedOperationException("remove");
}
So override it simply to remove effectively the iterated element.
You can rely on ArrayList.Itr code :
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
ArrayList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
Related
I need to implement my own Iterator for my List class that functions like a Stack and implements java.lang.Iterable.
The Iterator method that is implemented in the List class should return an Iterator.
#Override
public Iterator<E> iterator() {
return new Iterator<>() {
private MyEntry<E> it = begin;
#Override
public boolean hasNext() {
if(pos.next != null) {
return true;
}
else {
return false;
}
}
#Override
public E next() {
if (!hasNext()) {
reset();
}
else {
it = it.next;
}
return it.o;
}
#Override
public void remove() {
}
};
}
The List itself works like a Stack. It has an begin Entry that marks the beginning of the List. Each Entry holds a reference to the next Entry. With the pos Element the List keeps track of its position. The advance() method allows you to pass through the list Entry by Entry. The elem() method returns the Value that the Entry holds at the position pos. The add() method adds an Entry at the end of the List. The delete() method removes the Entry at pos.
import java.util.Iterator;
import java.util.NoSuchElementException;
public class MyList<E> implements Cloneable, java.lang.Iterable {
public MyList() {
pos = begin = new MyEntry<E>();
}
public boolean empty() {
return begin.next == null;
}
public boolean endpos() { // true, if end has been reached
return pos.next == null;
}
public void reset() {
pos = begin;
}
public void advance() {
if (endpos()) {
throw new NoSuchElementException("Already at the end of this List");
}
pos = pos.next;
}
public E elem() {
if (endpos()) {
throw new NoSuchElementException("Already at the end of this List");
}
return pos.next.o;
}
public void add(E x) {
MyEntry<E> newone = new MyEntry<E>(x, pos.next);
pos.next = newone;
}
public void delete() {
if (endpos()) {
throw new NoSuchElementException("Already at the end of this List");
}
pos.next = pos.next.next;
}
The Entrys that the List holds have a Generic Value o and a reference next tho the next MyEntry
class MyEntry<E> {
MyEntry<E> next;
E o;
MyEntry() {
this(null, null);
}
MyEntry(E o) {
this(o, null);
}
MyEntry(E o, MyEntry<E> e) {
this.o = o;
this.next = e;
}
}
But at the moment when I am testing it with my test class MyListTest I get the three test Strings out, but after that the Programm throws an NullPointerException in the next() method at return it.o
import org.junit.Test;
import java.util.*;
public class MyListTest {
#Test
public void test() {
MyList list = new MyList();
Iterator itr = list.iterator();
list.add("a");
list.add("b");
list.add("c");
while(itr.hasNext()) {
Object element = itr.next();
System.out.println(element + " ");
}
iter.remove();
while(itr.hasNext()) {
Object element = itr.next();
System.out.println(element + " ");
}
}
}
My Question is why the Iterator runs out of bounds after the last Entry and how I can prevent that.
So the Solution was that the hasNext() method
#Override
public boolean hasNext() {
if(pos.next != null) {
return true;
}
else {
return false;
}
}
Should have been
#Override
public boolean hasNext() {
if(it.next != null) {
return true;
}
else {
return false;
}
}
Because neither hasNext() nor next() should interfere with the pos element.
The Iterator should keep its own position independent from the rest of the class.
I am trying to figure out how Guava is creating the iterator that cycles infinitely over itself but I cannot figure it out.
public static <T> Iterable<T> cycle(final Iterable<T> iterable) {
checkNotNull(iterable);
return new FluentIterable<T>() {
#Override
public Iterator<T> iterator() {
return Iterators.cycle(iterable);
}
#Override public String toString() {
return iterable.toString() + " (cycled)";
}
};
}
public static <T> Iterator<T> cycle(final Iterable<T> iterable) {
checkNotNull(iterable);
return new Iterator<T>() {
Iterator<T> iterator = emptyIterator();
Iterator<T> removeFrom;
#Override
public boolean hasNext() {
if (!iterator.hasNext()) {
iterator = iterable.iterator();
}
return iterator.hasNext();
}
#Override
public T next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
removeFrom = iterator;
return iterator.next();
}
#Override
public void remove() {
checkRemove(removeFrom != null);
removeFrom.remove();
removeFrom = null;
}
};
}
However it does not show how exactly this is achieved. I am missing something probably.
This part of code
if (!iterator.hasNext()) {
iterator = iterable.iterator();
}
checks if old iterator has no more elements. When this is true it simply gets new iterator which will let us start again.
The list over which I want to iterate, contains an Array.
What I am trying to do is to make it possible to create an Iterator within the Iterator, so that I am able to iterate over the array in every Listelement.
I tried it this way:
#Override
public Iterator<A> iterator() {
return new MyListIterator();
}
private class MyListIterator implements Iterator<A>, Iterable<B>
{
private Listelem current;
private MyListIterator()
{
this.current = head;
}
#Override
public boolean hasNext()
{
return this.current != null;
}
#Override
public A next()
{
A next = this.current.getValue();
this.current = this.current.getSuccessor();
return next;
}
#Override
public void remove()
{
Listelem tmp = head;
while( tmp.getSuccessor().getSuccessor() != this.current )
{
tmp = tmp.getSuccessor();
}
tmp.setSuccessor(this.current);
}
#Override
public Iterator<B> iterator() {
return new MyInnerListIterator();
}
private class MyInnerListIterator implements Iterator<B>
{
private int currentIndex = 0;
private B[] array = current.getAssoc();
#Override
public boolean hasNext() {
return currentIndex < array.length && array[currentIndex] != null;
}
#Override
public B next() {
return array[currentIndex++];
}
#Override
public void remove() {
}
}
}
The problem is, when I am creating the first Iterator with iterator() the object does not contain the method iterator().
Can somebody explain to my why this is not working, and how to do it different?
The problem is that iterator returns an Iterator, even though in this case it happens to also be a MyListIterator. Class Iterator does not have an iterator() function. You need to have iterator() return a MyListIterator, so that you can use methods not in the Iterator interface.
It is likely simpler however, to simply use a for:in loop:
List<Object[]> list = ....
for (Iterator<Object[]> it = list.iterator(); it.hasNext();) {
Object[] arr = it.next();
for (Object o : arr) {
...
}
}
And if you don't need to remove elements from the list, then you can replace the iterator use with another for:in
I am trying to implement an Iterator with Iterable in Java, here is what I have so far:
public class keysIterator<A> implements Iteratble<A<{
A[] elements;
int nextElement;
keysIterator(A[] elements, int nextElement) {
this.elements = elements;
this.nextElement = 0;
}
public boolean hasNext() {
return this.nextElement < elements.length;
}
public A next() {
A result = elements[nextElement];
nextElement = nextElement + 1;
return result;
}
public void remove() {
// TODO Auto-generated method stub
}
public Iterator<A> iterator() {
// TODO Auto-generated method stub
}
}
I need help writing the remove and iterator methods, any assistance is greatly appericated.
Thank you.
Having an Iterator implement Iterable doesn't make sense to me
Something Iterable has an iterator() method, that returns an Iterator.
Also an iterator usually doesn't hold the data but refers to someother instance that has the data.
So usually
class Foo implements Iterable
{
public Iterator iterator() {
return new FooIterator();
}
}
class FooIterator implements Iterator {
// with methods as you've defined them
}
You are mixing up implementation of the Iterator interface with your Iterable class. Try this:
public class KeysIterable<A> implements Iterable<A> {
A[] elements;
int nElements;
private class KeysIterator<A> implements Iterator<A> {
int nextElement = 0;
public boolean hasNext() {
return nextElement < nElements;
}
public A next() {
A result = elements[nextElement];
nextElement = nextElement + 1;
return result;
}
public void remove() {
if (nextElement < nElements - 1) {
System.arraycopy(elements, nextElement + 1,
elements, nextElement, nElements - nextElement - 1);
}
nElements--;
}
}
public Iterator<A> iterator() {
return new KeysIterator<A>();
}
public KeysIterable() {
}
// other methods
}
It would probably be better to implement your Iterable class using an ArrayList instead of a generic array.
Use an ArrayList instead of an array, so you can just do:
public Iterator<A> iterator() {
return elements.iterator();
}
If you really want an array, you can always do:
public Iterator<A> iterator() {
return Arrays.asList(elements).iterator();
}
I am trying to write a class that implements a tree using an array and I need some help to write an Iterator method that which returns an iterator of the elements stored in the tree.
Solution:
public Iterator<E> iterator() {
return new Iterator<E>() {
private int index = 0;
public boolean hasNext() {
return index < ArrayTree.this.size();
}
public E next() {
if (!hasNext()) {
return new NoSuchElementException();
}
return ArrayTree.this.tree[index++];
}
public void remove() {
return new OperationNotSupported();
}
}
}
Without examining your implementation very closely, a very simple implementation might be
public Iterator<E> iterator() {
return new Iterator<E>() {
private int index = 0;
public boolean hasNext() {
return index < ArrayTree.this.size();
}
public E next() {
if (!hasNext()) {
return new NoSuchElementException();
}
return ArrayTree.this.tree[index++];
}
public void remove() {
return new OperationNotSupported();
}
}
}
There are a couple of ways to go, but if your ArrayTree class implements Iterable and Iterator interfaces you'll be on your way.