Help with custom iterator - java

I'm having trouble with my custom iterator...it seems that the next() method is not working.
I think my constructor is not working...and I got this error message: java.lang.ArithmeticException: / by zero
import java.util.Iterator;
public class RandomBag <Item> implements Iterable<Item>
{
private Node first;
private int N;
private int k=0;
private class Node
{
Item item;
Node next;
}
public void add(Item item)
{
Node oldfirst = first;
first = new Node();
first.item = item;
first.next = oldfirst;
N++;
}
public boolean isEmpty()
{
return first == null;
}
public int size()
{
return N;
}
public Iterator<Item> iterator()
{
return new RandomIterator();
}
private class RandomIterator implements Iterator<Item>
{
Item[] a = (Item[]) new Object [N];
public RandomIterator()
{
int counter = 0;
//put items in the array
for (Node x=first; x!=null; x=x.next)
{
a[counter] = x.item;
counter++;
}
//randomize the items in the array
for (int i=0; i<size(); i++)
{
int randomIndex = StdRandom.uniform(i, size());
Item item = a[randomIndex];
a[randomIndex] = a[i];
a[i] = item;
}
}
public void remove() {}
public boolean hasNext()
{
return k!=N;
}
public Item next()
{
Item item = a[k % a.length];
k++;
return item;
}
}
public static void main(String[] args)
{
RandomBag<Double> numbers = new RandomBag<Double>();
Iterator iter = numbers.iterator();
numbers.add(1.0);
numbers.add(4.0);
numbers.add(3.0);
numbers.add(5.0);
StdOut.println(iter.next());
StdOut.println(iter.next());
StdOut.println(iter.next());
StdOut.println(iter.next());
}
}

The problem is in this method:
public Item next()
{
Item item = a[k % a.length]; // If a.length is zero... BOOM
k++;
return item;
}

It doesn't protect you against this error in the future with a zero-length bag (or some of the other code issues pointed out), but moving this line:
Iterator iter = numbers.iterator();
Below the final .add() statement should fix the issue you're seeing, which is occurring because the iterator is initializing before anything is in numbers.

First of all: The k variable should be part of the iterator and NOT of the class itself - otherwise you get obviously pretty useless results as soon as you have more than 1 iterator.
But the problem is that you use a argument less constructor for your RandomBag class which means that N is initialized to 0. Then you construct your inner class iterator with an array of size N (=0) and try to use it - that won't work. The add() methods after initializing your Iterator have absolutely no effect - which makes this iterator pretty useless (usually you should throw a concurrent modification exception here and use the data of the datastructure not make a copy=)
PS: If you want to use this strange iterator, change your hasNext() method to use your arrays length and NOT N - that'll fix this issue because next() will not be called (or if it is, throwing an exception is fine)

Related

How to use Iterator next() method to generate power set of LinkedSet

For my class I have to create an iterator that will generate a power set of a LinkedSet. Per my professor, I have to iterate through a bitString of the int current. Where current is the subset to which we are adding elements of the main set. I keep having a NullPointerException. I think I am looping through the bitString correctly but when I want to move to the next node in the set, it is saying it is null. I've stared at this for 12 hours and cannot figure out what to do. My professor provided a framework, so I'll explain what is mine and what is his.
This is the framework:
private class LinkedSetPowerSetIterator implements Iterator<Set<T>> {
// cardinality of this set
int N;
// cardinality of the power set (2^N)
int M;
// the integer identifier of the current subset, i.e. the current element
// of the power set. Legal values range from 0..M-1 inclusive.
int current;
public LinkedSetPowerSetIteratorInt32BitString() {
// initialize N, M, and current here
}
public boolean hasNext() {
return current < M;
}
public Set<T> next() {
LinkedSet<T> s = new LinkedSet<T>();
char[] bitstring = Integer.toBinaryString(current).toCharArray();
// iterate from right to left over bitstring and the internal
// linked list to ensure that the call to add will insert a new
// first node (constant time)
current = current + 1;
return s;
}
public void remove() {
}
}
What I have so far:
private class myPowerIterator implements Iterator<Set<T>> {
// cardinality of set
int N;
// cardinality of power set (2^N)
int M;
//current subset in power set
int current;
// starting node, rear node
Node set = rear;
public myPowerIterator() {
N = size;
M = (int)Math.pow(2, N);
current = 0;
}
public boolean hasNext() {
return (current < M);
}
public Set<T> next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
LinkedSet<T> result = new LinkedSet<T>();
char[] bitString = Integer.toBinaryString(current).toCharArray();
for (int i = bitString.length - 1; i >= 0; i--) {
if (bitString[i] == 1) {
result.add(set.element); // How do I make sure it is adding elements
set = set.prev; // from starting set? Keep getting Error:
} // NullPointerException: Cannot read field
else { // "prev" because this.set is null.
set = set.prev;
}
}
current = current + 1;
return result;
}
public void remove() {
throw new UnsupportedOperationException();
}
}
You need to implement the Iterable<T> interface in your LinkedSet<T>. If you don't do this then your next() method will not "reset" it's location, thus giving you the NullPointer.

