For my data structures class, we have to create our own Stack data type and the implementation for it as a project. The problem I'm running into is when the professor asked us to implement an equals(Object object) method. Heres what I have so far...
package stack;
import list.*;
public class Stack <E>
implements StackADT<E>//the interface
{
List <E> values;
public Stack()
{
values = new ArrayList<E>();
}
public E push(E value)
{
values.add(value);
return value;
}
public E pop()
{
return values.remove(values.size()-1);
}
public E peek()
{
return values.get(values.size()-1);
}
/** #return true only if this Stack is empty */
public boolean isEmpty()
{
return (values.size()==0);
}
/** Clear this stack, to make it an empty stack */
public void clear()
{
for (int i = 0; i < values.size()-1; i++)
{
pop();
}
}
public String toString()
{
String result = "[";
for (int i = 0; i<values.size(); i++)
{
if (i == values.size()-1)
{
result = result + values.get(i);
}
else
{
result = result + values.get(i) +",";
}
}
result = result + "]";
return result;
}
public boolean equals (Object object)
{
if (!(object instanceof StackADT))
{
return false;
}
StackADT <E> otherStack = new Stack<E>();
for(Object o: object)//heres where i run into trouble
{
otherStack.push(o);
}
for (int i=0;i<values.size()-1;i++)
{
if (!(values.get(i).equals(otherStack.pop())))
{
return false;
}
}
return true;
}
}
Our Stack is pretty much an ArrayList which we also built in our class. the problem is, I cant add the Object object into a stack because its not something thats iteratable(?able to be iterated over). Is there a better way to do this? I would think a get() would work, since the Stack I create is an ArrayList, but whenever I use get() on otherStack, it can't find the method. I had a temporary solution when I tried casting object as a stack(I hope im using the right terminology). It looked something like this
Stack otherStack = (Stack) object;
for (int i=0;i<values.size()-1;i++)
{
if (!(values.get(i).equals(otherStack.pop())))
{
return false;
}
}
return true;
}
this seemed to work, but when pop() was called on otherStack, the values in the original list(the one that becomes otherStack) that was passed into the equals() method we're also popped from the original list, leading to an incorrect result. Is there a better way to do this without adding in any other methods? I'm trying to stick as close to the formula set up by my professor as possible, so I dont want to add any extra fields or methods.
any and all help is appreciated
An equals method is not supposed to create anything, not even a temporary object. Rather than creating a new otherStack, cast the object that you have checked to be StackADT, like this:
// This should be the first line of any equals() implementation:
if (object == this) {
return true;
}
// You've got this part right: you need to check the other object's type
if (!(object instanceof StackADT)) {
return false;
}
// Now that you know the type, cast the other object to StackADT<E>
StackADT<E> otherStack = (StackADT<E>)object;
// The next step is to check the sizes:
if (values.size() != otherStack.values.size()) {
return false;
}
// Finally, go through the individual elements in a loop
In the loop that follows, do not pop the other stack. Do not do anything that can modify it. Simply go through the underlying storage (i.e. values), and check elements one by one.
Don't forget to override hashCode as well: you need to do it every time when you override equals for the object to fulfill the contract specified by java.lang.Object.
Related
The Inventory consists of two arrays, one an array of objects[10] and one an array of ints[10]. The array of objects is to identify an item, and the array of ints is supposed to keep track of how many you have. For some reason the code is producing all kinds of errors. Not really sure what to do!
public void additem(Object newItem) {
if (itemsInInventory == 0) {
invent[0] = newItem;
inventItemAmount[0]++;
itemsInInventory++;
}else if (itemsInInventory > 0) {
for (int i = 0; i < itemsInInventory; i++) {
if (invent[i].getItemNum() == newItem.getItemNum()) {
inventItemAmount[i]++;
} else {
invent[itemsInInventory] = newItem;
inventItemAmount[itemsInInventory]++;
itemsInInventory++;
}
}
}
}
Complete code can be found here: https://github.com/YungSheep/HitsujiStories
I see in your GitHub code that your inventory is limited to 10 ; and your if-else condition doesn't hold any case for itemsInInventory > 10, that will first give you an idea of where your NPE comes from. It might be better for you to change your current else if condition to something like "a > 0 && a <= max" then add a case when it's higher than your max capacity.
EDIT : Also, I'm pretty sure I know why you get messed up amounts for each type of item : if you imagine the if-else statement inside a loop, the item slot [0] would only be accessible once, when the player has an empty inventory. That means I can't add up any further in the slot [0] if I picked an item and set itemsInInventory to another number than 0 ! You might have to rebuild your if-else contents.
SECOND EDIT : In case you find it messy to code, I suggest you to make an InventorySlot class :
public class InventorySlot {
private Object object;
private int amount;
// CONSTRUCTOR (assuming you don't instanciate filled slots)
public InventorySlot() {
this.setObject(null);
this.setAmount(0);
}
// GETTERS AND SETTERS
public Object getObject() {
return this.object;
}
public int getAmount() {
return this.amount;
}
public void setObject(final Object object) {
this.object = object;
}
public void setAmount(final int amount) {
this.amount = amount;
}
// METHOD THAT ADDS NEW ITEM IF MATCHES. RETURNS BOOLEAN TO TELL IF SUCCEEDED
public bool addIfMatches(final Object object) {
if (this.getObject.getItemNum() == object.getItemNum()) {
this.setAmount(this.getAmount++);
return true;
} else {
return false;
}
}
// AND OTHER USEFUL METHODS...
}
Hope this helps you, happy coding !
I need help with removing just added element from the arrayList.
I have a private static ArrayList<Position> positions = new ArrayList<>() to which I'm adding objects of the class Position with parameters name, quantity, and price.
Than I have a method adding objects to the list, and in case if the same product is added for the second time, it is supposed to add the quantity to the first object of that name and remove that second one.
So far I have this method:
public void addPosition(Position p) {
for (Position poz: positions) {
if (poz.getname().equals(p.getname())) {
poz.setquantity(poz.getquantity() + p.getquantity());
}
} positions.add(p);
}
Adding quantities works just fine, but I've got problem with removing the element with recurring name.
Please help.
You shouldn't add duplicate items and then remove them. Just declare a method which handles adding items correctly; that is, it adds the item if it does not exist, and it updates the quantity if it does exist.
It should look like this:
public void addPosition(Position addition) {
//flag to track whether the new item exists in the list
boolean itemExists = false;
//go through the list looking for an item with the passed name to update
for (Position existing : positions) {
if (existing.getName().equals(addition.getName())) {
existing.setQuantity(existing.getQuantity() + addition.getQuantity());
itemExists = true;
}
}
//if no matching item was found, add the new item
if (!itemExists) {
positions.add(addition);
}
}
The above should work. If you care about performance, it might be better to use a HashMap so you can look up the Position by name instead of looping through the whole list each time.
If you are interested to know other data Structure , i want suggest you HashSet , by default it will not insert duplicates for primitive objects .
In your case the only thing you need to do to your Position class , is to add
equals and hashCode methods . As getters and setters Eclipse for example will create by him self .
hashCode()
As you know this method provides the has code of an object. Basically the default implementation of hashCode() provided by Object is derived by mapping the memory address to an integer value. If look into the source of Object class , you will find the following code for the hashCode. public native int hashCode(); It indicates that hashCode is the native implementation which provides the memory address to a certain extent. However it is possible to override the hashCode method in your implementation class.
equals()
This particular method is used to make equal comparison between two objects. There are two types of comparisons in Java. One is using “= =” operator and another is “equals()”. I hope that you know the difference between this two. More specifically the “.equals()” refers to equivalence relations. So in broad sense you say that two objects are equivalent they satisfy the “equals()” condition. If you look into the source code of Object class you will find the following code for the equals() method.
Here a complete working example ( you can modify your class following this cose)
import java.util.HashSet;
public class Zhashset{
private int num;
public Zhashset(){
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + num;
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Zhashset other = (Zhashset) obj;
if (num != other.num)
return false;
return true;
}
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
HashSet<Zhashset> hs = new HashSet<Zhashset>();
hs.add(new Zhashset());
hs.add(new Zhashset());
for(Zhashset item : hs)
System.out.println(item.getNum());
}
}
Output will be : 0 written only once.
I need to use the class ReturnObjectImpl to basically find errors when I add an element to the ArrayList data structure class (this is a university assignment).
I am not sure how I get my functions in the ArrayList class to return ReturnObject. I need some way of passing everything through to ReturnObject, checking if there is an error (which I am not sure how to do either) and then providing either an error message or the object.
public interface ReturnObject {
/**
* Returns whether there has been an error
* #return whether there has been an error
*/
public boolean hasError();
/**
* Returns the error message.
*
* This method must return NO_ERROR if and only if
* {#hasError} returns false.
*
* #return the error message
*/
public ErrorMessage getError(); //Changes the return to a String has in the interface ErrorMessage is throwing an error - if marks are deducted, please discuss with me
/**
* Returns the object wrapped in this ReturnObject, i.e. the
* result of the operation if it was successful, or null if
* there has been an error.
*
* Note that the output of this method must be null if {#see
* hasError} returns true, but the opposite is not true: if
* {#see hasError} returns false, this method may or may not
* return null.
*
* #return the return value from the method or null if there has been an error
*/
public Object getReturnValue();
}
And then there is the class itself (which in currently incomplete):
public class ReturnObjectImpl implements ReturnObject {
// Constructor for successful operation
ReturnObjectImpl (Object c){
if (!hasError()){
getReturnValue(c);
}
}
// Constructor for error
ReturnObjectImpl (){
if (hasError()){
// getError();
}
}
public boolean hasError() {
//returns true or false depending on if there is an error
return null;
}
public ErrorMessage getError() { //Changes the return to a String has in the interface ErrorMessage is throwing an error - if marks are deducted, please discuss with me
//returns the error message is hasError == true or NO_ERROR if hasError() returns false
return ErrorMessage;
}
public Object getReturnValue() {
// TODO Auto-generated method stub
return null;
}
}
And finally the ArrayList class
public class ArrayList implements List{
public static final int CAPACITY=16;
private int size = 0;
private Object[] data;
//constructors
public ArrayList() {
data = new Object[CAPACITY];
} //Constructs arraylist with default capacity
public ArrayList(int capacity) { // Constructs arraylist with given capacity
data = new Object[capacity];
System.out.println("Created an ArrayList of capacity " + capacity);
}
public boolean isEmpty(){
return (size == 0);
}
public int size(){
System.out.println("The ArrayList is not full, but currently has " + size + " indexs");
return size;
}
public ReturnObject get(int index){
return null; //INCOMPLETE
}
public ReturnObject remove(int index){
return null;
}
public ReturnObject add(int index, Object item){
if(index <= size && index < data.length){
for (int x = size-1; x >= index; x--){
data[x+1] = data[x];
size++;
}
data[index] = item;
System.out.println("Added to array at " + index);
}
return null;
}
public ReturnObject add(Object item){
if (data[0] == null){
data[0] = item;
}
//int adding = size + 1;
data[size] = item;
System.out.println("Added item to index " + size);
size++;
return null;
}
//added - but DELETE BEFORE SUBMITTING
public void printAll(){
for(int x = 0; x < data.length; x++){
System.out.println(data[x]);
}
}
}
In short, I have two issues:
1. What the functions for error checking should look like in returnObjectImpl
2. More significantly, how I supposed to send the results of, say, public ReturnObject add(Object item) from ArrayList class to ReturnObjectImpl.
If List is the java.util.List interface, you have some serious mistakes here:
List is a generic interface, but your ArrayList is not generic. (If you were coding this for Java 1.4.x, that would be OK. But Java 1.4.x was retired > 10 years ago!)
Your ArrayList methods are incompatible with the java.util.List API. For example, add should return a boolean, get should return the element type (or Object if you are ignoring generics) not some other type.
If not ... then calling the interface List is a bad idea. Ditto for ArrayList. You shouldn't "borrow" the names of standard classes and interfaces like this. It will get you into trouble.
To answer your questions:
1) What the functions for error checking should look like in returnObjectImpl.
There is no returnObjectImpl method. And the error checking does not belong in the ReturnObjectImpl class. That class (per its name and API design) is simply a "holder" that represents either a value or an error condition. The actual error checking code belongs in your array list class; e.g. some thing like this.
if (/* some error */) {
return new ReturnObjectImpl(/* some error message */);
}
2) More significantly, how I supposed to send the results of, say, public ReturnObject add(Object item) from ArrayList class to ReturnObjectImpl.
if (/* not an error */) {
return new ReturnObjectImpl(/* the value */);
}
Obviously you are going to have to redesign the ReturnObjectImpl constructors to make that work.
Opinion: I think someone may have gotten into the "don't use exceptions" mindset that afflicts1 some people who have learned to program in (say) C or C++. Without getting into the debate over whether exceptions are "good" or "bad", the fact remains that they are an integral part of the Java language, and they are used consistently throughout the the Java language and class libraries. You cannot avoid them, and you will hurt yourself if you try.
If this was your design, and you really want to avoid exceptions this much ... you should be using a different programming language2.
1 - That isn't intended to be perjorative, but I'm afraid that "avoid exceptions" thinking rarely (if ever) gives a good outcome in terms of Java productivity or maintainability.
2 - I'm reminded of the line "Real programmers can write FORTRAN in any language".
I've created my own Stack class but need to implement a get method to return a stack element based on an index passed within the args. I've created a contains method and would of assumed get would work in a similar fashion.
My question is how would I implement the get method? I want to basically implement the get method that Stack inherits from the Vector class in the standard library. See -http://docs.oracle.com/javase/1.4.2/docs/api/java/util/Vector.html#get%28int%29
Here is my contains method below.
public boolean contains (T value){
T t = top.item;
Object node = t;
while(node!=null)
{
if(node==value){
return true;
}
else {
node=top.next;
}
}
return false;
}
The classical Stack does not support that operation, and truly should not extend Vector.
The operations that it supports are:
push(item)
pop();
peek();
So what you want to do, if you want to use a data structure to back your Stack is to use an instance of a List which will allow you to mirror what the original Sun team did.
function contains(Item item)
{
return Stack.getList().contains(item)
}
If instead you want to just use an array as the backing you would need to iterate over each value in the array and perform an equals comparison on it.
function contains(Item item)
{
for(int i = 0; i < itemArray.length;i++)
{
if(itemArray[i] == item)
{
return true;
}
}
return false;
}
Why Methode LinkedList.contains() runs quickly than such implementation:
for (String s : list)
if (s.equals(element))
return true;
return false;
I don't see great difference between this to implementations(i consider that search objects aren't nulls), same iterator and equals operation
Let's have a look at the source code (OpenJDK version) of java.util.LinkedList
public boolean contains(Object o) {
return indexOf(o) != -1;
}
public int indexOf(Object o) {
int index = 0;
if (o==null) {
/* snipped */
} else {
for (Entry e = header.next; e != header; e = e.next) {
if (o.equals(e.element))
return index;
index++;
}
}
return -1;
}
As you can see, this is a linear search, just like the for-each solution, so it's NOT asymptotically faster. It'd be interesting to see how your numbers grow with longer lists, but it's likely to be a constant factor slower.
The reason for that would be that this indexOf works on the internal structure, using direct field access to iterate, as opposed to the for-each which uses an Iterator<E>, whose methods must also additionally check for things like ConcurrentModificationException etc.
Going back to the source, you will find that the E next() method returned by the Iterator<E> of a LinkedList is the following:
private class ListItr implements ListIterator<E> {
//...
public E next() {
checkForComodification();
if (nextIndex == size)
throw new NoSuchElementException();
lastReturned = next;
next = next.next;
nextIndex++;
return lastReturned.element;
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
This is considerably "busier" than the e = e.next; in LinkedList.contains! The iterator() of a LinkedList is actually a ListIterator, which has richer features. They aren't needed in your for-each loop, but unfortunately you have to pay for them anyway. Not to mention all those defensive checks for ConcurrentModificationException must be performed, even if there isn't going to be any modification to the list while you're iterating it.
Conclusion
So yes, iterating a LinkedList as a client using a for-each (or more straightforwardly, using its iterator()/listIterator()) is more expensive than what the LinkedList itself can do internally. This is to be expected, which is why contains is provided in the first place.
Working internally gives LinkedList tremendous advantage because:
It can cut corners in defensive checks since it knows that it's not violating any invariants
It can take shortcuts and work with its internal representations
So what can you learn from this? Familiarize yourself with the API! See what functionalities are already provided; they're likely to be faster than if you've had to duplicate them as a client.
I decided to test this and came out with some interesting result
import java.util.LinkedList;
public class Contains {
private LinkedList<String> items = new LinkedList<String>();
public Contains(){
this.addToList();
}
private void addToList(){
for(int i=0; i<2000; i++){
this.items.add("ItemNumber" + i);
}
}
public boolean forEachLoop(String searchFor){
for(String item : items){
if(item.equals(searchFor))
return true;
}
return false;
}
public boolean containsMethod(String searchFor){
if(items.contains(searchFor))
return true;
return false;
}
}
and a JUnit testcase:
import static org.junit.Assert.assertEquals;
import org.junit.Test;
public class ContainsTest {
#Test
public void testForEachLoop(){
Contains c = new Contains();
boolean result = c.forEachLoop("ItemNumber1758");
assertEquals("Bug!!", true, result);
}
#Test
public void testContainsMethod(){
Contains c = new Contains();
boolean result = c.containsMethod("ItemNumber1758");
assertEquals("Bug!!", true, result);
}
}
This funny thing is when I run the JUnit test the results are :
- testForEachLoop() - 0.014s
- testContainsMethod() - 0.025s
Is this true or I am doing something wrong ?