I have a java object that implements the Iterable interface. This linked list has a group of objects that each hold a parameterized object (so it could be a String OR an ArrayList or whatever).
In the iterator() method, i create an Iterator object that takes an array of these parameterized items and return it.
However, when i use the following code:
//create an Iterable object named 'iterate'
for(String current : iterate){
//try to do some stuff with it... print it out?
}
//more code
//here is how i implemented the iterator function of my Iterable class:
public Iterator<Item> iterator(){
// return an iterator over items in order from front to end
Item[] items = (Item[]) new Object[numberOfItems];
QueueItem<Item> item = first;
for(int i=0;i<numberOfItems;i++){
items[i] = item.getInfo();
item = item.next;
}
return new myIterator(items);
}
//here is the code for the myIterator class. it is a private internal class
private class myIterator implements Iterator<Item>{
Item items[];
int index;
public myIterator(Item current[]){
items = current;
index = 0;
}
#Override
public boolean hasNext() {
if(items==null){
return false;
}
return (index>=items.length);
}
#Override
public Item next() {
if(index+1>=items.length){
throw new NoSuchElementException("There are no more elements!");
}
return items[index++];
}
#Override
public void remove() {
throw new UnsupportedOperationException("this operation is not supported");
}
}
the code goes to the for loop, then creates the Iterator object correctly (I used breakpoints to confirm), and returns it, but then the code jumps out of the for loop without going through it even once and continues....
Am i missing something? did i do something wrong here? how do i need to change the implementation of my Iterable object? is there some GOTCHA with implementing this that i'm not taking into account?
thanks!
in hasNext method you check if return (index>=items.length); Well this will return false. change operant to "<"
oh my gosh. so embarrassing. the hasNext method had the boolean statement reversed.
it should have been:
return (index<items.length); thanks anyways!
i've been pulling my hair out about this. i debugged everything else, then it dawned on me.
This is my first iterator implementation, so i figured it must have been something more fundamental that i wasn't doing correctly.
Related
I'm trying to do a linkedlist for an assigment i have, this ask explicitly to create, from scratch a linkedlist and some derivated types like a queue and a stack, this is just some college homework, and i realize how to make a node class and a linkedlist class, but i'm struggling to create the addAll() method in this linkedlist class, this is what i have.
if i must bet, i say is the Collection c one, but then, i'm trying to add list of stuff there, in order to pass him's content to the new list, obiusly is not ready and obiusly doesn't work.
Can you tell me how i can pass some kind of "proto-list" in order to pass them data inside the new list?
(I know i must use somekind of for(objects) but i'm failing to pass some data through the parameter, which will be the right parameter to put there?)
public boolean addAll(Collection c) {
for (int i = 0; i < (this.listaNodos.size()); i++) {
//for (T someT : c){
// Node newNodo = new Node(someT);
//}
//i know the one down there is not gonna do anything, because
//i'm not accesing the data, but one problem at a time would ya ;)
Node newNodo = new Node(someT);
Node actualNodo = this;
boolean processFinished = false;
try{
if(index >= this.listaNodos.size() || index < 0){
throw new IndexOutOfBoundsException();
}
do{
if(index == actualNodo.getIndex())
{
actualNodo.setData(someT);
processFinished = true;
return true;
}
else
{
actualNodo = actualNodo.nextNode;
}
}while(!processFinished);
return false;
}catch(IndexOutOfBoundsException ex)
{
throw ex;
}
}
return false;
}
Can you tell me how to fix it to make it work?
Any request for clarification, constructive comment, or question would be greatly apreciated too.
Thanks in advance
I assume you already have an add() method of some sort right? If so, you can go over each element in c and add it using the add method:
public boolean addAll(Collection<T> c) {
boolean changed = false;
for (T t:c) {
changed |= this.add(t);
}
return changed;
}
I'm assuming the returned boolean means whether this list has changed, this is how it is defined in the Collection contract: https://docs.oracle.com/javase/7/docs/api/java/util/Collection.html#addAll(java.util.Collection).
You were also missing a generic type for your add method, so I added one. I assume your class definition looks somthing like this?
public class MyLinkedList<T>
How do you code an Iterator for a Set? Given that the iterator does not have access to the underlying data storage mechanism, and can only use the Set methods, is it possible to do this?
Every implementation I've managed to find creates the Iterator as an anonymous class; however, I am trying to figure out if there is a clever way to iterate over a Set while only accessing the methods provided by Set.
So far, the best I've managed to come up with looks like this:
import java.util.*;
public class SetIterator<E> implements Iterator
{
protected E[] arrayData;
protected Set<E> set;
protected int index;
protected boolean canRemove;
public SetIterator(Set<E> set)
{
this.set = set;
this.arrayData = (E[]) set.toArray();
this.index = -1;
this.canRemove = false;
}
public E next()
{
if(this.hasNext())
{
this.canRemove = true;
return this.arrayData[++this.index];
}
else
{
throw new NoSuchElementException("There is no next element");
}
}
public boolean hasNext()
{
return this.index + 1 < this.arrayData.length;
}
public void remove()
{
if(this.canRemove)
{
this.set.remove(this.arrayData[index--]);
this.arrayData = (E[]) this.set.toArray();
this.canRemove = false;
}
else
{
throw new IllegalStateException("Cannot remove element before calling next");
}
}
}
But that feels quite kludgy.... Is there a better way?
I think your title doesn't leave much space for answers, but if I use the following as your actual question:
How do you build an Iterator for a Set?
(and understand build as in get an instance of)
I think as PM 77-1 pointed out in the comments:
call the iterator() method on it, which it has since at least Java 1.5.
Keep in mind that it depends on the actual implementation of Set, wether the elements will always be iterated over in the same order.
if we look in AbstractCollection we will see that toArray actually calls the iterator() (abstract method) to produce the array which you will use, so your method still depends on the specific iterator, so you are essentially decorating the iterator.
public Object[] toArray() {
// Estimate size of array; be prepared to see more or fewer elements
Object[] r = new Object[size()];
Iterator<E> it = iterator();
for (int i = 0; i < r.length; i++) {
if (! it.hasNext()) // fewer elements than expected
return Arrays.copyOf(r, i);
r[i] = it.next();
}
return it.hasNext() ? finishToArray(r, it) : r;
}
Still not sure what you are trying to accomplish, the underlying datastructure of the set will have different (and specific) ways to efficently iterate the data, any generic solution would sacrafice performance, using the iterable interface should be generic enough.
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 have a LinkedList over which I need to iterate back and forth multiple times. I am using it to keep track of a series of pages in a workflow that will be created dynamically. This does not behave as I would expect. Given this example:
LinkedList<String> navigationCases;
navigationCases.add("page1");
navigationCases.add("page2");
navigationCases.add("page3");
navigationCases.add("page4");
ListIterator navigationItr = navigationCases.listIterator();
navigationItr.next(); // Returns page1
navigationItr.next(); // Returns page2
navigationItr.previous(); //Returns page2 again
navigationItr.next(); //Returns page2 again
I thought perhaps I was building my list incorrectly, or using the Iterator wrong, but after reading the documentation, this seems to be by design:
A ListIterator has no current element; its cursor position always lies between the element that would be returned by a call to previous() and the element that would be returned by a call to next().
And:
(Next) Returns the next element in the list. This method may be called repeatedly to iterate through the list, or intermixed with calls to previous to go back and forth. (Note that alternating calls to next and previous will return the same element repeatedly.)
So after reading this, it is clear why my code is behaving the way it does. I just don't understand why it should work this way. Even remove seems to be bending over backwards to accommodate this implementation:
Note that the remove() and set(Object) methods are not defined in terms of the cursor position; they are defined to operate on the last element returned by a call to next() or previous().
Conceptually, a LinkedList seemed to model my workflow cases pretty well, but I can't use an Iterator that behaves this way. Am I missing something here, or should I just write my own class maintain a list of cases and navigate through them?
This should do your job:
public class Main {
public static void main(String[] args) {
final LinkedList<String> list = new LinkedList<String> ();
list.add ("1"); list.add ("2"); list.add ("3"); list.add ("4");
final MyIterator<String> it = new MyIterator (list.listIterator());
System.out.println(it.next());
System.out.println(it.next ());
System.out.println(it.next ());
System.out.println(it.previous ());
System.out.println(it.previous ());
System.out.println(it.next ());
}
public static class MyIterator<T> {
private final ListIterator<T> listIterator;
private boolean nextWasCalled = false;
private boolean previousWasCalled = false;
public MyIterator(ListIterator<T> listIterator) {
this.listIterator = listIterator;
}
public T next() {
nextWasCalled = true;
if (previousWasCalled) {
previousWasCalled = false;
listIterator.next ();
}
return listIterator.next ();
}
public T previous() {
if (nextWasCalled) {
listIterator.previous();
nextWasCalled = false;
}
previousWasCalled = true;
return listIterator.previous();
}
}
}
And a fiddle for it.
ListIterator was designed to behave this way. See the conversation beneath ShyJ's answer for the rationale.
I find this behavior to be beyond idiotic, and have instead written a very simple alternative. Here's the Kotlin code with a extension function for ArrayLists:
class ListIterator<E>(var list: ArrayList<E>) : Iterator<E> {
private var cursor: Int = 0
fun replace(newList: ArrayList<E>) {
list = newList
cursor = 0
}
override fun hasNext(): Boolean {
return cursor + 1 < list.size
}
override fun next(): E {
cursor++
return current()
}
fun hasPrevious(): Boolean {
return 0 <= cursor - 1
}
fun previous(): E {
cursor--
return current()
}
fun current(): E {
return list[cursor]
}
}
fun <E> ArrayList<E>.listFlippingIterator() = ListIterator(this)
If you wish to include removal functionality, I highly recommend writing the API to explicitly instruct the iterator if it should remove left or right, e.g. by defining those methods as removeNext() and removePrevious().
Do something like this (pseudocode) --
class SkipIterator extends ListIterator {
public E previous(){
E n = super.previous();
return super.previous();
}
...
}
then:
LinkedList<String> navigationCases;
navigationCases.add("page1");
navigationCases.add("page2");
navigationCases.add("page3");
navigationCases.add("page4");
SkipIterator navigationItr = (SkipIterator)navigationCases.listIterator();
navigationItr.next(); // Returns page1
navigationItr.next(); // Returns page2
navigationItr.previous(); // Returns page1
Cheers
i am a novice programmer, to be specific, i am learning java programming and i am supposed to implement sortedLinkedList class that extends LinkedList class from the java library. The list has to store persons in ascending order of their surnames. I have already written my Person class that implements Comparable interface. my problem is, I have been struggling implementing this sortedLinkedClass but to no avail. My code runs without any compiling or run time error but the program does not print anything. Another thing as you can see , I am testing it with Integers instead of Persons and it throws NullPointerException when trying to add a number that is already in the list. My code is as it is below.
import java.util.*;
public class SortedLinkedList< E> extends LinkedList<E>
{
private Link<E> first;
private Link<E> last;
/**
* Constructor for objects of class SortedLinkedList
*/
public SortedLinkedList()
{
//super();
first = null;
last = null;
}
/*
* Link class for creating Link nodes in the SortedLinkedList objects
*/
private class Link<E>
{
public Comparable<E> data;
public Link next;
}
/*
* Overiding add method from LinkedList class
*/
public boolean add(E obj)
{
Link newLink = new Link();
newLink.data = (Comparable<E>)obj;
// When the list is initially empty
if (first == null)
{
first = newLink;
last = newLink;
return true;
}
// When the element to be added is less than the first element in the list
if (newLink.data.compareTo(first.data) < 0)
{
//newLink.data = obj;
newLink.next = first;
first = newLink;
return true;
}
// When the element to be added is greater than every element in in list
// and has to be added at end of the list
if (newLink.data.compareTo(last.data) > 0)
{
//newLink.data = obj;
last.next = newLink;
last = newLink;
return true;
}
//When the element to be added lies between other elements in the list
if (newLink.data.compareTo(first.data) >= 0 && newLink.data.compareTo(last.data) <= 0)
{
//newLink.data = obj;
Link current = first.next;
Link previous = first;
while (newLink.data.compareTo(current.data) <= 0)
{
previous = current;
current = current.next;
}
previous.next = newLink;
newLink.next = current;
}
return true;
}
public static void main (String[] args)
{
LinkedList<Integer> list = new SortedLinkedList<Integer>();
list.add(4);
list.add(5);
list.add(10);
list.add(9);
//list.add(5);
ListIterator<Integer> iterator = list.listIterator();
while (iterator.hasNext())
{
System.out.println(iterator.next());
}
}
}
If you must use a LinkedList, all you really have to do is override the "add" method so that it inserts your element in the correct position. You can do that by invoking the add(integer,Object) method which inserts your element in a specific position.
Here's a quick and dirty (and non-generic :P) implementation of what I'm talking about.
public class PersonLinkedList extends LinkedList<Person> {
public boolean add(Person personToAdd) {
int index = 0;
for( ; index<size() ; index++){
Person personAlreadyInList = get(index);
if(personToAdd.compareTo(personAlreadyInList) < 0){
break;
}
}
add(index, personToAdd);
return true;
};
public static void main(String[] args) {
Person amy = new Person("Amy");
Person bob = new Person("Bob");
Person claire = new Person("Claire");
PersonLinkedList list = new PersonLinkedList();
list.add(bob);
list.add(claire);
list.add(claire);
list.add(amy);
list.add(bob);
for (Iterator iterator = list.iterator(); iterator.hasNext();) {
Person person = (Person) iterator.next();
System.out.println(person);
}
}
}
class Person implements Comparable<Person>{
private String name;
public Person(String name) { this.name = name; }
public String getName() { return name; }
#Override
public String toString() { return getName();}
#Override
public int compareTo(Person p) {
return name.compareTo(p.name);
}
}
The reason nothing gets printed is because you store the data in your own linked list data tree and not the LinkedList's data tree. You don't override the iterator method, so the iterator will loop through LinkedList's data which is empty. This is also a problem with all the other methods in LinkedList.
Are you sure you need to inherit from the LinkedList class or are you suppose to make your own class.
If you are supposed to inherit from LinkedList get rid of you node and use LinkedList for storing the data. Your add method would then use a ListIterator to find the correct spot for adding and use the add method of ListIterator.
If you don't inherit from LinkedList then extend AbstractSequentialList.
Note:
Both of these options should not be used in real code. Adding automatic sorting breaks the List interface.
The whole problem is a perfect example of "prefer composition over inheritance".
If this is homework do it as instructed, otherwise I'd recommend changing the exercise to implement a SortedCollection backed by a LinkedList. Then implement Collection and use a List as a member variable.
You could use a SortedSet if you don't need to support elements with the same sort key.
Also, the reason your code doesn't print anything is because you override adding items to the list, but not iterating (the iterator() or listIterator() methods.) Extending LinkedList doesn't automagically make your data structure iterable unless you modify its contents using the base class add(), remove(), and other methods.
besides iterator, add/remove override, I think your algorithm to sort is not correct. And that leads to the nullpointer exception when you add existing elements into your "sortedLinkedList".
while (newLink.data.compareTo(current.data) <= 0)
{
previous = current;
current = current.next;
}
I think what you wanted is while (newLink.data.compareTo(current.data) >0) . not <=0. here is the mistake.
since "=0" is in while condition, it will go through the whole list, till the last element, then execute:
(current is the last now)
previous = current;
current = current.next; (now, current is Null, since last.next is Null)
finally, current is Null, then comes again, current = current.next; Bang! Nullpointer.
so I guess the Nullpointer was thrown at this line.