java for loop does not update variable - java

public CarDealerShip() {
cars = new Car[80];
listSize=0;
}
public void addNewCar (String model, int year, int price, String color) {
m = model;
y = year;
p = price;
c = color;
cars [listSize] = new NewCar (m,y,p,c);
listSize++;
}
public void addUsedCar (String model, int year, int price, boolean rusty) {
m = model;
y = year;
p = price;
r = rusty;
cars [listSize] = new UsedCar(m,y,p,r);
listSize++;
}
public String printReport() {
String list="";
if (cars.length==listSize)
for (int i =0; i <= listSize; i++)
list+=cars[i].toString()+"\n";
return list;
}
In the method printReport, the for loop is suppose to update the variable list but does nothing at all. It been a while since i use Java again so any help is appreciated.

Since 0 <= 0, the for loop will iterate once even if listSize==0 (even if cars[0] is not defined).
So if printReport "does nothing at all" (including throwing an exception), the most likely cause is that the expression in the if statement evaluates to false.
This might happen if you haven't added 80 cars to cars when you try calling printReport.

When you create an object of the class CarDealerShip, the variable listSize gets a value of 0 while the 'cars' array is 80 elements long.
So basically this IF fails:
if (cars.length==listSize).
Hence, the for loop is never entered.
This is all that can be said from the code you provided.

Remove this line :
if (cars.length==listSize)
Because cars is a array whose length is 80 and the variable listSize gets a value of 0 at the time of creating this class . So for loop is not executed .

Related

Return how many objects in an arraylist whose model year is between these two ints (parameters)...? java

My programming prof is obsessed with Lamborghini's so we always do assignments related to them in some way...
Instance variables from LamborghiniCarLot class...
getModelYear() //returns the year
private ArrayList <Lamborghini> inventory; //an arraylist made up of Lamborghini(another class) objects
Method coding:
public int howManyBetweenTheseYears(int startYear, int endYear)
{
//returns the number of lamborghinis in the inventory whose model year is between these numbers, inclusive
}
Let me know if you need anything else..
EDIT1: I've tried this:
public int howManyBetweenTheseYears(int startYear, int endYear)
{
Iterator<Lamborghini> i = inventory.iterator();
int n = 0;
while(i.hasNext()){
Lamborghini lambo = i.next();
if((lambo.getModelYear() >= startYear) && (lambo.getModelYear() <= endYear)){
n++;
}
}
System.out.println(n);
return n;
}
It compiles with the rest of my assignment but it doesn't work with the testing class, which was expected. In the testing class, I get the NullPointerException error.
EDIT2: I've gotten rid of the NPE error and my testing class compiles, but I don't get the correct return value with this coding:
public int howManyBetweenTheseYears(int startYear, int endYear)
{
int n = 0;
for(Lamborghini l : inventory){
while((l.getModelYear()>=startYear) && (l.getModelYear()<= endYear)){
n++;
}
}
return n;
}
When startYear is 2010 and endYear is 2012, the int returned should be 3 buts its 0. Tested with other years and the result is always 0.
When you say
private ArrayList<Lamborghini> inventory;
it defaults to null. So it's the same as,
private ArrayList<Lamborghini> inventory = null;
and so you get a NPE when you try iterate it. Also, you should use the interface type. So, change it to something like
private List<Lamborghini> inventory = new ArrayList<>();
But, you'll still need to add Lamborghini(s) to your inventory.

How to decide the state of an object before starting to code?

