Where is the possible memory leak in my code? There is also supposed to be a programming error too in one the methods as well, that might cause problems if I create a subclass of this class.
The add method basically just takes an index of where to add the item. For every item that occupies anything after the index in the current array, it just copies it over a spot over, and then places the item into index. I don't see what's wrong with it.
For the remove method, it does the same thing basically, except in reverse.
private static final int MAX_LIST = 3;
protected Object []items;
protected int numItems;
public MyArray()
{
items = new Object[MAX_LIST];
numItems = 0;
}
/*the programming error should be in this method*/
public void add(int index, Object item)
throws ListIndexOutOfBoundsException
{
if (numItems > items.length)
{
throw new ListException("ListException on add");
}
if (index >= 0 && index <= numItems)
{
for (int pos = numItems-1; pos >= index; pos--)
{
items[pos+1] = items[pos];
}
items[index] = item;
numItems++;
}
else
{
throw new ListIndexOutOfBoundsException(
"ListIndexOutOfBoundsException on add");
}
}
/*The memory leak should be in this method*/
public void remove(int index)
throws ListIndexOutOfBoundsException
{
if (index >= 0 && index < numItems)
{
for (int pos = index+1; pos < numItems; pos++)
{
items[pos-1] = items[pos];
}
numItems--;
}
else
{
throw new ListIndexOutOfBoundsException(
"ListIndexOutOfBoundsException on remove");
}
}
Make sure that unused items elements are set to null otherwise objects referenced from there cannot be garbage collected.
After the for loop shifting down the items add a line:
items[numItems-1] = null;
Related
This question already has answers here:
Cannot make a static reference to the non-static method
(8 answers)
Closed 2 years ago.
Im trying to work on some of the Queue methods, get some practice with them in a little bit so I chose a handful from the list on Oracle's documentation and gave them a shot. Everything in my code seems to be working smoothly except for this one hiccup that I have not been able to get over. I'm pretty new at programming and I am in college for it, but I am still learning the basics. Here is what I have for my code:
import java.util.NoSuchElementException;
public class Queue<E> {
private Object[] queue;
private int size = 0;
private int top;
private int bottom;
public Queue() {
queue = new Object[10];
}
public Queue(int capacity) {
queue = new Object[capacity];
}
#SuppressWarnings("unchecked")
public E elm() {
if (size == 0) {
throw new NoSuchElementException();
}
return (E) queue[top];
}
public boolean add(E elm) {
if (elm == null) {
throw new NullPointerException();
}
if (size == queue.length) {
int newCapacity = (int)Math.ceil(queue.length + 1.5);
Object[] newArr = new Object[newCapacity];
for (int i = 0; i < queue.length; i++) {
newArr[i] = queue[i];
}
}
if (bottom == -1) {
top = 0;
bottom = 0;
queue[bottom]= elm;
} else {
bottom = (bottom +1) % queue.length;
}
queue[bottom] = elm;
size++;
return true;
}
public boolean isEmpty() {
return size == 0;
}
#SuppressWarnings("unchecked")
public E remove() {
if (size == queue.length) {
throw new NoSuchElementException();
}
E elm = (E) queue[top];
top = (top +1) % queue.length;
size--;
if (size == 0) {
bottom = -1;
}
return elm;
}
public void clear() {
return;
}
public int size() {
for (int i = 0; i < queue.length; i++) {
size += 1;
}
return size;
}
boolean contains(Object o) {
if (Queue.contains(o)) {
return true;
} else {
return false;
}
}
}//end of file
the problem lies in the very last block of code. I keep getting the message in Eclipse, telling me "Cannot make a static reference to the non-static method contains(Object) from the type Queue" and it is suggesting I change contains() to static. I have tried this to no avail. When I do change it to static, I only get a repeating error upon running it that says "Exception in thread "main" java.lang.StackOverflowError" and gives the location of the error repeatedly. I am not sure what it is that I am doing wrong here? I'll put my driver below; I was using it to test some of my code but it doesnt have a whole lot in it.
public class Driver {
public static void main(String[] args) {
Queue<Integer> a1 = new Queue<>();
a1.add(10);
a1.add(79);
System.out.println(a1.size());
System.out.println(a1.contains(10));
}
}
Queue.contains is notation of calling a static method of the Queue class, which is why it is complaining.
On changing it to static, you are then just making the contains functions call itself recursively forever which is why it then stack overflows.
You will need to write the code yourself to compare each element for the contains function.
I am trying to print the elements of stack S in reverse (using a "for" loop), but so far I haven't had any success.
I have managed to do it with "pop" fairly easily, but the second way evades me. My solution for "pop" is commented out at the end of the code.
Any help will be appreciated.
PS. Most of this code is irrelevant to the question, but if I knew what and where I can cut out, I probably wouldn't need help at all. Sorry.
package simplearraystackofchars;
public class SimpleArrayStackofchars implements Stack {
protected int capacity; // The actual capacity of the stack array
public static final int CAPACITY = 2; // default array capacity
protected Object S[], K[]; // Generic array used to implement the stack
protected int top = -1; // index for the top of the stack (-1 = empty stack)
public SimpleArrayStackofchars() {
this(CAPACITY); // default capacity
}
public SimpleArrayStackofchars(int cap) {
capacity = cap;
S = new Object[capacity];
}
public int size() {
return (top + 1);
}
public boolean isEmpty() {
return (top == -1);
}
public void push(Object element) throws FullStackException {
if (size() == capacity) {
//throw new FullStackException("Stack is full. Stack size max is "+ capacity);
// can replace previous line with code to double stack size
doubleArray();
}
S[++top] = element;
}
public Object top() throws EmptyStackException {
if (isEmpty()) {
throw new EmptyStackException("Stack is empty.");
}
return S[top];
}
public Object pop() throws EmptyStackException {
Object element;
if (isEmpty()) {
throw new EmptyStackException("Stack is empty.");
}
element = S[top];
S[top--] = null; // dereference S[top] for garbage collection.
return element;
}
private void doubleArray() {
Object[] newArray;
System.out.println("Stack is full (max size was " + capacity + "). Increasing to " + (2 * capacity));
//double variable capacity
capacity = 2 * capacity;
newArray = new Object[capacity];
for (int i = 0; i < S.length; i++) {
newArray[i] = S[i];
}
S = newArray;
}
public static void main(String[] args) {
Stack S = new SimpleArrayStackofchars();
S.push("1");
S.push("2");
S.push("3");
S.push("4");
S.push("5");
S.push("6");
// Stack K is created by popping elements of Stack S from the top.
// This reverses the order.
//
// Stack K = new SimpleArrayStackofchars();
// while (!S.isEmpty()) {
// K.push(S.pop());
// }
// while (!K.isEmpty()) {
// System.out.println(K.pop());
// }
while (!S.isEmpty()) {
System.out.println(S.pop());
}
}
}
Not really sure about what you need that for loop for, but this should produce the same result:
Stack K = new SimpleArrayStackofchars();
for (int i = 0, i < S.size(); i++) {
K.push(S.pop());
}
for (int i = 0, i < K.size(); i++) {
System.out.println(K.pop());
}
I was required to create a simple queue array implementation with basic methods as enqueue, dequeue, isEmpty, and stuff like that. My only problem is that Im stuck when it comes to the resize method, because if I want to add more values to my queue (with fixed size because is an array) I do not know how to make it work and keep all the values in place.
Everything works just in case you were wondering, the only thing is that doesnt work is my resize (the method wrote in here wasn't the only one I tried).
I'm going to put my main method as well if you want to try it, hope you can help, thanks.
Main Method:
public class MainQueue {
public static void main(String[] args) {
int capacity=10;
Queue<Integer> queue = new Queue<Integer>(capacity);
queue.enqueue(1);
queue.enqueue(2);
queue.enqueue(3);
queue.enqueue(4);
queue.enqueue(5);
queue.enqueue(6);
queue.enqueue(7);
queue.enqueue(8);
queue.enqueue(9);
queue.enqueue(10);
System.out.println("Queue: "+ queue);
//WORKS SO FAR
queue.enqueue(11);
//11 is placed at the beginning of the queue
//instead at the end and my last value is null (?)
Class queue:
import java.util.NoSuchElementException;
public class Queue <E>{
private E[] elements;//array in generic
private int front;//first element or front of the queue
private int back;//last element or back of the queue
private int capacity; //capacity of the queue
private int count; //indicates number of elements currently stored in the queue
#SuppressWarnings("unchecked")
public Queue(int size)
{
capacity = size;
count = 0;
back = size-1;
front = 0;
elements =(E []) new Object[size]; //array empty
}
//Returns true if the queue is empty or false
public boolean isEmpty()
{
return count==0;//means its true
}
//Add elements to the queue
public void enqueue(E item)
{
if(count == capacity)
{
resize(capacity*2);
// System.out.println("Queue is full");
}
back =(back+1) % capacity; //example back=(0+1)%10=1
elements[back]=item;
//elements[0]=0
//item=elements[count];
count++;
}
//Public resize
public void resize(int reSize){
E[] tmp = (E[]) new Object[reSize];
int current = front;
for (int i = 0; i < count; i++)
{
tmp[i] = elements[current];
current = (current + 1) % count;
}
elements = tmp;
}
//Dequeue method to remove head
public E dequeue()
{
if(isEmpty())
throw new NoSuchElementException("Dequeue: Queue is empty");
else
{
count--;
for(int x = 1; x <= count; x++)
{
elements[x-1] = elements[x];
}
capacity--;
return (E) elements;
}
}
//peek the first element
public E peek()
{
if(isEmpty())
{
throw new NoSuchElementException("Peek: Queue is empty");
}
else
return elements[front];
}
//Print queue as string
public String toString()
{
if(isEmpty()) {
System.out.println("Queue is empty.");
//throw new NoSuchElementException("Queue is empty");
}
String s = "[";
for(int i = 0; i <count; i++)
{
if(i != 0)
s += ", ";
s = s + elements[i];// [value1,value2,....]
}
s +="]";
return s;
}
public void delete() { //Delete everything
count = 0;
}
}
you forgot to update stuff when resizing:
front, capacity and back .
public void resize(int reSize){
E[] tmp = (E[]) new Object[reSize];
int current = front;
for (int i = 0; i < count; i++)
{
tmp[i] = elements[current];
current = (current + 1) % count;
}
elements = tmp;
front = 0;
back = count-1;
capacity=reSize;
}
You have few mistakes in resizing when enqueing item which expand queue.
in resize algorithm
current = (current + 1) % count; should be (current + 1) % capacity
You have to change capacity value in resize function
capacity = resize;
Why are you changing capacity when dequeing?
I modified a program which creates a Queue and then add or remove items to it.
The problem in my code is that after I remove one item, and then add an item it goes into infinite loop and I'm not sure how to prevent it from happening.
My goal is to modify display() method only.
This is how I display Queue:
public void display()
{
int i = front;
do {
if (maxSize == nItems)
{
if (i == size())
i = 0;
System.out.print(queArray[i++] + " ");
}
else if (maxSize < nItems)
{
System.out.print("Too many queue items!");
break;
}
else
maxSize = nItems;
}
while (i != rear + 1 && !isEmpty());
}
This is how I add and remove items:
public void insert(long j) // put item at rear of queue
{
if(rear == maxSize-1) // deal with wraparound
rear = -1;
queArray[++rear] = j; // increment rear and insert
nItems++; // one more item
}
public long remove() // take item from front of queue
{
long temp = queArray[front++]; // get value and incr front
if(front == maxSize) // deal with wraparound
front = 0;
nItems--; // one less item
return temp;
}
Here is the source code for the same.
import java.util.Arrays;
public class Queue {
private int enqueueIndex;// Separate index to ensure enqueue happens at the end
private int dequeueIndex;// Separate index to ensure dequeue happens at the
// start
private int[] items;
private int count;
// Lazy to add javadocs please provide
public Queue(int size) {
enqueueIndex = 0;
dequeueIndex = 0;
items = new int[size];
}
// Lazy to add javadocs please provide
public void enqueue(int newNumber) {
if (count == items.length)
throw new IllegalStateException();
items[enqueueIndex] = newNumber;
enqueueIndex = ++enqueueIndex == items.length ? 0 : enqueueIndex;
++count;
}
// Lazy to add javadocs please provide
public int dequeue() {
if (count == 0)
throw new IllegalStateException();
int item = items[dequeueIndex];
items[dequeueIndex] = 0;
dequeueIndex = ++dequeueIndex == items.length ? 0 : dequeueIndex;
--count;
return item;
}
#Override
public String toString() {
return Arrays.toString(items);
}
}
Using binarySearch never returns the right index
int j = Arrays.binarySearch(keys,key);
where keys is type String[] and key is type String
I read something about needing to sort the Array, but how do I even do that if that is the case?
Given all this I really just need to know:
How do you search for a String in an array of Strings (less than 1000) then?
From Wikipedia:
"In computer science, a binary search is an algorithm for locating the position of an element in a sorted list by checking the middle, eliminating half of the list from consideration, and then performing the search on the remaining half.[1][2] If the middle element is equal to the sought value, then the position has been found; otherwise, the upper half or lower half is chosen for search based on whether the element is greater than or less than the middle element."
So the prerequisite for binary search is that the data is sorted. It has to be sorted because it cuts the array in half and looks at the middle element. If the middle element is what it is looking for it is done. If the middle element is larger it takes the lower half of the array. If the middle element is smaller it the upper half of the array. Then the process is repeated (look in the middle etc...) until the element is found (or not).
If the data isn't sorted the algorithm cannot work.
So you would do something like:
final String[] data;
final int index;
data = new String[] { /* init the elements here or however you want to do it */ };
Collections.sort(data);
index = Arrays.binarySearch(data, value);
or, if you do not want to sort it do a linear search:
int index = -1; // not found
for(int i = 0; i < data.length; i++)
{
if(data[i].equals(value))
{
index = i;
break; // stop looking
}
}
And for completeness here are some variations with the full method:
// strict one - disallow nulls for everything
public <T> static int linearSearch(final T[] data, final T value)
{
int index;
if(data == null)
{
throw new IllegalArgumentException("data cannot be null");
}
if(value == null)
{
throw new IllegalArgumentException("value cannot be null");
}
index = -1;
for(int i = 0; i < data.length; i++)
{
if(data[i] == null)
{
throw new IllegalArgumentException("data[" + i + "] cannot be null");
}
if(data[i].equals(value))
{
index = i;
break; // stop looking
}
}
return (index);
}
// allow null for everything
public static <T> int linearSearch(final T[] data, final T value)
{
int index;
index = -1;
if(data != null)
{
for(int i = 0; i < data.length; i++)
{
if(value == null)
{
if(data[i] == null)
{
index = i;
break;
}
}
else
{
if(value.equals(data[i]))
{
index = i;
break; // stop looking
}
}
}
}
return (index);
}
You can fill in the other variations, like not allowing a null data array, or not allowing null in the value, or not allowing null in the array. :-)
Based on the comments this is also the same as the permissive one, and since you are not writing most of the code it would be better than the version above. If you want it to be paranoid and not allow null for anything you are stuck with the paranoid version above (and this version is basically as fast as the other version since the overhead of the method call (asList) probably goes away at runtime).
public static <T> int linearSearch(final T[] data, final T value)
{
final int index;
if(data == null)
{
index = -1;
}
else
{
final List<T> list;
list = Arrays.asList(data);
index = list.indexOf(value);
}
return (index);
}
java.util.Arrays.sort(myArray);
That's how binarySearch is designed to work - it assumes sorting so that it can find faster.
If you just want to find something in a list in O(n) time, don't use BinarySearch, use indexOf. All other implementations of this algorithm posted on this page are wrong because they fail when the array contains nulls, or when the item is not present.
public static int indexOf(final Object[] array, final Object objectToFind, int startIndex) {
if (array == null) {
return -1;
}
if (startIndex < 0) {
startIndex = 0;
}
if (objectToFind == null) {
for (int i = startIndex; i < array.length; i++) {
if (array[i] == null) {
return i;
}
}
} else {
for (int i = startIndex; i < array.length; i++) {
if (objectToFind.equals(array[i])) {
return i;
}
}
}
return -1;
}
To respond correctly to you question as you have put it. Use brute force
I hope it will help
public int find(String first[], int start, int end, String searchString){
int mid = start + (end-start)/2;
// start = 0;
if(first[mid].compareTo(searchString)==0){
return mid;
}
if(first[mid].compareTo(searchString)> 0){
return find(first, start, mid-1, searchString);
}else if(first[mid].compareTo(searchString)< 0){
return find(first, mid+1, end, searchString);
}
return -1;
}
Of all the overloaded versions of binarySearch in Java, there is no such a version which takes an argument of String. However, there are three types of binarySearch that might be helpful to your situation:
static int binarySearch(char[] a, char key);
static int binarySearch(Object[] a, Object key);
static int binarySearch(T[] a, T key, Comparator c)