Why Comparable Interface is intialise with new Operator? though it is interface?

Below is the class and in this, I'm using a Comparable interface. How can it is initialized with new, though it is an interface?
public class PriorityQueueImpl {
#SuppressWarnings("rawtypes")
private Comparable[] pQueue;
private int index;
public PriorityQueueImpl(int capacity){
pQueue = new Comparable[capacity];
}
public void insert(Comparable item ){
if(index == pQueue.length){
System.out.println("The priority queue is full!! can not insert.");
return;
}
pQueue[index] = item;
index++;
System.out.println("Adding element: "+item);
}
#SuppressWarnings("unchecked")
public Comparable remove(){
if(index == 0){
System.out.println("The priority queue is empty!! can not remove.");
return null;
}
int maxIndex = 0;
// find the index of the item with the highest priority
for (int i=1; i<index; i++) {
if (pQueue[i].compareTo (pQueue[maxIndex]) > 0) {
maxIndex = i;
}
}
Comparable result = pQueue[maxIndex];
System.out.println("removing: "+result);
// move the last item into the empty slot
index--;
pQueue[maxIndex] = pQueue[index];
return result;
}
public static void main(String a[]){
PriorityQueueImpl pqi = new PriorityQueueImpl(5);
pqi.insert(34);
pqi.insert(23);
pqi.remove();
pqi.remove();
}
}
in the above code, Comparable Array initializes with the new operator. how is this possible?
new Comparable[capacity] is not an initialisation ofComparable interface but an array that can hold objects of type Comparable. You can refer following section of JLS

Implement Queue using fixed size array

