Having trouble making my own iterator for a collections class - java

I'm getting the error "Iterator cannot be resolved to a type". I'm trying to take the storage class and add the code necessary to implement java's Collections class.
I dont think i'm allowed to import Iterator, i think i need to make my own.
public class storage {
private Object[] data = new Object[256];
// Don't allow access to anything not yet stored
private int nextEmptySlot = 0;
private int i=0;
public Object begin(){
return data[0];
}
public Object end(){
return data[nextEmptySlot];
}
//class Iterator() {
// public Storage data;
//}
public Iterator iterator() {
// returns a class that iterates over the data array
return new Iterator() {
public Object remove(){
for(int j=i+1 ; j<=nextEmptySlot-1 ; j++) {
this.data[j-1] = this.data[j];
}
return (this.data.data[i]);
}
public int hasNext(){
if(this.data.data[i+1] != null) return 1;
else return 0;
}
public Object next(){
i++;
if (hasNext()==1){
return this.data.data[i];
}
else if (hasNext()==0){
throw UnsupportedOperationException();
}
return this;
}
};
}
}

You need to import java.util.Iterator;

This code isn't even wrong; check out the Iterator methods:
http://download.oracle.com/javase/1.4.2/docs/api/java/util/Iterator.html
Your Iterator does not implement the java.util.Iterator interface; using the same name doth not make it one.
Look at your method:
public int hasNext()
The java.util.Iterator hasNext() returns a boolean.
This is utterly wrong.

Related

How to print elements from generic array list, using iterator in Java

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;
}

Writing an iterator for my own array list class in Java

