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();
}
Related
I'm working in a school project, where I want to implement the Iterator design pattern. I want to use generic arrays.
Container.java
public interface Container {
Iterator getIterator();
}
Iterator.java
public interface Iterator <T> {
boolean hasNext();
T next();
}
TransactionRepository.java
public class TransactionRepository<T> implements Container {
public TransactionRepository(){
userTransactions = new ArrayList<>();
}
public List<T> userTransactions;
#Override
public Iterator <T> getIterator() {
return new UserTransactions();
}
private T t;
public void add(T t) {
this.t = t;
}
public T get() {
return t;
}
private class UserTransactions implements Iterator <T> {
int index;
#Override
public boolean hasNext() {
return index < userTransactions.size();
}
#Override
public T next() {
if(this.hasNext())
return userTransactions.get(index);
return null;
}
}
}
In my other class, I add the elements to the list by first creating the TransactionRepository object like this: TransactionRepository<String> companyName = new TransactionRepository<String>();.
Then I add elements to the array with the add method companyName.add("CompanyName");. After that I want to print the array using Iterator, but It just won't print the elements. I have tried multiple variations, but none of them worked.
Iterator <String> stringIterator = companyName.getIterator();
while (stringIterator.hasNext()) {
System.out.println("Name : " + companyName.get());
}
With the current implementation List<T> userTransactions is never updated.
In this case userTransactions.size() in hasNext() method will always return 0 so the result of method will be false.
Moreover, you should use stringIterator.next() instead of companyName.get(). Since you implement your own iterator you don't want to use get() method at all.
There is also a need to update index counter variable after calling next() method.
#Override
public T next() {
if (this.hasNext())
return userTransactions.get(index++);
return null;
}
Change modifier on userTransactions to private final as it should be referenced just with iterator.
Code with proposed improvements:
public class TransactionRepository<T> implements Container {
public TransactionRepository() {
userTransactions = new ArrayList<>();
}
public List<T> userTransactions;
#Override
public Iterator<T> getIterator() {
return new UserTransactions();
}
public void add(T t) {
userTransactions.add(t);
}
private class UserTransactions implements Iterator<T> {
int index;
#Override
public boolean hasNext() {
return index < userTransactions.size();
}
#Override
public T next() {
if (this.hasNext()) {
return userTransactions.get(index++);
}
return null;
}
}
}
It seems that you are never adding elements to your userTransactions List on the add method
You add() method doesnt add anything to your list , it's just like a setter of the attribute t , you should use it to add elements to the list instead
public void add(T t) {
userTransactions.add(t);
}
There is also another problem , the index , your next() method gets the index element while you didnt initialise your index variable , i recommand you to do it in this way :
int index = 0 ;
...
public T next() {
if(this.hasNext())
int temp = index;
index++;
return userTransactions.get(temp);
return null;
}
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();
}
}
I would like to write a class(called Seii) that is basically a sequence of whole numbers starting from s0. s0 is set in the constructor:
se + 1 = 3*(se/2)
The catch is: A for-loop should be able to iterate through the objects of this class and spit out the elements of the sequence (without the starting number s0). Also, the sequence ends with the first element larger than 42.
For example:
for(int i:new Seii(2)){
System.out.println(i)
gives out:
3,4,6,9,10,15,16,24,36,54
I would like to do it using iterators. Can someone pls help me out?
My idea would be to rewrite the next() method so that it does the calculation for the next element of the sequence, but i'm not getting anywhere with the logic of this.
public class Seii<T> implements Iterator {
private ArrayList<Integer> list = new ArrayList<>();
Iterator<Integer> it = list.iterator();
private final int size;
public Seii(int size) {
this.size = size;
}
int seii = 0;
#Override
public boolean hasNext() {
// TODO Auto-generated method stub
return false;
}
#Override
public Object next() {
if ((size % 2) == 0) {
seii = 3 * (seii/2);
return seii;
}
}
}
}
This is my implementation.
Seii should implement Iterable<Integer>, which will allow it to support the enhanced for loop syntax. The easiest way of doing that, IMHO, is just to have an inner Iterator class which implements your logic:
public class Seii implements Iterable<Integer> {
private class SeiiIterator implements Iterator<Integer> {
#Override
public boolean hasNext() {
return value <= 42;
}
#Override
public Integer next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
value = 3 * (value / 2);
return value;
}
}
private int value;
public Seii(int value) {
this.value = value;
}
#Override
public Iterator<Integer> iterator() {
return new SeiiIterator();
}
}
You do not need to store the sequence, so the array list can be removed from your implementation. All you need is the last value, which can be set in the constructor:
// This is a wrapper class that constructs iterators.
// It is used for plugging in your code into enhanced "for" loop
class Seii implements Iterable<Integer> {
private int current;
private int max;
public Seii(int current, int max) {
this.current = current;
this.max = max;
}
#Override
public Iterator<Integer> iterator() {
return new SeiIterator(current, max);
}
}
// This is the actual iterator that maintains state
// and produces the desired sequence.
class SeiIterator implements Iterator<Integer> {
private int current;
private int max;
public SeiIterator(int current, int max) {
this.current = current;
this.max = max;
}
#Override
public boolean hasNext() {
return current < max;
}
#Override
public Integer next() {
current = (3*current)/2;
return current;
}
#Override
public void remove() {
throw new UnsupportedOperationException();
}
}
Note that in order to use your iterator in an enhanced for loop you need to wrap it in an Iterable<Integer>.
Demo.
Your Seii class should implement Iterable<Integer> not Iterator, since that's the interface required by the enhanced for loop. It would have an iterator method that returns an instance of a class that implements the Iterator<Integer> interface.
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 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.