I came across below interview question and I am working on it:
Build a queue class with the enqueue and dequeue methods. The queue
can store an UNLIMITED number of elements but you are limited to
using arrays that can store up to 5 elements max..
Here is what I was able to come up with. Is this the right way to do it in the interview or is there any better way we should implement in the interview?
class Solution {
private final List<List<Integer>> array;
public Solution() {
this.array = new ArrayList<>();
}
public void enqueue(int value) {
if(array.isEmpty()) {
List<Integer> arr = new ArrayList<>();
arr.add(value);
array.add(arr);
return;
}
if(array.get(array.size() - 1).size() != 5) {
array.get(array.size() - 1).add(value);
return;
}
List<Integer> arr = new ArrayList<>();
arr.add(value);
array.add(arr);
return;
}
public int dequeue() {
if(array.isEmpty()) {
return -1;
}
for(List<Integer> l : array) {
for(int i=0; i<l.size(); i++) {
return l.remove(i);
}
}
return -1;
}
}
As I mentioned in comments, your solution doesn't really solve the problem because the outer array of 5-element arrays can have more than 5 elements.
Instead, you can implement the queue as a linked list of 4-integer nodes, using the 5th element for a reference to the next array. But there's no reason to assume the elements are integers. This turns out to be pretty simple.
public class SillyQueue<T> {
private static final int MAX = 5;
private Object [] head = new Object[MAX], tail = head;
private int headPtr = 0, tailPtr = 0;
void enqueue(T x) {
if (tailPtr == MAX - 1) {
Object [] a = new Object[MAX];
tail[MAX - 1] = a;
tail = a;
tailPtr = 0;
}
tail[tailPtr++] = x;
}
T dequeue() {
if (headPtr == MAX - 1) {
head = (Object[]) head[MAX - 1];
headPtr = 0;
}
return (T) head[headPtr++];
}
}
Your answer uses ArrayList instead of true arrays, and worse, uses an unlimited arraylist to put those arrays in. I think that the interviewers expected you to implement a singly-linked list of 5-element arrays:
/**
* A singly-linked list node with an array; supports popping its 1st elements,
* and adding elements at the end, possibly by creating a new node
*/
public class ListNode {
final int MAX = 5;
private int contents[] = new int[MAX];
private int size = 0; // valid elements
private ListNode next = null;
private ListNode(ListNode next) {
this.next = next;
}
public boolean isEmpty() { return size == 0; }
public ListNode addLast(int value) {
ListNode next = this;
if (size == MAX) {
next = new ListNode(this);
}
next.contents[next.size ++] = value;
return next;
}
public int removeFirst() {
if (size == 0) {
throw new NoSuchElementException("empty queue");
}
int value = contents[0];
size --;
for (int i=1; i<size; i++) contents[i-1] = contents[i];
return value;
}
}
/**
* A simple queue on top of nodes that keep arrays of elements
*/
public class ListArrayQueue {
ListNode first = new ListNode();
ListNode last = first;
public void enqueue(int value) {
last = last.addLast(value);
}
public int dequeue() {
if (first.isEmpty() && first != last) {
first = first.next;
}
return first.removeFirst();
}
}
Performance-wise, this can be improved: you can avoid keeping the size in each ListNode, since only the 1st and last nodes can be non-full. You can also avoid the loop in removeFirst, but that would entail replacing size by firstIndex and lastIndex; which could again be moved into the ListArrayQueue to save space in each node.
If they has asked you to build an unlimited array out of 5-element array pieces, you would have had to implement something similar to a b-tree. Which, without handy references, would be quite hard to pull off during an interview.
You can use a 1-D array and use Wrap-around indexing to implement the queue with the limitation that queue can contain maximum 5 elements.
For checking the condition of empty queue, maintain a variable that counts the number of elements present in the queue.
Is this the right way to do it in the interview…?
Presenting uncommented code is never right, let alone in an interview.
In an interactive interview, it would be your task to find out whether you can/should use an unlimited number of arrays.
If not, you have to negotiate a way to handle an enqueue() to a queue filled to capacity in addition to a dequeue() to an empty one.
Fix the type of items the queue can hold.
Agree upon the parameters of the enqueue and dequeue methods.
The task is to Build a queue class, Solution is a bad choice for a name - array for something to access the items is no better.
In a language providing arrays, I'd take limited to using arrays literally - if using something more, why not an implementation of java.util.Queue?
The empty queue handling is entirely redundant: in enqueue(), you could have used
if (!array.isEmpty() && array.get(array.size() - 1).size() < 5); in dequeue() you can just drop it.
Instantiating List<Integer>s, you know there won't be more than five items at a time: tell the constructor.
dequeue() leaves empty List<Integer>s in arrays, giving rise to the current nested loop that desperately needs a comment.
(For the second part of the question, I second Rajkamal Tomar.)
Trade Off - Organize Fixed Size Arrays
Manage arrays based on ArrayList
enqueue - append new fixed size array - O(1)
dequeue - remove first fixed size array - O(n)
Manage arrays based on LinkedList
enqueue - append new fixed size array to linked list - O(1)
dequeue - remove first fixed size array - O(1)
cons - extra next pointer to setup linked list
public class FixedArrayQueue<T> {
private Node<T> head, tail;
private int front, rear, size;
private final int SIZE;
public FixedArrayQueue(int n) {
SIZE = n;
head = tail = new Node<T>(SIZE);
front = rear = size = 0;
}
public void enqueue(T t) {
tail.array[rear++] = t;
if (rear == SIZE) {
rear = 0;
append();
}
size++;
}
public T dequeue() {
if (size == 0) {
throw new EmptyQueueException();
}
T ret = head.array[front++];
if (front == SIZE) {
front = 0;
remove();
}
size--;
return ret;
}
private void append() {
tail.next = new Node<T>(SIZE);
tail = tail.next;
}
private void remove() {
head = head.next;
}
private boolean isEmpty() {
return size == 0;
}
private int size() {
return size;
}
}
class Node<T> {
T[] array;
Node<T> next;
public Node(int n) {
array = (T[]) new Object[n];
}
}

How to add items into an Array Generic Object from the parameter in Java