I am writing an iterator method for my own array list class, however, when I try to test the class it says foreach loop is not applicable to MyArrayList. can anyone help me out with where I have gone wrong?
The class itself uses arrays of objects and the necessary methods to act like an arraylist (add, remove, get etc.)
Here is the class constructor and my iterator class:
public class MyArrayList {
public Object[] arrayList = new Object[5];
int length1 = 5;
public MyArrayList() {
}
public MyArrayList(Object[] arrayList) {
this.arrayList = arrayList;
length1 = arrayList.length;
}
public ArrayListIterator iterator(){
return new ArrayListIterator(this);
}
class ArrayListIterator<MyArrayList> implements Iterator<Object> {
private Object[] arrayListIterable;
private int count = 0;
public ArrayListIterator(Object[] x){
arrayListIterable = x;
}
public ArrayListIterator(MyArrayList myArrayList) {
}
public boolean hasNext(){
if(count < arrayList.length){
return true;
}else{
return false;
}
}
public Object next(){
int x = count;
count++;
return arrayListIterable[x];
}
}
Your MyArrayList class must implement Iterable<T> interface.
Check the javadoc for Iterable:
Implementing this interface allows an object to be the target of the "for-each loop" statement.

Interview: Collections Iterator

Hi guys i got this as an interview question and was having trouble with it. I am familiar with generics/collections & iterator but the manner i which the Collection is declared completely threw me.
Heres the question: Contained in the provided workspace is cocI, the start of a class that implements an Iterator that can be used to iterate a Collection of Collections. The Collection of Collections is passed into the constructor of the class. The Iterator should iterate through the contents depth-first.
For example, if the Collection of Collections looks like the following:
[0] – [“A”, “B”, “C”]
[1] – [“D”]
[2] – [“E”, “F”]
The iterator should then return the contents in the following order: “A”, “B”, “C”, “D”, “E”, “F”
Q.Provide implementations for the hasNext() and next() methods in cocI
Thanks
import java.util.Collection;
import java.util.Iterator;
public class cocI implements Iterator<Object> {
private Collection<Collection<Object>> _collOfColl = null;
public cocI(Collection<Collection<Object>> collofColl) {
_collOfColl = collofColl;
}
public boolean hasNext() {
// TODO implement this method
return false;
}
public Object next() {
// TODO implement this method
return null;
}
public void remove() {
throw new UnsupportedOperationException();
}
}
All you need to do is keep track of the current collection's iterator within the collection of collections. The hasnext() method, which is the tricky part, will then do one of two things: return true if the current iterator has more elements, if not search until we find a collection that has elements. If we exhaust all the collections, return false.
public class Cocl implements Iterator<Object> {
private Collection<Collection<Object>> _collOfColl = null;
private final Iterator<Collection<Object>> coClIterator;
private Iterator<Object> currentColIterator;
public Cocl(Collection<Collection<Object>> collofColl) {
_collOfColl = collofColl;
coClIterator = collofColl.iterator();
if (coClIterator.hasNext()) {
currentColIterator = coClIterator.next().iterator();
}
}
public boolean hasNext() {
if (currentColIterator == null) {
return false;
}
if (!currentColIterator.hasNext()) {
while (coClIterator.hasNext()) {
currentColIterator = coClIterator.next().iterator();
if (currentColIterator.hasNext()) {
return true;
}
}
return false;
} else {
return true;
}
}
public Object next() {
if (hasNext()) {
return currentColIterator.next();
}
throw new NoSuchElementException();
}
public void remove() {
throw new UnsupportedOperationException();
}
public static void main(String[] args) {
Collection<Object> one = Arrays.asList((Object) "A", (Object) "B", (Object) "C");
Collection<Object> two = Arrays.asList((Object) "D", (Object) "E");
Cocl cocl = new Cocl(Arrays.asList(one, two));
while (cocl.hasNext()) {
Object a = cocl.next();
System.out.println(a);
}
}
}
A couple of introductory remarks:
cocI is an odd class name; it should start with a capital letter.
The interface you are supposed to implement doesn't use generics effectively. You should be able to use a data type more specific than Object.
It is good practice to use the #Override annotation.
The solution involves an iterator for the outer collection and an iterator for the inner collection. When the inner iterator runs out of elements, it needs to be replaced with an iterator for the next collection. However, considering that a collection could be empty, the advancement needs to be done in a loop, which I've put in an advanceCollection() helper.
import java.util.Collection;
import java.util.Iterator;
import java.util.NoSuchElementException;
public class cocI<T> implements Iterator<T> {
private Iterator<Collection<T>> outerIterator;
private Iterator<T> innerIterator;
public cocI(Collection<Collection<T>> collofColl) {
this.outerIterator = collofColl.iterator();
advanceCollection();
}
#Override
public boolean hasNext() {
return this.innerIterator != null && this.innerIterator.hasNext();
}
#Override
public T next() {
if (this.innerIterator == null) {
throw new NoSuchElementException();
}
try {
return this.innerIterator.next();
} finally {
advanceCollection();
}
}
#Override
public void remove() {
throw new UnsupportedOperationException();
}
private void advanceCollection() {
while ((this.innerIterator == null || !this.innerIterator.hasNext())
&& this.outerIterator.hasNext()) {
this.innerIterator = this.outerIterator.next().iterator();
}
}
}
There is one slightly tricky piece of code I used:
try {
return this.innerIterator.next();
} finally {
advanceCollection();
}
It is roughly equivalent to:
T result = this.innerIterator.next();
advanceCollection();
return result;

How to implement iterator as an attribute of a class in Java

let's say I have this simple MyArray class, with two simple methods: add, delete and an iterator. In the main method we can see how it is supposed to be used:
public class MyArray {
int start;
int end;
int[] arr;
myIterator it;
public MyArray(){
this.start=0;
this.end=0;
this.arr=new int[500];
it=new myIterator();
}
public void add(int el){
this.arr[this.end]=el;
this.end++;
}
public void delete(){
this.arr[this.start]=0;
this.start++;
}
public static void main(String[] args){
MyArray m=new MyArray();
m.add(3);
m.add(299);
m.add(19);
m.add(27);
while(m.it.hasNext()){
System.out.println(m.it.next());
}
}
And then MyIterator should be implemented somehow:
import java.util.Iterator;
public class myIterator implements Iterator{
#Override
public boolean hasNext() {
// TODO Auto-generated method stub
return false;
}
#Override
public Object next() {
// TODO Auto-generated method stub
return null;
}
#Override
public void remove() {
// TODO Auto-generated method stub
}
}
MyIterator should iterate arr from MyArray class, from start to end values; both are also attributes of MyArray. So, as MyIterator should use MyArray attributes, how should MyIterator be implemented? Perhaps I can send the current object in the initialization:
it=new myIterator(this);
But I guess it's not the best soultion. Or maybe MyArray itself should implement Iterator interface? How is this solved?
EDIT:
Ok, thanks to everybody. This was a simple example of what I wnat to do, so don't care about fixed length array. Waht I really want to do is a circular FIFO, that's why start and end are the cursors.
This circular FIFO will be an array of pairs of ints with, e.g., size 300: int[][] arr=new int[300][2].
When iterating a circular array I have to take care if the counter arrives to the end and make it start from the beginning, so this is how I have solved it:
if (this.start >= this.end ) temp_end=this.end+this.buff.length;
else temp_end=this.end;
int ii;
int j=0;
int[] value=new int[2];
for(int i=this.start; i<temp_end; i++){
ii=i% this.arr.length;
value=this.buff[ii];
//do anything with value
}
But I would like to avoid worrying about these things and just iterate in a simple way, I can do this with iterator interface, but then I have 2 problems: the first one I already explained and has been solved by many answers, and the second one is that my array is made of pairs of ints, and I can't use iterator with primitive types.
Its very unusual to maintain an iterator as an instance variable of the class. You can only traverse the array once - probably not what you want. More likely, you want your class to provide an iterator to anyone that wants to traverse your array. A more traditional iterator is below.
Java 5+ code - I haven't tried to compile or run, so it may be contain errors (not near a dev machine right now). It also uses autobox'ing for converting Integer to int.
public class MyArray implements Iterable<Integer> {
public static class MyIterator implements Iterator<Integer> {
private final MyArray myArray;
private int current;
MyIterator(MyArray myArray) {
this.myArray = myArray;
this.current = myArray.start;
}
#Override
public boolean hasNext() {
return current < myArray.end;
}
#Override
public Integer next() {
if (! hasNext()) throw new NoSuchElementException();
return myArray.arr[current++];
}
#Override
public void remove() {
// Choose exception or implementation:
throw new OperationNotSupportedException();
// or
//// if (! hasNext()) throw new NoSuchElementException();
//// if (currrent + 1 < myArray.end) {
//// System.arraycopy(myArray.arr, current+1, myArray.arr, current, myArray.end - current-1);
//// }
//// myArray.end--;
}
}
....
// Most of the rest of MyArray is the same except adding a new iterator method ....
public Iterator<Integer> iterator() {
return new MyIterator();
}
// The rest of MyArray is the same ....
}
Also note: be careful of not hitting that 500 element limit on your static array. Consider using the ArrayList class instead if you can.
In my opinion it is better to implement MyArray as common Iterable object, so it can be used in a for statement.
My suggestion:
/**
* My array
*/
public class MyArray<TItem> implements Iterable<TItem>
{
/**
* Internal used iterator.
*/
private class MyArrayIterator<TItem> implements Iterator<TItem>
{
private MyArray<TItem> _array;
/**
* #param array The underlying array.
*/
public MyArrayIterator(MyArray<TItem> array)
{
this._array = array;
}
/**
* Gets the underlying array.
*
* #return The underlying array.
*/
public MyArray<TItem> getArray() {
return this._array;
}
#Override
public boolean hasNext() {
// TODO Auto-generated method stub
return false;
}
#Override
public TItem next() {
// TODO Auto-generated method stub
return null;
}
#Override
public void remove() {
// TODO Auto-generated method stub
}
}
public void add(int el){
// do add
}
public void delete(){
// do delete
}
#Override
public Iterator<TItem> iterator() {
// TODO Auto-generated method stub
return new MyArrayIterator<TItem>(this);
}
}
As I said you can use it in a for statement:
private static void test(MyArray<String> strArray)
{
for (String str: strArray) {
// do something
}
}
Iterator is an interface . Iterator<E> which means only Object can go here (E) .
Iterator<Integer> is legal but Integer<int> is not because int is primitive data type
You can change the array to the ArrayList and then iterate over this arraylist. I added getIterator() method that returns the arraylist.iterator() and test it in main() method
import java.util.ArrayList;
import java.util.Iterator;
public class MyArray {
int start;
int end;
ArrayList<Integer> arr;
public MyArray() {
this.start = 0;
this.end = 0;
arr = new ArrayList<Integer>(500);
}
public void add(int el) {
arr.add(el);
this.end++;
}
public void delete() {
arr.remove(arr.size()-1);
this.start++;
}
public Iterator<Integer> getIterator(){
return arr.iterator();
}
public static void main(String[] args) {
MyArray m = new MyArray();
m.add(3);
m.add(299);
m.add(19);
m.add(27);
Iterator<Integer> it = m.getIterator();
while(it.hasNext()){
System.out.println(it.next());
}
}
}
My suggestion is to let MyArray implement the interface java.lang.Iterable and create an instance of an iterator per iterator() call (as an anonymous class). Then you can use an instance of MyArray directly in a foreach construct:
public class MyArray implements Iterable {
// ...
// Only arr is needed now as an instance variable.
// int start;
// int end;
int[] arr;
// myIterator it;
/**
* From interface Iterable.
*/
public Iterator<Integer> iterator() {
return new Iterator<Integer>() {
// The next array position to return
int pos = 0;
public boolean hasNext() {
return pos < arr.length;
}
public Integer next() {
if(hasNext())
return arr[pos++];
else
throw new NoSuchElementException();
}
public void remove() {
throw new UnsupportedOperationException();
}
}
}
}
Update: According to BertF's comment I updated my code to make it clear, that the only instance variable for class MyArray is now arr. The state for the iterator is now inside the anonymous Iterator implementation. So you can create multiple iterator instances which don't interfere each other.
EDIT: this does not work for arrays of primitive types:
you could use Arrays for this:
it = new Arrays.asList(arr).subList(start, end).iterator();
END OF EDIT
If you really want to implement your own iterator, I would suggest an internal class in this scenario. This way you can access MyArray.this from myIterator.
public class MyArray {
....
private class myIterator implements Iterator{
....
}
}
MyArray should implement the Iterator as it is also responsible for maintaining the array. Simple encapsulation principle.

Is it possible to merge iterators in Java?

Is it possible to merge iterators in Java? I have two iterators and I want to combine/merge them so that I could iterate though their elements in one go (in same loop) rather than two steps. Is that possible?
Note that the number of elements in the two lists can be different therefore one loop over both lists is not the solution.
Iterator<User> pUsers = userService.getPrimaryUsersInGroup(group.getId());
Iterator<User> sUsers = userService.getSecondaryUsersInGroup(group.getId());
while(pUsers.hasNext()) {
User user = pUsers.next();
.....
}
while(sUsers.hasNext()) {
User user = sUsers.next();
.....
}
Guava (formerly Google Collections) has Iterators.concat.
Also the Apache Commons Collection have several classes for manipulating Iterators, like the IteratorChain, that wraps a number of Iterators.
You could create your own implementation of the Iterator interface which iterates over the iterators:
public class IteratorOfIterators implements Iterator {
private final List<Iterator> iterators;
public IteratorOfIterators(List<Iterator> iterators) {
this.iterators = iterators;
}
public IteratorOfIterators(Iterator... iterators) {
this.iterators = Arrays.asList(iterators);
}
public boolean hasNext() { /* implementation */ }
public Object next() { /* implementation */ }
public void remove() { /* implementation */ }
}
(I've not added generics to the Iterator for brevity.) The implementation is not too hard, but isn't the most trivial, you need to keep track of which Iterator you are currently iterating over, and calling next() you'll need to iterate as far as you can through the iterators until you find a hasNext() that returns true, or you may hit the end of the last iterator.
I'm not aware of any implementation that already exists for this.
Update:
I've up-voted Andrew Duffy's answer - no need to re-invent the wheel. I really need to look into Guava in more depth.
I've added another constructor for a variable number of arguments - almost getting off topic, as how the class is constructed here isn't really of interest, just the concept of how it works.
I haven't written Java code in a while, and this got me curious to whether I've still "got it".
First try:
import java.util.Iterator;
import java.util.Arrays; /* For sample code */
public class IteratorIterator<T> implements Iterator<T> {
private final Iterator<T> is[];
private int current;
public IteratorIterator(Iterator<T>... iterators)
{
is = iterators;
current = 0;
}
public boolean hasNext() {
while ( current < is.length && !is[current].hasNext() )
current++;
return current < is.length;
}
public T next() {
while ( current < is.length && !is[current].hasNext() )
current++;
return is[current].next();
}
public void remove() { /* not implemented */ }
/* Sample use */
public static void main(String... args)
{
Iterator<Integer> a = Arrays.asList(1,2,3,4).iterator();
Iterator<Integer> b = Arrays.asList(10,11,12).iterator();
Iterator<Integer> c = Arrays.asList(99, 98, 97).iterator();
Iterator<Integer> ii = new IteratorIterator<Integer>(a,b,c);
while ( ii.hasNext() )
System.out.println(ii.next());
}
}
You could of course use more Collection classes rather than a pure array + index counter, but this actually feels a bit cleaner than the alternative. Or am I just biased from writing mostly C these days?
Anyway, there you go. The answer to you question is "yes, probably".
public class IteratorJoin<T> implements Iterator<T> {
private final Iterator<T> first, next;
public IteratorJoin(Iterator<T> first, Iterator<T> next) {
this.first = first;
this.next = next;
}
#Override
public boolean hasNext() {
return first.hasNext() || next.hasNext();
}
#Override
public T next() {
if (first.hasNext())
return first.next();
return next.next();
}
}
Starting with Java 8 and later this can be done without external dependencies using Stream API. This also allows concatenation of iterator with other types of streams.
Streams.concat(StreamSupport.stream(<iter1>, false), StreamSupport.stream(<iter2>, false));
move your loop to a method and pass the iterator to method.
void methodX(Iterator x) {
while (x.hasNext()) {
....
}
}
an iterator comes FROM a collection or a set.
why not use the method already available
Collection.addAll(Collection c);
and then create your iterator from the last object.
this way, your iterator will iterate all the contents of both collection.
You can use my version of an extendable iterator. It uses a double-ended queue of iterators which to me makes sense:
import java.util.Deque;
import java.util.Iterator;
import java.util.concurrent.ConcurrentLinkedDeque;
public class ExtendableIterator<T> implements Iterator<T> {
public Deque<Iterator<T>> its = new ConcurrentLinkedDeque<Iterator<T>>();
public ExtendableIterator() {
}
public ExtendableIterator(Iterator<T> it) {
this();
this.extend(it);
}
#Override
public boolean hasNext() {
// this is true since we never hold empty iterators
return !its.isEmpty() && its.peekLast().hasNext();
}
#Override
public T next() {
T next = its.peekFirst().next();
if (!its.peekFirst().hasNext()) {
its.removeFirst();
}
return next;
}
public void extend(Iterator<T> it) {
if (it.hasNext()) {
its.addLast(it);
}
}
}
The Merged Iterator:
import static java.util.Arrays.asList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.NoSuchElementException;
public class ConcatIterator<T> implements Iterator<T> {
private final List<Iterable<T>> iterables;
private Iterator<T> current;
#SafeVarargs
public ConcatIterator(final Iterable<T>... iterables) {
this.iterables = new LinkedList<>(asList(iterables));
}
#Override
public boolean hasNext() {
checkNext();
return current != null && current.hasNext();
}
#Override
public T next() {
checkNext();
if (current == null || !current.hasNext()) throw new NoSuchElementException();
return current.next();
}
#Override
public void remove() {
if (current == null) throw new IllegalStateException();
current.remove();
}
private void checkNext() {
while ((current == null || !current.hasNext()) && !iterables.isEmpty()) {
current = iterables.remove(0).iterator();
}
}
}
The concat method to create an Iterable:
#SafeVarargs
public static <T> Iterable<T> concat(final Iterable<T>... iterables) {
return () -> new ConcatIterator<>(iterables);
}
Simple JUnit test:
#Test
public void testConcat() throws Exception {
final Iterable<Integer> it1 = asList(1, 2, 3);
final Iterable<Integer> it2 = asList(4, 5);
int j = 1;
for (final int i : concat(it1, it2)) {
assertEquals(j, i);
j++;
}
}
I would refactor the original design from:
Iterator<User> pUsers = userService.getPrimaryUsersInGroup(group.getId());
Iterator<User> sUsers = userService.getSecondaryUsersInGroup(group.getId());
To something like:
Iterator<User> users = userService.getUsersInGroup(group.getId(), User.PRIMARY, User.SECONDARY, ...);
You can try ConcatIterator from Cactoos:
Iterator<String> names = new ConcatIterator<>(
Arrays.asList("Sarah", "Mary").iterator(),
Arrays.asList("Jeff", "Johnny").iterator(),
);
Also check ConcatIterable, which concatenates Iterables.
In the Apache Commons Collections there is public static <E> Iterator<E> org.apache.commons.collections4.IteratorUtils.chainedIterator(Collection<Iterator<? extends E>> iterators) that says
Gets an iterator that iterates through a collections of Iterators one after another.
which should be what you want.
import java.util.Arrays;
import java.util.Iterator;
import org.apache.commons.collections4.IteratorUtils;
//also works: import org.apache.commons.collections.IteratorUtils;
class Scratch {
public static void main( String[] args ) {
final Iterator<String> combinedIterator = IteratorUtils.chainedIterator(
Arrays.asList( "a", "b", "c" ).iterator(),
Arrays.asList( "1", "2", "3" ).iterator()
);
while( combinedIterator.hasNext() ){
System.out.println( combinedIterator.next() );
}
// "abc123" will have been printed out
}
}
every Iterator object holds own memory location (adress), so you can't simply "merge" them. except if you extend iterator class and write your own implementation there.
If you are dealing with the same number of objects in both iterators an alternative solution would be to process two iterators in one loop like this :
while (iterator1.hasNext() && iterator2.hasNext()) {
// code
}

Categories