I have a question about this block of Java code. (Yes, I am a beginner). The code works, I am just a little confused. This code checks the people and cars arrays to find if it has empty seats, which is what the tryToAdd method does. It will then add the person to that car. My question is about the boolean values. It looks to me that added is set to false. Then in the for loop it says: as long as added is true..do the loop. So, it seems that the loop should never run.
public void loadPassengers() {
for (Person p : people) {
boolean added = false;
for (int i = 0; !added && i < cars.size(); i++) {
added = cars.get(i).tryToAdd(p);
}
}
}
Then in the for loop it says: as long as added is true
Actually, it says the opposite of that. Look again:
for (int i = 0; !added && i < cars.size(); i++)
! is the 'logical inverse' (or not) operator. So this statement is actually saying 'stay in the for loop so long as we haven't added and i is less than the size of cars'.
Presumably, at some point cars.get(i).tryToAdd(p) will return true, and the for loop will terminate. Or you run out of cars. Either way the loop runs for at least one iteration (so long as you have at least one car).
You confused it. Actually,
if(!added)
{
//code
}
This condition is equal to:
if(added == false)
{
//code
}
So your logic says, as long as *added* is false, keep iterating, and try to perform' added = cars.get(i).tryToAdd(p); ,setting value of added to 'true'`
! is inverse of boolean.
You are executing a loop to say that unless a person is added (tryToAdd(p) which returns true) execute the loop. And also i < cars.size() says cars should have seat to add person.
Added explanation in your code.
public void loadPassengers() {
boolean added; //Declaring added variable outside for loop for memory management
for (Person p : people) { //Execute loop for each person
added = false; //setting added value to false for each person
// unless person is added execute the loop and also check for the car size.
for (int i = 0; (added == false && i < cars.size()); i++) { // added == false or !added is same
added = cars.get(i).tryToAdd(p); // tryToAdd(p) return true to confirm that a person is added
}
}
}
Related
method code here:
public boolean addItem(MediaItem item)
{
for (int count = 0; count < Library.size(); count++){
String callNum = Library.get(count).getCallNumber();
if(item.getCallNumber().compareToIgnoreCase(callNum) == 0)
{
while( item.getCopyNumber() < Library.get(count).getCopyNumber())
{
int copyNum = item.getCopyNumber();
copyNum++;
item.setCopyNumber(copyNum);
}
Library.add(item);
return true;
} else if (item.getCallNumber().compareToIgnoreCase(callNum) != 0)
{
item.setCopyNumber(1);
Library.add(item);
return true;
}
}
return false;
}
testCases:
public void testAddItem(){
AnytownLibrary newlib = new AnytownLibrary();
assertNotNull(newlib);
MediaItem newItem = new Book();
MediaItem nextItem = new Book();
assertNotNull(nextItem);
assertNotNull(newItem);
newItem.setCallNumber("1");
nextItem.setCallNumber("1");
newlib.addItem(newItem);
assertTrue(newlib.addItem(newItem));
newlib.addItem(nextItem);
assertTrue(newlib.addItem(nextItem));
}
I cannot figure out why this is failing it keep throwing a assertion error here, and its not telling me that its just the output is false so im unsure whats wrong
i have completely tested my get and set methods and they are correct;
and a version of this that just asserts that the (itemname) rather than call numbers return true passed previously, so I'm sure the answer is somewhere in the method itself
Your logic for adding an item to library is wrong. Adding the very first item will always fail, because the for loop with not execute as the size is zero. So nothing will happen. Since this fails all the subsequent addItem calls will also fail.
There are many what to do this, a simple way will be to check if size is zero and add to the list directly and return. Else use ur for loop.
I'm currently programming on a little project (which is way to specific to explain here) and I got everything working except one part. I've got a List pZiegel by parameter which is modified in recursion. Because it didn't work, I did a little debugging and found the problem: At one point, the list contains exactly one number at the end of the method. Then, the program jumps one recursion depth back. And directly after that, it doesn't contains any numbers anymore. How did it lose the number? Lists as parameters work with pass-by-reference, so it shouldn't just reject it, right?
public void erstelleBaum (Tree pTree, List<Integer> pZiegel, List<Integer> pFugen, int tiefe) {
if (tiefe / n >= maxHoehe) {
System.out.println("hi");
mauerGefunden = true;
alleFugen = pFugen;
}
if (!mauerGefunden) {
pZiegel.toFirst();
while (pZiegel.hasAccess() && !mauerGefunden) {
boolean ziegelHinzufügen = false;
möglich = true;
aktZiegel = pZiegel.getContent();
// ...
if (möglich) {
// ...
pZiegel.remove();
if (pZiegel.isEmpty()) {
ziegelHinzufügen = true;
pZiegel = new List();
for (int i = 1; i <= n; i++) {
pZiegel.append(i);
}
}
// Recursion
erstelleBaum(neuesBlatt, pZiegel, neueFugen, neueTiefe);
// Here, it tells me that pZiegel is empty (at recursion depth 17)
if (ziegelHinzufügen) {
pZiegel.toFirst();
while (pZiegel.hasAccess()) {
pZiegel.remove();
}
pZiegel.append(aktZiegel);
}
else {
pZiegel.toFirst();
while (pZiegel.hasAccess() && pZiegel.getContent() < aktZiegel) {
pZiegel.next();
}
if (pZiegel.hasAccess()) {
pZiegel.insert(aktZiegel);
pZiegel.toFirst();
while (pZiegel.getContent() != aktZiegel) {
pZiegel.next();
}
}
else {
pZiegel.toLast();
pZiegel.append(aktZiegel);
pZiegel.toLast();
}
}
}
pZiegel.next();
}
}
// Here, pZiegel contained one number (at recursion depth 18)
}
I hope, the code isn't too messy. I tried to keep out the parts that doesn't involve pZiegel. And sorry, that the variables are named in german. I didn't want to change them for this post because I know I would forget to change something in the code.
Feel free to ask, if something is unclear.
I believe the pZiegel List reference is being lost at some point. You should check the pZiegel object ID (a number displayed when you inspect the object) to make sure it is the same List instance all over the recursions.
Notice that there's one part of your code that makes the pZiegel identifier reference a new List:
...
if (pZiegel.isEmpty()) {
ziegelHinzufügen = true;
pZiegel = new List(); // <---- this line
for (int i = 1; i <= n; i++) {
pZiegel.append(i);
}
}
...
I believe you are calling the 18th recursion with pZiegel referencing one list (maybe empty). Inside the 18th recursion that line is called and pZiegel starts referencing a new List (realize that the last List still exists and is referenceed by the pZiegiel identifier of the 17th recursion). On the last line of the 18th recursion call you believe you are inspecting the same pZiegiel List from the 17th recursion, but that's not the case.
I am working on a school assignment. The objective is to practice GUI's, clone() methods, and using/ modifying existing code. I am trying to write an equals method in the way the instructor desires-- by using a clone of the object, removing items from the bag (returns boolean based on success or failure to remove).
The bag is represented in an array, and should return true in cases such as {1,2,3} and {3,2,1}, ie order does not matter, only the number of each number present in the arrays.
Here is the issue
It works in most cases, however there is a bug in cases where the bags contain numbers as such: {1,1,2} and {1,2,2} and other similar iterations. It is returning true instead of false.
I believe it has something to do with the remove() method we are supposed to use. If i understand it correctly, it is supposed to put the value at the 'end' of the array and decrease the manyItems counter (this is a variable for number of items in the array, because array.length is by default in the constructor 10.)
The code is largely written by another person. We had to import the existing files and write new methods to complete the task we were given. I have all the GUI part done so i will not include that class, only the used methods in the IntArrayBag class.
A second pair of eyes would be helpful. Thanks.
public class IntArrayBag implements Cloneable
{
// Invariant of the IntArrayBag class:
// 1. The number of elements in the bag is in the instance variable
// manyItems, which is no more than data.length.
// 2. For an empty bag, we do not care what is stored in any of data;
// for a non-empty bag, the elements in the bag are stored in data[0]
// through data[manyItems-1], and we don�t care what�s in the
// rest of data.
private int[ ] data;
private int manyItems;
public IntArrayBag( )
{
final int INITIAL_CAPACITY = 10;
manyItems = 0;
data = new int[INITIAL_CAPACITY];
}
public IntArrayBag clone( )
{ // Clone an IntArrayBag object.
IntArrayBag answer;
try
{
answer = (IntArrayBag) super.clone( );
}
catch (CloneNotSupportedException e)
{ // This exception should not occur. But if it does, it would probably
// indicate a programming error that made super.clone unavailable.
// The most common error would be forgetting the "Implements Cloneable"
// clause at the start of this class.
throw new RuntimeException
("This class does not implement Cloneable");
}
answer.data = data.clone( );
return answer;
}
public int size( )
{
return manyItems;
}
public boolean remove(int target)
{
int index; // The location of target in the data array.
// First, set index to the location of target in the data array,
// which could be as small as 0 or as large as manyItems-1; If target
// is not in the array, then index will be set equal to manyItems;
for (index = 0; (index < manyItems) && (target != data[index]); index++)
// No work is needed in the body of this for-loop.
;
if (index == manyItems)
// The target was not found, so nothing is removed.
return false;
else
{ // The target was found at data[index].
// So reduce manyItems by 1 and copy the last element onto data[index].
manyItems--;
data[index] = data[manyItems];
return true;
}
}
//I added extra variables that are not needed to try to increase readability,
//as well as when i was trying to debug the code originally
public boolean equals(Object obj){
if (obj instanceof IntArrayBag){
IntArrayBag canidate = (IntArrayBag) obj; // i know this can be changed, this was required
IntArrayBag canidateTest = (IntArrayBag) canidate.clone(); //this was created
//as a clone because it was otherwise referring to the same memory address
//this caused items to be removed from bags when testing for equality
IntArrayBag test = (IntArrayBag) this.clone();
//fast check to see if the two objects have the same number of items,
//if they dont will return false and skip the item by item checking
if (test.size() != canidateTest.size())
return false;
//the loop will go through every element in the test bag it will
//then remove the value that is present at the first index of the test bag
for (int i = 0; (i < (test.size()) || i < (canidateTest.size())); i++){
int check = test.data[i];
//remove() returns a boolean so if the value is not present in each bag
//then the conditional will be met and the method will return false
boolean test1 = test.remove(check);
boolean test2 = canidateTest.remove(check);
if (test1 != test2)
return false;
}//end for loop
// if the loop goes through every element
//and finds every value was true it will return true
return true;
}//end if
else
return false;
}//end equals
}
I cannot see the big picture, as I havent coded GUIs in Java before, however, as far as comparing 2 int[] arrays, I would sort the arrays before the comparison. This will allow you to eliminate problem cases like the one you stated ( if sorting is possible), then apply something like:
while(array_1[index]==array_2[index] && index<array_1.length)
{index++;}
and find where did the loop break by checking the final value of index
Is it explicitly stated to use clone? You can achieve it easily by overriding the hashCode() for this Object.
You can override the hashCode() for this object as follows:
#Override
public int hashCode() {
final int prime = 5;
int result = 1;
/* Sort Array */
Arrays.sort(this.data);
/* Calculate Hash */
for(int d : this.data) {
result = prime * result + d;
}
/* Return Result */
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || this.getClass() != obj.getClass()){
return false;
}
return false;
}
If you want to continue using your implementation for equals to compare test and CandidateTest then also you can compute unique hashes and make decision based on the results.
Here is the code snippet:
/* Assuming that you have put size comparison logic on top
and the two objects are of same size */
final int prime = 31;
int testResult = 1;
int candidateTestResult = 1;
for(int i = 0; i < test.size(); i++) {
testResult = prime * testResult + test.data[i];
candidateTestResult = prime * candidateTestResult + candidateTest.data[i];
}
/* Return Result */
return testResult == candidateTestResult;
I believe the problem is in this line:
for (int i = 0; (i < (test.size()) || i < (canidateTest.size())); i++){
The problem here is that test and canidateTest are the clones that you made, and you are removing elements from those bags. And any time you remove an element from the bag, the size will decrease (because you decrease manyItems, and size() returns manyItems). This means you're only going to go through half the array. Suppose the original size is 4. Then, the first time through the loop, i==0 and test.size()==4; the second time, i==0 and test.size()==3; the third time, i==2 and test.size()==2, and you exit the loop. So you don't look at all 4 elements--you only look at 2.
You'll need to decide: do you want to go through the elements of the original array, or the elements of the clone? If you go through the elements of the clone, you actually never need to increment i. You can always look at test.data[0], since once you look at it, you remove it, so you know test.data[0] will be replaced with something else. In fact, you don't need i at all. Just loop until the bag size is 0, or until you determine that the bags aren't equal. On the other hand, if you go through the elements of this.data (i.e. look at this.data[i] or just data[i]), then make sure i goes all the way up to this.size().
(One more small point: the correct spelling is "candidate".)
Maybe you should try SET interface
view this in detail :http://www.tutorialspoint.com/java/java_set_interface.htm
A set object cannot contains duplicate elements, so it's suitable for your assignment than build your own class.
For example:[1,1,2] and [1,2,2]
you can use this to test whether they are equal
arr1 = {1,1,2}
arr2 = {1,2,2}
Set<Integer> set = new HashSet<Integer>();
for(int i : arr1){//build set of arr1
if(set.contains(i)==false){
set.add(i)
}
}
for(int i:arr2){
if(set.contains(i)==false){
System.out.println('not equal');
break;
}
}
Hope this is helpful.
I have an issue where I am trying to compare an object's name (String) to another String, and I've tried using .equals() as well as == but neither seem to work in my case.
The code I have right now is:
public boolean checkingObjectName(String checkName)
{
for (int i=0; i<count; i++) //where 'count' has a value of 3
{
if (product[i].getName().equals(checkName)) //where product[i] has been initialised
{
return true;
}
else
{
return false;
}
}
}
The program always returns false, even if the name that has been set to product[i] is the same as the parameter given. I've tried looking at other questions relating to .equals() and == and other String references but I have not had any luck in finding something that relates to my problem.
I have seen people use compareTo(), but I'm not sure if that is necessary in my code, and I'm not completely sure on how to use it.
EDIT: As said by Houssni in the comments, I have just realised that the return statement ends the loop and method. Is it possible to check each product's name without having the method terminated after the first check, and have it return a boolean value?
EDIT 2: I have modified the code to how the answers that have been provided say, which is:
public boolean checkingObjectName(String checkName)
{
for (int i=0; i<count; i++) //where 'count' has a value of 3
{
if (product[i].getName().equals(checkName)) //where product[i] has been initialised
{
return true;
}
}
return false;
}
I still get the same issue with the product[i].getName() not being equal to checkName and the method returning false, even though they should equal. Any possibilities on why this is happening, because I've looked through my code and I'm not sure.
Edit 3: The only other code that relates to the block of code above is the input of the parameter from another class, which is:
String checkName = JOptionPane.showInputDialog("Enter the name: ");
while (storingProducts.checkingObjectName(checkName) == false) //assume for storingProducts
{
JOptionPane.showMessageDialog(null, "No products were found. Please re-input name.");
checkName = JOptionPane.showInputDialog("Enter the name: ");
storingProducts.checkingObjectName(checkName);
}
if (storingProducts.checkingObjectName(checkName) == true)
//extra code
So, that's all the code relating to my issue. I'm still not sure why the method returns false, though both values are receiving the same String value.
Edit 4: The product and count are coming from the class with the checkingObjectName method:
public class Store
{
private Product[] product; //Product is another class that just sets and gets
private int count=3;
public Store()
{
product = new Product[count];
for (int i=0; i<count; i++)
{
product[i] = new Product();
}
//extra code
SOLUTION
I fixed the issue: instead of using .equals(), I tried using .equalsIgnoreCase() and it worked.
The method is returning as soon as it hits count 0 and it doesn't find a match. If you want to loop through your array until you find a matching name, your code should look like this:
public boolean checkingObjectName(String checkName)
{
for (int i=0; i<count; i++) //where 'count' has a value of 3
{
if (product[i].getName().equals(checkName)) //where product[i] has been initialised
{
return true;
}
}
return false;
}
There are two ways to compare strings:
The first is to compare via addresses of the string. Such as: string blue = string red.
The second way to compare strings is through values. This can be done by using the string.equals("StringValue").
Since you have a return statement that will be reached on every posible situation (if condition is true or false), the method will always exit on the first iteration.
What can you do? If you want to return true if the name exists in the array and false otherwise, you can do:
public boolean checkingObjectName(String checkName)
{
for (int i=0; i<count; i++) //where 'count' has a value of 3
{
if (product[i].getName().equals(checkName))
return true;
}
return false; // if after all elements has been checked
// and none was equal to 'checkName', return 'false'
}
How about collecting the names into a List (or Set) and check if checkName matches?
public boolean checkObjectName(final String checkName) {
List<String> productNames = new ArrayList<String>();
for (Product prod : product) {
productNames.add(prod.getName());
}
return productNames.contains(checkName);
}
Note that this will only work if you're comparing case-sensitive strings. Alternatively,
public boolean checkObjectName(final String checkName) {
List<String> productNames = new ArrayList<String>();
for (Product prod : product) {
productNames.add(prod.getName().toLowerCase());
}
return productNames.contains(checkName.toLowerCase());
}
If you do not like this approach, you can use the ones given already, and replace equals with equalsIgnoreCase.
I have the following code
public void makeBaby() {
String duplicate;
boolean full = false;
boolean same = false;
for (int i = 0; i < park.length; i++) {
if (park[i] == null) {
full = false;
} else if (i == park.length - 1 && park[i] != null) {
full = true;
}
if (i != park.length - 1) {
for (int j = 1; j < park.length; j++) {
if (park[i].name.equals(park[j].name)) {
same = true;
duplicate = park[i].name;
}
}
}
if (!full) {
System.out.println("The zoo is full. Cannot make any more babies");
} else if (!same) {
Animal duplicate = new Animal((float) 0.1 * park[i].mass,park[i].name, park[i].legs);
addAnimal(duplicate);
}
}
}
As may be able to see in the code, I have to see if the array called park is full and if not, I need to make a baby animal. but before that, I also need to check if there are 2 animals that have the same type(name).
But I am experiencing problems with the line
Animal duplicate = new Animal((float) 0.1 * park[i].mass,park[i].name, park[i].legs);
addAnimal(duplicate);
because the somehow java does not recognize the duplicate as the duplicate I set in the if statement above.
It is simply creating an animal called duplicate which is not what I want to do..
There are some other things that don't add up. For example:
full is declared as false. In the first if-statement:
if (park[i] == null) {
full = false;
which is already known.
If i am not mistaken:
(!full)
is read as false and is meant to be executed when full = true.
(full)
same goes for (!same)
I am no coding genius, so correct me if i'm wrong. :)
You have two variables each named duplicate, I suspect that this is confusing you.
You have variable
String duplicate;
and you have
Animal duplicate
What is your intention? they are different types.
I suspect you mean:
Animal theNewBaby ...
addAnimal(theNewBaby);
And somewhere you intend the name of the new baby to be the String you stored in duplicate. As we can't see your Animal() constructor we don't know.
You have multiple problems here... For one you have two duplicate variables... one String and one Animal. So depending on which parameter your addAnimal() method takes you might be grabbing the wrong duplicate.
Secondly, I don't believe your "Same" code check is going to work as you are looping through the same list twice. Unless you exclude the first found animal from your second j loop you are always going to find a match even when there is only one animal.
That might work for amoebas but not for elephants! :-)
You only have to rename your variable duplicate(for example sDuplicate with the type as prefix), there is no other way if you want to give addAnimal() the string duplicate you set in the if statement. And add to the if condition:
&& i!=j
then your duplicate check will work.