I am having trouble with my code to add iterator support to ArrayList
this is the class i create to implement Iterator
class MyArrayListIterator<E> implements Iterator<E> {
private E[] list = null;
private int currentIndex = 0;
#Override
public boolean hasNext() {
if (currentIndex < list.length) {
return true;
} else {
return false;
}
}
#Override
public E next(){
return list[currentIndex++];
}
}
This must include, which i think i did correct
"list" of type MyArrayList
"currentIndex" of type int, initially at zero
This is my main method for testing
public static void main(String[] args) throws Exception {
MyList<String> names = new MyArrayList<>();
names.add("Steve");
names.add("Frank");
names.add("Heather");
names.add("Chris");
names.add("Oliver");
for (String string : names) { // error at names Can only iterate over an array or an instance of java.lang.Iterable
System.out.println(string);
}
}
}
In the myArrayList i have added as the requirement is Make MyArrayList implement the Iterable interface by adding the iterator() method, which should return an instance of MyArrayListIterator.
public Iterator<E> iterator() {
return new MyArrayListIterator();
}
Please let me know what I am doing wrong.
As already mentioned in the comments, your problem is that you read from list in MyArrayListIterator without initializing it. This causes a NullPointerException.
You can fix this in two different ways:
Make MyArrayListIterator a non-static nested (they are also called inner classes) class of MyArrayList.
By doing so, you get access to all fields of the outer-class, which in this case is MyArrayList. For example, see this code snippet:
public class MyArrayList<E> implements MyList<E> {
private Object[] list = new Object[10];
private int size = 0;
public Iterator<E> iterator(){
return new MyArrayListIterator<>();
}
// more of your implementation...
// This is the inner class
private class MyArrayListIterator<T> implements Iterator<T> {
private int currentIndex = 0;
#Override
public boolean hasNext() {
// Since this is a inner class, we have access to the
// "list" field defined by MyArrayList.
return currentIndex < list.length;
}
#Override
public T next() {
// Since this is a inner class, we have access to the
// "list" field defined by MyArrayList.
return (T) list[currentIndex++];
}
}
}
Make MyArrayListIterator a static nested class or a separate class.
In this case, you don't have access to the fields defined in MyArrayList, which means you have to provide them yourself. This can be done using the constructor.
public class MyArrayList<E> implements MyList<E> {
private Object[] list = new Object[10];
private int size = 0;
public Iterator<E> iterator(){
return new MyArrayListIterator<>((E[])list);
}
// More of your list implementation
// This is a static inner class, which means we do not have access to
// the fields of the outer class.
private static class MyArrayListIterator<T> implements Iterator<T> {
private final T[] elements;
private int currentIndex = 0;
public MyArrayListIterator(T[] elements) {
this.elements = elements;
}
#Override
public boolean hasNext() {
// Since we got the elements as constructor argument, they are not
// null (assuming you did not call it with null as parameter).
return currentIndex < elements.length;
}
#Override
public T next() {
// Since we got the elements as constructor argument, they are not
// null (assuming you did not call it with null as parameter).
return elements[currentIndex++];
}
}
}
For more information on nested classes, see this tutorial by Oracle on nested classes.
Related
public interface Iterator<T> {
// Returns true if the iterator is valid (points to an element), false otherwise.
boolean isValid();
// Returns the current element and moves forward. This method can only be called if the iterator is valid. If the iterator points to the last element, it becomes invalid after the call.
T next();
// Returns the current element and moves backwards. This method can only be called if the iterator is valid. If the iterator points to the first element, it becomes invalid after the call.
T prev();
}
In a class that does not implement interface Iterator, how is it possible to create a method that returns Iterator<K>, when you can only create methods for an interface inside a class that implements it?
public class ABC<K> implements EFG<K>{
public Iterator<K> minIt() {
//method body
//return Iterator<K> variable
}
}
The class ABC containing the method minIt() does not implement Iterator<T>
(No classes implement the interface Iterator <T> )
You can use an Anonymous Class that implements the interface:
For instance:
interface Foo<T> {
T foo();
}
class Bar<T> {
T t;
public Foo<T> bar() {
return new Foo<T>() { // <-- Anonymous class implementing `Foo`
public T foo() {
return t;
}
};
}
}
Execution:
Bar<String> b = new Bar<>();
b.t = "hello"; // with a setter in real life
Foo<String> f = b.bar();
f.foo(); // will return "hello"
The other option which I think would be the most common is to use a method that returns the interface, for instance the list interface has an iterator() method even though it itself doesn't implements the Iterator interface.
List<String> list = new ArrayList<>();
Iterator<String> stringIterator = list.iterator();
Here's the implementation
Simple. By making a class that implements it. Note that you have a type that you came up with on your own and you named it Iterator. Given that java.util.Iterator exists, this is a really bad idea. You should pick another name.
public class ABC<K> implements EFG<K> {
// Let's say this contains the items that can be iterated over.
private List<K> list = new ArrayList<K>();
class MyIterator implements my.pkg.Iterator<K> {
private int position = 0;
#Override public boolean isValid() {
return position > -1 && position < list.size();
}
#Override public K next() {
if (!isValid()) throw new NoSuchElementException();
return list.get(position++);
}
#Override public K prev() {
if (!isValid()) throw new NoSuchElementException();
return list.get(position--);
}
}
public Iterator<K> minIt() {
return new MyIterator<K>();
}
}
Note that classes that you put in classes can only be constructed in instance contexts within that class: They have a 'secret' field of your outer's type. Hence why the code in MyIterator can access the list field of your outer class.
Java has 'anonymous inner class literal' syntax which lets you shorten this: Instead of explicitly declaring class MyIterator, you can also write:
public Iterator<K> minIt() {
return new your.pkg.Iterator<K>() {
private int position = 0;
#Override public boolean isValid() {
// same code goes here as the previous snippet
}
};
}
This anonymous inner class form is a lot more common. It's just syntax sugar - a shorter way to write the same thing.
Class definition for Binary Search Tree in Java:
public class BST<E extends Comparable<E>> implements Iterable<E>, Cloneable
public Iterator<E> iterator() {
return new BSTInOrderIterator();
}
private class BSTInOrderIterator implements Iterator<E> {
private int sortedArrayFillerIndex;
private final E[] sortedArray;
private int ptr;
public BSTInOrderIterator() {
sortedArrayFillerIndex = 0;
sortedArray = (E[]) (new Object[size()]);
inOrder(root);
ptr = 0;
}
private void inOrder(Node x) {
if (x == null) return;
inOrder(x.left);
sortedArray[sortedArrayFillerIndex++] = x.value;
inOrder(x.right);
}
#Override
public boolean hasNext() {
return ptr < size();
}
#Override
public E next() {
return sortedArray[ptr++];
}
}
In the iterator, I first build a sorted array through an inorder traversal of my BST.
However, I get class cast exception in the constructor of the BST iterator. How do I handle that?
The issue is in the line sortedArray = (E[]) (new Object[size()]);. You cannot initialize a generic array like this. To initialize the sortedArray try below.
sortedArray =(E[]) Array.newInstance(clazz, size())
Be aware that you need to provide the class of the required object as the clazz
See the answers for this question for more details. How to create a generic array in Java?
I'm trying to create a genetic ArrayList of my class Team but I can't cast Comparable to T despite that T extends Comparable
(I tried extends Comparable without putting < T > and same problem is happening)
public class ArrayList<T extends Comparable>
{
static int MaxSize = 1003;//some random maximum size for our array lists
public int Size = 0;
public int Capacity = 0;
T[] MyList;
public ArrayList()//Default Constructor
{
this(MaxSize);
}
public ArrayList(int Capacity)
{
MyList = (T[]) new Comparable[Capacity]; // Casting
}
}
public class Team implements Comparable<Team>
{
public String Name;
public int Points;
public int GamesCount;
public int Wins;
public int Loses;
public int GoalDifference;//Goals Scored - Goals Against
public int GoalsScored;
public int GoalsAgainst;
public Team(String s)
{
Name = s;
Points = 0;
GamesCount = 0;
Wins = Loses = 0;
GoalDifference = GoalsAgainst = GoalsScored = 0;
}
}
public class Test
{
public static void main(String args[])
{
ArrayList<Team> Teams = new ArrayList<Team>(10);
for(int i = 0 ;i < 10;i++)
{
String TeamName = in.next();
Teams.MyList[i] = new Team(TeamName);//exception here
}
}
}
I am getting the following exception. Many thanks in advance for your help.
Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Comparable; cannot be cast to [LTeam;
at Test.main(Test.java:21)
That's obvious, just think about it for a second.
new Comparable[Capacity];
Here you're creating an array which will contain Comparable elements.
Then you're trying to downcast it to an array of Team, which means trying to use a more specific type, and which is not allowed (Upcasting and downcasting in Java), and as you see, throws a ClassCastException.
As your array will contain only types which extends Comparable, you can have a Comparable array inside your ArrayList implementation.
Comparable[] MyList;
Then you can initialize it without casting
MyList = new Comparable[Capacity];
And remember to implement the Comparable#compareTo method in your Team class, otherwise the code won't compile.
You asked for an example.
public class ArrayList<T extends Comparable> {
private static final int MAX_SIZE = 1000;
private final Comparable<T>[] list;
public ArrayList() {
this(MAX_SIZE);
}
public ArrayList(int capacity) {
list = new Comparable[capacity]; // Casting
}
public T get(final int index) {
return (T) list[index];
}
public void set(final int index, final T value) {
list[index] = value;
}
}
Usage is pretty simple
final ArrayList<Team> teamArrayList = new ArrayList<>(3);
teamArrayList.set(0, new Team("One"));
teamArrayList.set(1, new Team("Two"));
teamArrayList.set(2, new Team("Three"));
final String name = teamArrayList.get(0).Name;
As you extended the Comparable<T> interface, you need to implement it
Compares this object with the specified object for order. Returns a
negative integer, zero, or a positive integer as this object is less
than, equal to, or greater than the specified object
A basic example is
#Override
public int compareTo(final Team other) {
return name.compareTo(other.name);
}
In your code, T is Team.
Team IS-A Comparable. Hence, you can cast Team to Comparable.
But every Comparable is not a Team. Therefore, Comparable cannot be cast to Team.
watch this statement: MyList = (T[]) new Comparable[Capacity]; it initializes an array from Comparable interface and put it in to MyList field with type of Team[].
you can test it with:
{
MyList = (T[]) new Comparable[Capacity]; // Casting
System.out.println( MyList.getClass().toString());
}
it writes class [Ljava.lang.Comparable; in output... so in the first attempt to access this field from outside of class you will get ClassCastException even by calling length in test method like this:
public class Test
{
public static void main(String args[])
{
MArrayList<Team> Teams = new MArrayList<Team>(10);
int length = Teams.MyList.length; // this line throws ClassCastException
....
}
}
To solve your problem I suggest change your ArrayList class like this:
public class ArrayList<T extends Comparable<T>>
{
...
Comparable<T>[] MyList;
...
public ArrayList(int Capacity)
{
MyList = new Comparable[Capacity]; // Casting
}
}
Building queue implementation based on linked list. Cannot run application because of the two errors:
public class Queue<Integer> implements Iterable<Integer> {
...
public Iterator<Integer> iterator() {
return new ListIterator(first);
}
private class ListIterator<Integer> implements Iterator<Integer> {// error #1
private Node<Integer> current;
public ListIterator(Node<Integer> first) {
current = first;
}
public boolean hasNext(){ return current != null; }
public void remove() { throw new UnsupportedOperationException();}
public int next() { // error #2
if (!hasNext()) throw new NoSuchElementException();
int item = current.item;
current = current.next;
return item;
}
}
}
error #1: error: Queue.ListIterator is not abstract and does not override abstract method next() in Iterator
where Integer is a type-variable:
Integer extends Object declared in class Queue.ListIterator
error #2: error: next() in Queue.ListIterator cannot implement next() in Iterator
return type int is not compatible with Integer
where E,Integer are type-variables:
E extends Object declared in interface Iterator
Integer extends Object declared in class Queue.ListIterator
How to get it working?
Boxing and unboxing in Java simplify code in many places, but method return types is not one of them. The next method must return an Integer, not an int. It must match the generic type parameter exactly.
public Integer next()
Second, you've declared a generic type parameter Integer in your Queue and ListIterator classes that has nothing to do with java.lang.Integer. Remove it:
// here
public class Queue implements Iterable<Integer> {
and
// here
private class ListIterator implements Iterator<Integer> {
So I am attempting to create a LinkedHashedDictionary's Iterator member for a homework assignment, however I am having multiple issues regarding its types.
Iterator Interface:
package nhUtilities.containers2;
public interface Iterator<Element> extends Cloneable, java.util.Iterator<Element>
{
public void reset ();
public void advance ();
public boolean done ();
public Element get ();
public boolean equals (Object obj);
public boolean traverses (Object container);
public Object clone ();
public void setEqualTo (Iterator<Element> other);
public boolean hasNext ();
public Element next ();
public void remove ();
}
In my code, I have a private class called EntryIterator. It extends an AbstractIterator, but implements the Iterator above.
My current implementation is as follows:
private class EntryIterator<Element> extends AbstractIterator<Element>
implements Iterator<Element>
{
protected Iterator<Key> keyIterator;
protected Dictionary<Key,Value> dictionary;
public EntryIterator(Dictionary<Key,Value> dictionary)
{
keyIterator = keys.iterator();
this.dictionary = dictionary;
}
public void reset()
{ keyIterator = keys.iterator(); }
/**
* #Requrie !this.done()
*/
public void advance()
{ keyIterator.advance(); }
public boolean done()
{ return keyIterator.done(); }
// public Entry<Key,Value> get()
// Violates initial Interface: Results in compile error.
// Return type must be "Element"
public Element get()
{
Key key = keyIterator.get();
Value value = dictionary.get(keyIterator.get());
return (Element) new Entry<Key,Value>(key, value);
}
public boolean traverses(Object container)
{
// TODO Iterator traverses
return false;
}
public void setEqualTo(Iterator<Element> other)
{
this.keyIterator = ((EntryIterator<Element>) other).keyIterator;
this.dictionary = ((EntryIterator<Element>) other).dictionary;
}
}
I have done multiple varieties of this class regarding its types, but none of them seem to be compatible with my Dictionary. Should I keep the formatting as is above, I get an error on my Dictionary's iterator() function:
public Iterator<Entry<Key,Value>> iterator()
{
return new EntryIterator<Entry<Key,Value>>(this);
}
The error states it is "The return type is incompatible for Dictionary.iterator()"
Should I change the type of the EntryIterator class' type to:
private class EntryIterator<eEntry<Key,Value>> extends AbstractIterator<Element>
implements Iterator<Element>
I simply get an error saying "Syntax error expected on token '<'" as well as another incompatibility error on my Dictionary.Iterator() function.
Can someone point me in the right direction as to how I can link up all of these different types to get them to return what my contract for Dictionary demands?
I have attempted asking my question during the class, via email to the instructor, as well as one on one merely to be avoided. Any help would be much appreciated.
So, the problem was actually with my class instantiation... Here for everyone with similar issues:
private class EntryIterator extends AbstractIterator<Entry<Key,Value>> implements
nhUtilities.containers2.Iterator<Entry<Key, Value>>