So, I am creating a generic data structure named "Sack". In this I add items to a sack, grab a random item, see if it's empty, or dump out its contents etc. Also I'm creating it to expand to hold as many items as needed.
Currently, I'm working on the add method and I'm having troubles on my add method, and I am trying to think of a way adding what's in my parameter into the sack.
import java.util.Arrays;
public class Sack<E>
{
public static final int DEFAULT_CAPACITY = 10;
private E [] elementData;
private int size;
#SuppressWarnings("unchecked")
public Sack()
{
elementData = (E[]) new Object[DEFAULT_CAPACITY];
}
#SuppressWarnings("unchecked")
public Sack(int capacity)
{
if(capacity < 0)
{
throw new IllegalArgumentException("capacity " + capacity);
}
this.elementData = (E[]) new Object[capacity];
}
public boolean isEmpty()
{
if(size == 0)
{
return true;
}
else
{
return false;
}
}
public E [] dump()
{
E [] E2 = Arrays.copyOf(elementData, size);
for(int i = 0; i < size; i++)
{
elementData[i] = null;
}
size = 0;
return E2;
}
In this method, I am trying to add item, into my sack. When I run my tests, I am told it's incorrect. If there's a way to improve this.
public void add(E item)
{
elementData[size] = item;
size++;
}
elementData is what I am adding the items into.
Update
I updated my add method to look like this.
public void add(E item)
{
if(size >= elementData.length-1)
{
elementData[size] = item;
size++;
}
}
The message I am now receiving is that add is not working correctly and to check size usage.
You cannot ensure capacity of Java arrays, Javascript can! You can create a new one and copy:
public void add(E element) {
int index = size++;
if(size >= elementData.length-1) {
// it ensures elementData
elementData = java.util.Arrays.copyOf(elementData, size);
}
elementData[index] = element;
}
or skip ensure of array capacity and change the check direction:
public void add(E element) {
if(size < elementData.length-1) {
elementData[size++] = element;
}
// TODO else notice of the unsuccessfull add
}
It sounds like there's a spec for what your Sack is supposed to do that you did not paste.
It also sounds like your add method is supposed to just work, even if the sack is already at capacity.
That means you need to make a new array, copy over all elements, and then replace the array you have in your Sack instance with the new one (because java arrays cannot grow or shrink).
Look at the source of of java's own ArrayList for a hint on how that's done.
So after numerous tries, I give credit to #rockfarkas for solving this. I put in the following code and it solved my add method code.
public void add(E item)
{
int index = size++;
if(size >= elementData.length-1)
{
elementData = Arrays.copyOf(elementData, size);
}
elementData[index] = item;
}
Here's another way of doing this,
public void add(E item)
{
ensureCapacity(size+1);
elementData[size] = item;
size++;
}
This also works, but I would have to modify the ensureCapacity method accurately, which I have.

Java Ring implementation

I am trying to implement a ring that remembers the last N elements. It adds element and changes the pointer correctly. The get() method must return the newest element added to the ring. I tried to find the logic in the get method with pen and paper and eventually, I managed to do it. However, when I run my code it does not seem so. Thanks for the help in advance.
[1][2][3][4][5] <- In the following example, get(0) has to return 5 and get(1) - 4
Iteration and print
[1][2][3][4][5]
Using the get method - get(0), get(1) ....
[1] [5] [4] [3] [2] - here [1] must be on the right side of [2]
import java.util.AbstractCollection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class CircularArrayRing<E> extends AbstractCollection<E> implements Ring<E>
{
private int elements;
private int front;
private E[] ring;
#SuppressWarnings("unchecked")
public CircularArrayRing()
{
ring = (E[]) new Object[10];
front = 0;
}
#SuppressWarnings("unchecked")
public CircularArrayRing(int size)
{
ring = (E[]) new Object[size];
front = 0;
}
#Override
public boolean add(E e)
{
ring[front] = e;
front++;
if(front == ring.length)
{
front = 0;
}
if(elements < ring.length)
{
elements++;
}
return false;
}
#Override
public Iterator<E> iterator()
{
return null;
}
#Override
public int size()
{
return elements;
}
#Override
public E get(int index) throws IndexOutOfBoundsException
{
if(index > elements - 1 || index > ring.length - 1)
{
throw new IndexOutOfBoundsException();
}
else
{
if (index > front)
{
return ring[ring.length + front -index];
}
else
{
return ring[front - index];
}
}
}
}
There are some mistakes with the array index handling.
For example if we look at the base case with just 1 element, the logic calling get(0) is:
front - index = 1 - 0 = 1 -> ArrayIndexOutOfBounds
From this we can see that front should be decreased by 1 to reach the correct index.
Further testing will show that the same fix should be applied also to the other branch of the if and that the condition itself should be >= instead of >.
The correct code inside get would then be:
if (index >= front) {
return ring[ring.length + front - 1 - index];
}
else {
return ring[front - 1 - index];
}
So, after looking a bit better at your implementation, I tried rewriting it.
No need to initialize size and effectiveSize, as their default is 0 as class members.
I think this still does what you want.
public class CircularArrayRing<E> extends AbstractCollection<E>
{
private final E[] ring;
private int size;
private int effectiveSize;
#SuppressWarnings("unchecked")
public CircularArrayRing() {
ring = (E[]) new Object[10];
}
#SuppressWarnings("unchecked")
public CircularArrayRing(final int size) {
ring = (E[]) new Object[size];
}
#Override
public boolean add(final E e) {
if (effectiveSize < ring.length) {
effectiveSize++;
}
if (size >= ring.length) {
size = 0;
}
ring[size++] = e;
return true;
}
#Override
public Iterator<E> iterator() {
return null;
}
#Override
public int size() {
return effectiveSize;
}
public E get(final int index) throws IndexOutOfBoundsException {
if (index < 0 || index > effectiveSize - 1) {
throw new IndexOutOfBoundsException();
}
return ring[effectiveSize - index - 1];
}
}
Java ring?
I thought you guys meant one of these:
https://www.slideshare.net/abhishekabhi1023/java-ring-new
I'm looking for information on how to program this ;(

Categories