My queue uses a stack hence I have two stacks.. s1 that accepts the add, then all of its items get moved into s2 which makes s2 my queue.
(no use of arrays..)
here is my implementation but when I test it, my remove unit test fails.
public class Queue
{
private Stack s1;
private Stack s2;
private int size;
public Queue()
{
//arbitrary sized.
s1 = new Stack();
s2 = new Stack();
size = 0;
}
public void insert(Object o)
{
//add object into s1.
s1.push(o);
size++;
}
//delete from queue
public Object remove()
{
int n = 0; ... arbitrary size n. //size not specified
for(int i = 1; i <= n ; i++)
{
//push all elements in s1 into s2
s2.insert(s1.pop());
}
//decrease the size
size--;
return s2.pop;
}
public Object peekFront()
{
s2.push(s1.pop());
return s2.peek();
}
}
TEST
import org.junit.Assert;
import static org.junit.Assert.*;
import org.junit.Test;
public class QueueTest
{
protected Queue q;
public QueueTest()
{
q = new Queue();
}
atTest
public void testRemove()
{
assertTrue(q.isEmpty()); -- passes
q.insert(10);
q.insert(11);
q.insert(12);
q.insert(23);
//remove
assertEquals(10, q.remove()); --- fails
}
public void testPeekFront()
{
q.insert(80);
q.insert(90);
q.insert(57);
assertEquals(20,q.peekFront());
}
}
Please can you put me in the right direction on why my public Object remove is not functioning correctly...
For example when I try to remove 23? My test passes but when I test for 10 which actually should be, then it fails.
Here is the complete code..... for both the class and the test...
I think you may be providing a static value for n. As the value n , will change dynamically, please make sure you are giving n=s1.size() [or any custom function to calculate size]. Please provide the complete code.
Assumed Fixes:
1. You are popping out all elements from s1 , during remove. Making it(s1) empty stack. So you have to fill it back by popping the values from s2 in the remove function itself. As fabian mentioned in the next answer use a helper method for transfering of elements from 1 stack to another.
2.In remove() method, store s1.pop() to a temp variable and remove all elements in s2. return temp variable. Other wise s2 will keep on growing.
3. set n = s1.size();
4. return s1.pop();
For the method to work you cannot simply hardcode the size. Furthermore you have to move the elements back to the original stack before the next insertion, or the order becomes wrong. I recommend transfering the objects in a helper method to avoid code duplication:
private static void transfer(Stack source, Stack target) {
while (!source.isEmpty()) {
target.push(source.pop());
}
}
I recommend moving the elements lazily to avoid unnecessary operations for repeated insert or repeated remove operations:
public void insert(Object o) {
// lazily transfer values back
transfer(s2, s1);
//add object into s1.
s1.push(o);
size++;
}
//delete from queue
public Object remove() {
if (s1.isEmpty() && s2.isEmpty()) {
return null; // alternative: throw exception
}
transfer(s1, s2);
//decrease the size
size--;
return s2.pop();
}
public Object peekFront() {
if (s1.isEmpty() && s2.isEmpty()) {
return null; // alternative: throw exception
}
transfer(s1, s2);
return s2.peek();
}
Alternatively you could simply transfer the values back to s1 in the remove method, which would make it a bit simpler to implement additional operations, however it would also make some operation sequences less efficient. (You also still need to fix peekFront()):
//delete from queue
public Object remove() {
if (s1.isEmpty() && s2.isEmpty()) {
return null; // alternative: throw exception
}
transfer(s1, s2);
//decrease the size
size--;
Object result = s2.pop();
transfer(s2, s1);
return result;
}
Related
I'm new to this site, so please feel free to correct me if there's anything wrong about my question or the style of the question.
I need to implement the Iterable Interface in my ShareCollection class, so that I can iterate over all the shares in this class. When I'm testing my class with the sample data it always hands back '0' as size, even though there are (in my example) two shares in my collection.
Here's the code of the class + one sample method which hands back an error:
public class ShareCollection implements Iterable<Share>{
private HashSet<Share> shares;
public ShareCollection() {
this.shares = new HashSet<Share>();
}
public ShareCollection(Collection<Share> shares) {
for (Share s : shares) {
HashSet<Share> checkSet = new HashSet<Share>(shares);
checkSet.remove(s);
if (checkSet.contains(s)) {
throw new IllegalArgumentException("There can't be two shares with the same name!");
}
}
this.shares = new HashSet<Share>(shares);
}
public boolean add(Share share) {
if (share == null) {
throw new NullPointerException("share isnt allowed to be null!");
}
return shares.add(share);
}
#Override
public Iterator<Share> iterator() {
return new HashSet<Share>(shares).iterator();
}
}
Here's the main method with the sample data I'm using:
public static void main(String[] args) {
Share s1 = new Share("s1", new ArrayList<>());
Share s2 = new Share("s2", new ArrayList<>());
ShareCollection sc = new ShareCollection()
sc.add(s1);
sc.add(s2);
int counter = 0;
for (Share s : sc) {
counter++;
}
System.out.print("Counter: " + counter + "\n");
System.out.print("Size: " + sc.size());
}
Here's the output for the main-method:
Counter: 2
Size: 0
Here's the error for the 'add'-method:
java.lang.AssertionError: ShareCollection#size should give 1 for a collection with 1 elements.
Expected: <1>
but: was <0>
at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:20)
at org.junit.Assert.assertThat(Assert.java:956)
at jpp.marketanalysis.tests.data.TestShareCollection.hasElements(TestShareCollection.java:158)
at jpp.marketanalysis.tests.data.TestShareCollection.testAdd(TestShareCollection.java:55)
Thank you in advance for your answers!
Update:
Exchanged the ArrayList with a HashSet (see #SeanPatrickFloyd's first answer)
Possible error: Does your Share class override the .equals() method?
Because ArrayList.contains() delegates to .equals()
Also, I see at least two problems with your code:
An ArrayList is very bad at a .contains() lookup (O(n)). You should use a HashSet instead (in that case you'd need to override both .equals() and .hashCode() in your Share class), it gives you O(1) and handles the .add() method properly for you as well
The Iterator you are returning is the ArrayList's original iterator, which makes your code vulnerable in several ways, including ConcurrentModificationException if you add something while iterating, but also mutation, if someone calls .remove() on the iterator. I'd suggest you make a defensive copy of the collection and use that iterator.
Here's your code rewritten accordingly:
public class ShareCollection implements Iterable<Share>{
private final Set<Share> shares;
public ShareCollection() {
this.shares = new HashSet<>();
}
public ShareCollection(Collection<Share> shares) {
this.shares = new HashSet<>(shares);
}
public boolean add(Share share) {
if (share == null) {
throw new NullPointerException("share isnt allowed to be null!");
}
return shares.add(share);
}
#Override
public Iterator<Share> iterator() {
return new HashSet<>(shares).iterator();
}
}
I'm sitting on an assignment for university and I'm at a point, where I fear I haven't really understood something fundamental in the concecpt of Java or OOP altogether. I'll try to make it as short as possible (maybe it's sufficient to just look at the 3rd code segment, but I just wanted to make sure, I included enough detail). I am to write a little employee management. One class within this project is the employeeManagement itself and this class should possess a method for sorting employees by first letter via bubblesort.
I have written 3 classes for this: The first one is "Employee", which contains a name and an ID (a running number) , getter and setter methods and one method for checking whether the first letter of one employee is smaller (lower in the alphabet) than the other. It looks like this:
static boolean isSmaller(Employee source, Employee target) {
char[] sourceArray = new char[source.name.length()];
char[] targetArray = new char[target.name.length()];
sourceArray = source.name.toCharArray();
targetArray = target.name.toCharArray();
if(sourceArray[0] < targetArray[0])
return true;
else
return false;
}
I tested it and it seems to work for my case. Now there's another class called EmployeeList and it manages the employees via an array of employees ("Employee" objects). The size of this array is determined via constructor. My code looks like this:
public class EmployeeList {
/*attributes*/
private int size;
private Employee[] employeeArray;
/* constructor */
public EmployeeList(int size) {
this.employeeArray = new Employee[size];
}
/* methods */
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
/* adds employee to end of the list. Returns false, if list is too small */
boolean add(Employee m) {
int id = m.getID();
if (id > employeeArray.length) {
return false;
} else {
employeeArray[id] = m;
return true;
}
}
/* returns employee at certain position */
Employee get(int index) {
return employeeArray[index];
}
/* Sets employee at certain position. Returns null, if position doesn't exist. Else returns old value. */
Employee set(int index, Employee m) {
if (employeeArray[index] == null) {
return null;
} else {
Employee before = employeeArray[index];
employeeArray[index] = m;
return before;
}
}
Now comes my real problem: In a third class called "employeeManagement" I am supposed to implement the sorting algorithm. The class looks like this:
public class EmployeeManagement {
private EmployeeList ml = new EmployeeList(3);
public boolean addEmployee(Employee e) {
return ml.add(e);
}
public void sortEmployee() {
System.out.println(ml.getSize()); // I wrote this for debugging, exactly here lies my problem
for (int n = ml.getSize(); n > 1; n--) {
for (int i = 0; i < n - 1; i++) {
if (Employee.isSmaller(ml.get(i), ml.get(i + 1)) == false) {
Employee old = ml.set(i, ml.get(i + 1));
ml.set(i+1, old);
}
}
}
}
The "println" before my comment returns "0" in console... I am expecting "3" as this is the size I gave the "EmployeeList" as parameter of the constructor within my "EmployeeManagement" class. Where is my mistake ? And how can I access the size of the object I created in the "EmployeeManagement" class (the "3") ? I'm really looking forward to your answers!
Thanks,
Phreneticus
You are not storing size in your constructor. Something like,
public EmployeeList(int size) {
this.employeeArray = new Employee[size];
this.size = size; // <-- add this.
}
Also, setSize isn't going to automatically copy (and grow) the array. You will need to copy the array, because Java arrays have a fixed length. Finally, you don't really need size here since employeeArray has a length.
The size variable you are calling is the class field. If you take a quick look at your code, the getter is getting the field (which is initialized as zero when created). The size you are using it. The good way of doing it would be to get the size of the array in the getter like this:
public int getSize() {
return employeeArray.length;
}
This would return the size of the array in the object.
Simple Linked List
public class List_manager {
Entry first;
Entry last;
public void add(String el) {
if (isEmpty()) { first=new Entry(el); last=first; return; }
new Entry(el,last);
}
public String get() {
Entry temp=first;
first=first.next;
return temp.data;
}
public boolean isEmpty() {
return first==null;
}
private class Entry {
String data;
Entry next;
public Entry(String data,Entry to) {
this.data=data;
to.next=this;
to=this;
}
public Entry(String data) {
this.data=data;
}
}
}
#The main class#
I added 3 element and list contains only 2... why?
public class Main {
public static void main(String[] args) {
List_manager l=new List_manager();
l.add("1");
l.add("2");
l.add("3");
System.out.println(l.get());
System.out.println(l.get()); // Why here output: "3"??
System.out.println(l.get()); // here is an error occurs
}
}
I really don`t get why list contains 2 elements?
Why it ignores 2nd added element?
to=this; This sentence have no influence on variable 'last', because veriable 'to' is formal parameter, while variable 'last' is actual parameter. So, when you executed this sentence "to = this;" the value of
variable 'last' was not changed to next.That's mean variable 'last' always pointed to the first element.
my change is : new Entry(el,last); --> last = new Entry(el,last);
Things look better.
Think about what your get method is doing. You already noticed some aberrant behavior with it.
public String get() {
Entry temp=first;
first=first.next;
return temp.data;
}
What happens the first time I call this?
temp gets whatever first is pointing to
first is moved to its next element (RED FLAG)
temp's data is returned...
One problem is that you're moving your head reference around - this is a bad idea, since it means that you can never access the true first element in your list ever again.
Now on its own, even with this implementation, you should still be able to get the first element.
The above was just a red herring - although you should not be moving your head pointer around. This is the real problem. What happens on subsequent add calls to your list?
public void add(String el) {
if (isEmpty()) {
first = new Entry(el);
last = first;
return;
}
new Entry(el,last);
}
Only the first element inserted and the last element inserted are respected. All other entries after next are overwritten.
I suggest that you use a debugger to figure this one out, as it stems from a misunderstanding of a good approach to do this. You only want to insert things through your tail pointer once you have one element. Doing this through object creation only causes heartache and confusion.
For posterity, I'll leave you with a sample, verbatim implementation I wrote for a singly linked list implementation I did a while back. It describes a more viable approach to inserting into a list.
public void insert(E data) {
Node<E> candidate = new Node<>(data);
if(head == null) {
head = candidate;
tail = head;
} else {
tail.setNext(candidate);
tail = tail.getNext();
}
size = size + 1;
}
So I'm making a search algorithm. I'm using a queue to store all of my objects
This is how I initialised it
Queue<Node> queue = new LinkedList<Node>();
I want to compare a variable in each object and order to queue. My plan is to use a for loop to compare the first object with each of the other objects and whichever object has the lowest variable is sent to the front of the queue. Then move onto the next object and repeat the process. My issue is I'm not sure how to retrieve an object from the queue that isn't the first object in the queue....
You could do a for loop through the Queue:
for (Node n : queue) {
do stuff with n
}
However, you aren't going to be able to remove items from the middle of the queue. Might I suggest a structure like an ArrayList?
In my opinion the best way is to use PriorityQueue. You can specify implementation of Comparator interface that will impose how elements should be sorted inside of queue.
Here is an example:
Let's say that this is your Node class:
public class Node {
// this field will be used to sort in queue
private int value;
public Node(int value) {
this.value = value;
}
public int getValue() {
return value;
}
#Override
public String toString() {
return "My value is: " + value;
}
}
And here is example of adding Nodes into queue:
import java.util.PriorityQueue;
import java.util.Random;
public class QueueExample {
public static void main(String[] args) {
Random r = new Random();
// Priority queue with custom comparator
PriorityQueue<Node> queue = new PriorityQueue<Node>(10, new SampleNodeComparator());
// adding 100 nodes with random value
for(int i = 0; i < 100; ++i) {
queue.add( new Node(r.nextInt(1000)));
}
// nodes will be removed from queue in order given by comparator
while(queue.size() != 0) {
System.out.println(queue.remove());
}
}
}
And the most important part - implementation of our custom comparator
import java.util.Comparator;
// our comparator needs to implements Comparator interface
public class SampleNodeComparator implements Comparator<Node> {
#Override
public int compare(Node o1, Node o2) {
/*
value that should be return from compare method should follow rules:
if o1 == o2 - return 0
if o1 > o2 - return any positive value
if o1 < 02 - return any negative value
*/
return o1.getValue() - o2.getValue();
}
}
When you run main method from QueueExample class you will see on console that values are removed from queue sorted by Node.value value.
Use Queue<E>#peek () to retrieve an object without removing it.
Some example code:
import java.util.*;
class Example {
public static void main (String[] args) throws Exception {
Queue<String> list = new PriorityQueue<>();
{ // Initialize the Queue
list.add ("Hello ");
list.add ("Mrs. ");
list.add ("DoubtFire! ");
}
System.out.println (list);
// Iterating through the Queue
String element;
while ( (element = list.peek()) != null) {
if (element.equals ("Mrs. ")) {
System.out.println ("\"Mrs\" found!");
}
System.out.println (element);
list.remove (element);
}
System.out.println (list); // Empty by now...
}
}
Output:
[DoubtFire! , Mrs. , Hello ]
DoubtFire!
Hello
"Mrs" found!
Mrs.
[]
Queue interface does not guarantee any particular order while iterating or polling so theoretically this task is impossible to implement with Queue.
Seeing your response to my comment, I think that in your case, you should use the PriorityQueue because it does what you need without needing you to reinvent the wheel, which is usually not recommended.
By default, the priority queue will use the default implementation of the compareTo method. Assuming that you have a composite type, you have two options:
You can make your custom class implement the Comparabale interface and have your sorting logic there.
Alternatively, you could pass your own comparator:
PriorityQueue<..> p = new PriorityQueue<..>(5, new Comparator<..>()
{
#override
public int compare(.. type1, .. type2)
{
//comparison logic done here.
}
}
You can take a look at this short tutorial for more information.
I'm working on sorted Queues like a Priority Queue. I already did it with a List, and it already worked great. Now I'd like to do it with a array. But I have a little logical Problem with add a new Element and insert it into the sorted array.
The final output should be like that:
Priority: 5 Value: x
Priority: 4 Value: iso
.... (and so on)
So the Element with the highest Priorithy should be on index = 0.
I just don't know (and yes I know it's really simply to switch it, but I just can't do it :/) how to do it...
I already tried a few things but I'm stuck... :/ can please anyone help?
Here's my code:
public class Queue {
private QueueElem[] a;
public Queue(int capacity)
{
QueueElem[] tempQueue = new QueueElem[capacity];
a= tempQueue;
}
public void enqueue(int p, String v)
{
QueueElem neu = new QueueElem(p,v);
int i=0;
while(i<a.length)
{
if (a[i] == null)
{
a[i] = neu;
break;
}
i++;
}
}
public void writeQueue()
{
int i=0;
while((i< a.length) && (a[i] != null))
{
System.out.println("Priority: " + a[i].priority + " Value: " + a[i].value);
i++;
}
}
public static void main(String args[])
{
Queue neu = new Queue(10);
neu.enqueue(4,"iso");
neu.enqueue(2,"abc");
neu.enqueue(5,"x");
neu.enqueue(1,"abc");
neu.enqueue(4,"bap");
neu.enqueue(2,"xvf");
neu.enqueue(4,"buep");
}
}//end class Queue
class QueueElem {
int priority;
String value = new String();
public QueueElem(){ }
public QueueElem(int p, String v)
{
this.priority = p;
this.value = v;
}
public int getPrio()
{
return this.priority;
}
public String getValue()
{
return this.value;
}
}
It would be better if you interpreted your array as a max-heap. That is the typical way to implement priority queue.
What you're looking for, if you're trying to maintain a sorted array for your priority queue, is to implement insertion sort (sort of; you don't have an unsorted array to start with. You have an empty array that you simply add to, while maintaining a sorted order). Every time you insert a new element, you will iterate through the array to find the correct spot and then insert it there, after shifting the elment currently at that spot, and everything after it one spot down. Note that this is not as performant as implementing this using a heap, since at worst you have O(n) performance every time you insert, whereas with a heap you have O(logn).
I don't understand why anyone would want to work with raw arrays... especially now that you have implemented it with a List.
If you want to see how to insert an element in a raw array, look in the code of ArrayList, since underneath it uses a raw array. You'll have to move all the elements to right of the insertion point, which you could copy in a loop, or by using System.arraycopy(). But the nastiest part is that you will likely have to create a new array since the array size increases by one when you add an element (it depends if you are using an array that has exactly the size of your data, or a larger array, as is done in ArrayList).