I have the following code for displaying the sum of two consecutive element of ArrayList until the element left is one.for example:-
if i entered
1 2 3 4 5
output
3 7 5 //adding the two consecutive last one is as it is
10 5//doing the same thing
15
code
import java.util.*;
import java.lang.Integer;
class Substan{
ArrayList <Integer> list = new ArrayList <Integer> ();
ArrayList <Integer> newList = new ArrayList <Integer> ();// this will be the list containing the next sequence.
int index=0;
int sum=0;
Substan(){
Scanner read = new Scanner(System.in);
String choice;
System.out.println("Enter the elements of the array");
do{
int element = read.nextInt();
list.add(element);
System.out.println("More?");
choice = read.next();
}while(choice.equals("y") || choice.equals("Y"));
}
/* precondition- we have the raw list that user has enterd.
postcondition - we have displayed all the sublists,by adding two consecutives numbers and the last one is having one element.
*/
void sublist(){
while(noofElementsIsNotOneInList()){
index =0;
while(newListIsNotComplete()){
if(nextElementIsThere()){
sum = addTheConsecutive();
}
else{
sum = getLastNumber();
}
storeSumInNewList();
}
displayTheNewList();
System.out.println("");
updateTheLists();
}
displayTheNewList(); //as we have danger of Off By One Bug (OBOB)
System.out.println("");
}
private boolean noofElementsIsNotOneInList(){
boolean isnotone = true;
int size = list.size();
if ( size == 1){
isnotone = false;
}
return isnotone;
}
private boolean newListIsNotComplete(){
boolean isNotComplete = true;
int listSize = list.size();
int newListSize = newList.size();
if (listSizeIsEven()){
if ( newListSize == listSize/2){
isNotComplete = false;
}
}
else{
if( newListSize == (listSize/2) +1){
isNotComplete = false;
}
}
return isNotComplete;
}
private boolean listSizeIsEven(){
if ( list.size()%2 == 0 ){
return true;
}
else{
return false;
}
}
/*
we are at some index.
returns true if we have an element at (index+1) index.
*/
private boolean nextElementIsThere(){
if ( list.size() == index+1 ){
return false;
}
else{
return true;
}
}
/* precondition-we are at index i
postcondition - we will be at index i+2 and we return sum of elements at index i and i+1.
*/
private int addTheConsecutive(){
int sum = list.get(index)+list.get(index+1);
index += 2;
return sum;
}
/* we are at last element and we have to return that element.
*/
private int getLastNumber(){
return list.get(index);
}
private void storeSumInNewList(){
newList.add(sum);
}
private void displayTheNewList(){
int size = newList.size();
for ( int i=0;i<size;i++){
System.out.print(newList.get(i)+" ");
}
}
/*precondition - we have processed all the elements in the list and added the result in newList.
postcondition - Now my list will be the newList,as we are processing in terms of list and newList reference will have a new object.
*/
private void updateTheLists(){
list = newList;
newList = new ArrayList <Integer>();// changing the newList
}
public static void main(String[] args) {
Substan s = new Substan();
s.sublist();
}
}
So i have done a lot of refinement of my code but having a problem of sharing the local variables with the other methods.for example i have used index instance for storing the index and initially i thought that i will put this as not an instance but a local variable in method sublist() but as it cannot be viewed from other methods which needed to use the index like addTheConsecutive().So considering that i put the index at class level.So is it wright approach that put the variables that are shared at class level rather than looking at only the state of the object initially before coding and stick to that and never change it?
Consider this:
An object can communicate with other(s) only by sharing its attributes. So, if you need an object to read the state of another, the only way it can be done is by giving it "permission" to read the other object attributes.
You have two ways to do that:
Declaring the object attributes public, or
Creating getXXX() methods (makes sense for private attributes)
I personally prefer option two, because the getXXX() method returns the value ("state") of a particular attribute without the risk of being modified. Of course, if you need to modify a private attribute, you should also write a setXXX() method.
Example:
public class MyClass {
private int foo;
private String bar;
/*
* Code
*/
public int getFoo() {
return foo;
}
public String getBar() {
return bar;
}
public void setFoo(int foo) {
this.foo = foo;
}
public void setBar(String bar) {
this.bar = bar;
}
/*
* More code
*/
}
This way all the object attributes are encapsulated, and:
they cannot be read by any other object, unless you specifically call the appropriate getXXX() function, and
cannot be altered by other objects, unless you specifically call the appropriate setXXX() function.
Compare it with the non-abstracted version.
for (int index = 0; index < list.size(); index += 2) {
int sum = list.get(index);
if (index + 1 < list.size() {
sum += list.get(index + 1);
}
newList.add(sum);
}
Now, top-down refining the algorithm using names is a sound methodology, which helps in further creative programming.
As can seen, when abstracting the above again:
while (stillNumbersToProcess()) {
int sum = sumUpto2Numbers();
storeSumInNewList(sum);
}
One may keep many variables like sum as local variables, simplifying state.
One kind of helpful abstraction is the usage of conditions, in a more immediate form:
private boolean listSizeIsEven() {
return list.size() % 2 == 0;
}
private boolean nextElementIsThere() {
return index + 1 < list.size();
}
There's no point in declaring index at Class level since you dont want it to be a member or an instance of that class. Instead make it local to the method and pass it to other methods as argument where you want to access it.
I think you are asking the wrong question.
Your class variables make very little sense, as do many of the methods. This is mostly because:
Your class is doing too much
Your algorithm is a little odd
The class variables that you do have make much more sense passed as method parameters. Some methods need to see them, and some don't.
Your class is also a little odd, in that calling subList twice on the same class will not produce the same answer.
The code is littered with methods I don't quite see the point in, such as:
private boolean noofElementsIsNotOneInList(){
boolean isnotone = true;
int size = list.size();
if ( size == 1){
isnotone = false;
}
return isnotone;
}
Shouldn't this be:
private boolean noofElementsIsNotOneInList(){
return list.size() == 1;
}
And it makes no sense for it to use some arbitrary List, pass one in so that you know which List you are checking:
private boolean noofElementsIsNotOneInList(final Collection<?> toCheck){
return toCheck.size() == 1;
}
The same logic can be applied to almost all of your methods.
This will remove the instance variables and make your code much more readable.
TL;DR: Using lots of short appropriately named methods: good. Having those methods do things that one wouldn't expect: bad. Having lots of redundant code that makes things very hard to read: bad.
In fact, just to prove a point, the whole class (apart from the logic to read from stdin, which shouldn't be there anyway) can transformed into one short, recursive, method that requires no instance variables at all:
public static int sumPairs(final List<Integer> list) {
if (list.size() == 1)
return list.get(0);
final List<Integer> compacted = new LinkedList<>();
final Iterator<Integer> iter = list.iterator();
while (iter.hasNext()) {
final int first = iter.next();
if (iter.hasNext()) compacted.add(first + iter.next());
else compacted.add(first);
}
return sumPairs(compacted);
}
Now you could break this method apart into several appropriately named shorter methods, and that would make sense. It's sometimes more helpful to start from the other end. Sketch out the logic of your code and what it's trying to do, then find meaningful fragments to split it into. Possibly after adding unit tests to verify behaviour.
what about doing by Recursion:
public int calculateSum(List<Integer> nums) {
displayList(nums);
if (nums.size() == 1) {
return nums.get(0);
}
List<Integer> interim = new ArrayList<Integer>();
for (int i = 0; i < nums.size(); i = i + 2) {
if (i + 1 < nums.size()) {
interim.add(nums.get(i) + nums.get(i + 1));
} else {
interim.add(nums.get(i));
}
}
return calculateSum(interim);
}
public static void displayList(List<Integer> nums){
System.out.println(nums);
}
Steps:
Run calculate sum until list has 1 element
if list has more than 1 element:
iterate the list by step +2 and sum the element and put into a new List
again call calculate sum

Why do I keep on getting an ArrayIndexOutofBoundsException?

I am trying to program a program that mimics the actions of a vending machine for my CS class. I have a double array stock that represents the the number of items at a particular "slot" [my vending machine is weird and is kinda like one long vending machine with 1 column of different items]. Here is my code so far:
public class VendingMachine
{
// define fields here
public static double itemPrice[];
public static String[] itemName;
public static int stock[][];
public static int maxPerSlot;
public static double cashAmmount;
public VendingMachine(int numslots, int maxperslot, double cash)
{
final int numSlots = numslots;
maxPerSlot = maxperslot;
cashAmmount = cash;
stock = new int[numSlots][0];
itemPrice = new double[numSlots];
itemName = new String[numSlots];
// complete this method
}
public void setProduct(int slot, String product, double price)
{ int Slot = slot;
itemPrice[slot] = price;
itemName[slot] = product;
stock[Slot][0] = 0;
//
}
public void restockProduct(String product, int quantity)
{
String Product = product;
int currentCapacity = quantity - maxPerSlot;
for(int i = 0; i < stock.length; i++){
if (itemName[i]==Product){
for(;quantity <= maxPerSlot && currentCapacity != 0; quantity--)
stock[i][0] += 1;
}
}
//Put # of products in slot that holds it and if that slot is full put the rest in the next
//availble slot that holds that product, if all full return error.
}
public double getCashOnHand()
{
return cashAmmount; // replace this line with your code
}
public int getQuantity(int slot)
{
return stock[slot][1]; // replace this line with your code
}
public int getQuantity(String product)
{ int total = 0;
for (int i = 0; i<itemName.length;i++){
if (product == itemName[i]){
total += stock[i][1];
}
}
return total;
}
public boolean buyItem(int slot)
{ int snum = slot;
if (stock[snum][1] != 0){
stock[snum][1]--;
return true;
} else {
return false;} // replace this line with your code
}
}
Every time I runException in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0
at VendingMachine.setProduct(VendingMachine.java:27)
at vmd.main(vmd.java:9) this code though I get this error message:
Can someone here please explain to me why I continue to get this error? I mean the logic seems quite correct .
Your problem's here:
stock = new int[numSlots][0];
This defines an array of numSlot arrays with a length of 0 each.
when you initialize stock in the constructor do this instead:
stock = new int[numSlots][1];
using 0 instead of 1 initializes an array of length 0!
You allocate zero elements in the second dimension of stock,
stock = new int[numSlots][0];
so you get that exception when you try to access the element at index zero.
stock[Slot][0] = 0;
This line
stock = new int[numSlots][0]; // <-- A length of zero? You want a one there.
Should be
stock = new int[numSlots][1]; // <-- like so. Or, if you really don't
// want to change your other code make it a 2.
// But you'll leave memory unused, and you really should change it.
Everywhere else (where you have code like this) -
stock[slot][1] // <-- stock[INDEX][1] <--- should be 0.
Like this
stock[slot][0] // <-- all of the other accesses.
Because this line:
stock = new int[numSlots][0];
allocates stock to be an array of arrays, and each of those arrays has length 0. So you can't assign anything into those arrays (they don't have any elements to assign). So when you do this:
stock[Slot][0] = 0;
you will get an ArrayIndexOutOfBounds. Remember that in Java, indexes start at 0, so if you want an array where the indexes go from 0 to N, you have to allocate the array with size N+1.

While and for loops for adding to two dimensional array

I have an arrayList which contains Objects. Each object contains a number of strings. I am trying to take these strings and add them to a two dimensional array.
public void iterateRow(Row row)
{
int x = 0;
int y = size();
tableArray = new String[y][5];
while(x < y){
int z = 0;
for (String s: row.rowString()){
tableArray[x][z] = s;
z++;
}
x++;
}
}
Whenever i run and create a new instance for the row class the method should add the strings contained in Row to the array. However it duplicates the latest entry x times (where x is the total number of entries).
Here is the Row class for further reference:
public class Row
{
public String appNumber;
public String name;
public String date;
public String fileLoc;
public String country;
public String elementString;
public String results[];
public Row(String appNumber, String name, String date, String fileLoc, String country, Table table)
{
this.appNumber = appNumber;
this.name = name;
this.date = date;
this.fileLoc = fileLoc;
this.country = country;
table.addApplicant(this);
}
public String[] rowString()
{
String[] a = {appNumber, name, date, fileLoc, country};
return a;
}}
I think it is a silly logical error in the iterateRow() method but i can't seem to work out what. Any help would be appreciated.
Edit: After everybody's help i have removed the while loop. However it still seems to be duplicating the Row rather than moving onto the next?
public void iterateRow(Row row)
{ int x = 0;
int y = size();
tableArray = new String[y][row.rowString().length];
for(int i =0; i<y;i++){
int z = 0;
for (String s: row.rowString()){
tableArray[x][z] = s;
z++;
}x++;}
}
The problem looks like it is in the while loop. If size() returns 3, for example, then the while loop will execute with x=0,1,2 so you'll assign tableArray[0], then tableArray[1] and then tableArray[2].
Its hard to tell what the solution is as I can't understand why you've got the while loop in the code at all.
It looks like you want to iterate through each element of a List of Rows
Maybe you want to use a method similar to the following:
public void iterateRows(List<Row> rows) {
int cols = 5;
int row = 0, col = 0;
tableArray = new String[rows.size()][cols];
for(Row row : rows) {
col = 0;
for(String c : row.rowString()) {
tableArray[row][col] = c;
col++;
}
row++:
}
}
However, it would be good to implement your own error checking incase there are more than 5 columns...
EDIT
This is probably not the best design to use for your program, and I would recommend changing it so that when a new row is added, you don't have to iterate through each of the old rows as well.
Your iterateRow method re-creates tableArray each time it is called. Because of the while loop, your Row object gets replicated y times in the array.
I suspect that you want to create your array outside of the iterateRow method and not use a while loop (just the for loop) to populate the next slot in your array.
You are not taking care to size the two dimensional array relative to the size of the Row.
While this might not be the smoking gun, it would be far safer to do
tableArray = new String[y][row.rowString().length];
instead of
tableArray = new String[y][5];
I don't know if this is for practical purpose or how IterateRow() is called, but a logical way to get this working would be to declare the array first, add 2 argument in IterateRow(reference of the array and currentRow). Then, inside iterateRow you get rid of the while loop and you just loop for the string proprieties.

Calculate the number of students who passed - what should I put in the if statement?

The idea is to add students to an arraylist, work out the number of students who have passed, and return that number.
I think I'm nearly there, as the code works, but it always returns the same value for the amount in the array list - and obviously, that is incorrect.
I have been doing this for hours now, and I can't see what the missing statement within the if statement is to finish it off! I would be soo grateful for this!
import java.util.ArrayList;
class Course
{
private ArrayList<Student> people = new ArrayList<Student>();
//Add a students mark
public void add( Student s )
{
people.add(s);
}
//Return the number of students who passed (mark>= 40)
public int pass()
{
int size = people.size();
int i = 0;
int result = 0;
for (i = 0; i < size; i++)
{
Student s = people.get(i);
if(s.getMark() >= 40);
{
// what's here?
}
return result;
}
}
}
Remove this statement inside pass method
ArrayList people = new ArrayList();
Because of this statement, when pass method is called, your local variable hides instance variable.
You are declaring a duplicate, empty people list in the pass() method. Remove it.
You create an ArrayList with no elements, and then create result of type Object[] from it, which will be of length 0.
ArrayList people = new ArrayList();
Object result[] = people.toArray();
Thus, your for loop will not be executed at all.
You probably want to access the instance variable people, you can do it by
Removing the ArrayList people = new ArrayList(); from the method
using this in creating the array: Object result[] =
this.people.toArray();
Firstly, you specify ArrayList people twice, once, outside of the pass method, and the second inside of the pass method. The pass method default uses the one inside of it, which is empty.
mark is always 0. So this does not work:
if ( mark >= 40)
You should return the result after you've finished the for loop, and you should be increasing result instead of i:
public int pass()
{
int size = people.size();
int result = 0;
for (int i = 0; i < size; i++)
{
Student s = people.get(i);
if(s.getMark() >= 40);
result++;
}
return result;
}

Categories

Resources