What's wrong with my copy constructor? - java

Beginner in Java. I'm stuck trying to figure out how to write one of the constructors for a java project. I'm going to include most of the code to provide some context. This class is to be accessed by another file which holds the methods for a terminal menu.
// java class for keyboard I/O
import java.util.Scanner;
// declaration of the class
public class NumberList
{
//integer constant that determines the size of the array
public static final int MAX_CAPACITY = 100;
//array to store the numbers
private double [] numbers;
//the number of valid numbers currently in the NumberList
private int length;
//default constructor that initializes array to size MAX_CAPACITY and initializes all
//array values to 0, sets length to 10
public NumberList()
{
numbers = new double[MAX_CAPACITY];
int i;
for(i = 0; i < MAX_CAPACITY; i++)
numbers[i] = 0;
length = 10;
}
//outputs the numbers in the NumberList to the
//standard output screen
public void print()
{
int i;
for(i = 0; i < length-1; i++)
System.out.println(numbers[i]+ ", ");
System.out.println(numbers[i]);
}
//assignment constructor, initializes array to size 100,
//initializes length to l and sets the first l values of the list to the value n
NumberList(int l, double n)
{
numbers = new double[MAX_CAPACITY];
length = l;
int i;
for(i = 0; i < MAX_CAPACITY; i++)
numbers[i] = n;
}
//array constructor, initializes array to size 100, takes an array
//as input and completes a deep copy (element to element copy) from the array
//parameter to the numbers array
NumberList(final double[] a)
{
this.numbers = new double[a.length];
for (int i = 0; i < a.length; ++i)
{
this.numbers[i] = a[i];
}
}
Everything above compiles nicely. Not sure if I'm on the right track or if a "for" loop is necessary.
**//copy constructor, initializes array to size 100,
//creates a copy of parameter NumberList nl to the calling NumberList
NumberList(final NumberList nl)
{
numbers = new double[MAX_CAPACITY];
nl = new NumberList(MAX_CAPACITY);
}**
//returns the length of NumberList
public int length()
{
int length = numbers.length;
return length;
}
//returns the sum of the numbers in the NumberList
public double sum()
{
double sum = 0;
for (int i = 0; i < numbers.length; i++)
{
sum = sum + numbers[i];
}
return sum;
}
Grateful for any tips/ advice I can get.

A copy constructor is just that: A constructor. So you're operating on a new instance freshly created for you. You don't want to create another instance, just set up this.
For instance, in your case, make the numbers of the current instance a copy of the numbers of the source instance, and copy length:
NumberList(final NumberList nl)
{
this.numbers = nl.numbers.clone();
this.length = nl.length;
}
(With thanks to Jorn Vernee and assylias for pointing out Arrays.copyOf and clone, respectively. Went with clone.)

Related

Error : The type of the expression must be an array type but it resolved to int

I have a problem to convert from int to int []. I have tried to modify the coding but still have error. I want to change the method getRandomNumberInRange into int[] because i need to combine with [hostType] and [hostType] is in array form.
// this method is to convert from int to int[]
static Integer[] toObject(int[] intArray) {
Integer[] result = new Integer[intArray.length];
for (int i = 0; i < intArray.length; i++) {
result[i] = Integer.valueOf(intArray[i]);
}
return result;
}
// this method to generate random number
public static int getRandomNumberInRange(int min, int max) {
if (min >= max) {
throw new IllegalArgumentException("max must be greater than min");
}
Random r = new Random();
return r.nextInt((max - min) + 1) + min;
}
//this method is to implement the function getRandomNumberInRange and need to be in array form
public static List<PowerHost> createHostList(int hostsNumber) {
List<PowerHost> hostList = new ArrayList<PowerHost>();
for (int i = 0; i < hostsNumber; i++) {
int hostType = i % Constants.HOST_TYPES;
// int mips2[]=(int) getRandomNumberInRange(100, 1000);
List<Pe> peList = new ArrayList<Pe>();
for (int j = 0; j < Constants.HOST_PES[hostType]; j++) {
int[] obj = new int[hostType] ;
Integer[] newObj = toObject(obj);
peList.add(new Pe(j, new PeProvisionerSimple(getRandomNumberInRange(100, 1000)[newObj])));
}
There are a few things wrong. First, in the last code snippet, you are missing two '}'s. Second, getRandomNumberInRange(int min, int max) returns an int, which is not an array. What that means is that you wouldn't do getRandomNumberInRange(100, 1000)[newObj] because that is like doing 107[4]. 107 isn't an array so that wouldn't work. Also, newObj is an array, so even if getRandomNumberInRange returned an array, newObj wouldn't be able to be used as an index to get the int in the array. This is because the index (the thing that goes in array[here]) must be an int.

java array index out of bounds

I'm building a class that takes an array of numbers and has methods to output their min, max and average values as a string representation of the numbers. Here's my constructor for the class:
public RandomArray(int sizeOfArray)/*Constructor: gets array size and populates array with
random numbers*/
{
Random generator = new Random();
size = sizeOfArray;
for (int i = 0;i < size;i++)
{
numbers[i] = generator.nextInt(size + 1);
}
}
I'm getting the array out of bounds exception message when I test this class with a driver program and this constructor is the one causing it. I'm not able to understand how I'm going beyond the size of the array here. Please help! Thanks.
Edit - So just to clear up any confusion I'm posting the entire class below for reference:
public class RandomArray
{
/*A class that contains an array of random numbers and methods that output
the numbers' minimum, maximum and average values. Also includes a method
that outputs a string representation of the numbers.*/
int size, min, max;
String array;
int[] numbers = new int[size];
public RandomArray(int sizeOfArray)/*Constructor: gets array size and populates array with
random numbers*/
{
Random generator = new Random();
size = sizeOfArray;
for (int i = 0;i < size;i++)
{
numbers[i] = generator.nextInt(size + 1);
}
}
public int min_value()
{
for (int i = 0;i < size - 1;i++)
{
min = numbers[i];
for (int k = 1;k < size; k++)
{
if (numbers[k] < min)
{
min = numbers[k];
}
else
{
min = numbers[i];
}
}
}
return min;
}
public int max_value()
{
for (int i = 0;i < size - 1;i++)
{
max = numbers[i];
for (int k = 1;k < size; k++)
{
if (numbers[k] > max)
{
max = numbers[k];
}
else
{
max = numbers[i];
}
}
}
return max;
}
public double average()
{
double avg;
int sum = 0;
for (int i = 0;i < size;i++)
{
sum = sum + numbers[i];
}
avg = sum/size;
return avg;
}
public String toStringArray()//Outputs a string representation of all the numbers in the array
{
for (int i = 0; i < size;i++)
{
array = Integer.toString(numbers[i]) + " ";
}
return array;
}
}
You are initializing the array before you initialize the size variable. The size variable has a default value which is passed into the array constructor and sets the array to that size. to fix the problem just move the initialization of the array into the constructor after the size variable is set.
public class RandomArray
{
/*A class that contains an array of random numbers and methods that output
the numbers' minimum, maximum and average values. Also includes a method
that outputs a string representation of the numbers.*/
int size, min, max;
String array;
int[] numbers;
public RandomArray(int sizeOfArray) {
Random generator = new Random();
size = sizeOfArray;
numbers = new int[size];
for (int i = 0;i < size;i++)
{
numbers[i] = generator.nextInt(size + 1);
}
}
Also I've noticed a bug with the string output method. The array would be overwritten on each iteration. To solve this you must add the array to itself.
public String toStringArray()//Outputs a string representation of all the numbers in the array
{
for (int i = 0; i < size;i++)
{
array = array + Integer.toString(numbers[i]) + " ";
}
return array;
}
Your method is passed the size of the array, but the array definition is not present in your code.
If you need to create the array in the RandomArray method, do something like :
public int[] RandomArray(int sizeOfArray)/*Constructor: gets array size, create and populates array with random numbers*/
{
int[] randomArray = new int[sizeOfArray];
for (int i = 0;i < randomArray.length();i++)
{
numbers[i] = generator.nextInt(size + 1);
}
return randomArray;
}
As you did not provide the entire class code it is hard to see whats going on. However I think you did not initialize the array correctly. If you have a private variable for an array, you should still 'make space' for it, as follows.
private int[] myIntArray; // As class member
myIntArray = new int[3]; // To allocate memory for the array
See the following link, for more info regarding arrays.
https://docs.oracle.com/javase/tutorial/java/nutsandbolts/arrays.html

Print random array on one line: Java

Working on building an array that can generate random integer values inside an array. It prints the random numbers but it prints it like this
[10][2][5][7][6][2][4][7][2][10][0]--->(down the side)--------> and want it to print like this [10,7,5,9,4,3,4,7,2,3] (one line).
public class ArrayLab
{
//array instance variable
private int[] array1 = new int[10];
//array constructor
public ArrayLab(int integer)
{
//class parameter = 10
int[] array1 = new int[]{integer};
}
public void initialize()
{
//allow randomization of numbers inside the array field.
System.out.println(Arrays.toString(array1));
//prints [0,0,0,0,0,0,0,0,0,0] which is ok
System.out.println();
for (int iteration = 0; iteration < array1.length; iteration ++)
{
Random number = new Random();
number.nextInt(10);
int n = number.nextInt(11);
int[] array1 = new int[]{n};
System.out.println(Arrays.toString(array1));
//prints down the side. Want on one line?
}
}
}
Just change
System.out.println(Arrays.toString(array1));
//new output
System.out.print(Arrays.toString(array1));
another way you can get this done is by using a for loop to iterate through the array in similar fashion
for( int i = 0; i < array1.length; i++ ){
System.out.print(array1[i]+" ");
}
for the random numbers
Random ran = new Random();
for( int i = 0; i < array1.length; i++ ){
int number = ran.nextInt((max - min) + 1) + min;
//insert the maximum and min values for your generator
array1[i] = number;

Calling a void Method into a constructor

I have a problem that goes like this. A user inputs 5 grades into an array.
The array must then be sorted from highest to lowest and then averaged.
the methods for the selectionSort and calculateMean must be void.
How do i call them into my constructor? then i need to print the data out to a toString.
This is what i have so far.
import java.util.Scanner;
public class Average {
//the array which will contain the scores
private int data[];
//the average of the scores
private double mean;
public Average(){
Scanner sc = new Scanner(System.in);
double data[] = new double[6];
for(int i = 1; i < data.length; i++){
System.out.println("Enter score number " + i);
data[i] = sc.nextDouble();
}
/*for(int p = 1; p < data.length; p ++){
System.out.println(data[p]);
}*/
//selectionSort();
}
public void calculateMean(){
double total = 0;
double sum = 0;
double average = 0;
for(int counter = 0; counter < data.length; counter++){
sum = sum + data[counter];
average = sum / data.length;
}
}
public void selectionSort(){
int temp = 0;
for(int joey = 0; joey<data.length; joey++){
for(int i = 1; i < data.length; i++) {
if(data[i - 1] > data[i]) {
temp = data[i-1];
data[i-1] = data[i];
data[i] = temp;
}
}
}
for(int p = 0; p < data.length; p++){
System.out.println(data[p]);
}
}
public String toString(){
return null;
}
}
You can call the 2 methods in your constructor like this
// Inside constructor
selectionSort(); // call the method
calculateMean(); // call the method
System.out.println(toString()); // print the data using toString
And your toString() can look like this
public String toString() {
return Arrays.toString(data);
}
Also, the logic in your calculateMean() is a bit wrong.
for (int counter = 0; counter < data.length; counter++) {
sum = sum + data[counter];
}
average = sum / data.length; // Calculate the average after finding the sum and not at every iteration.
Moreover, I see that the mean instance variable is not. You might want to assign the average calculated in the calculateMean() method to it, and you might want to print it some method or the toString() itself, depending in your needs.
Edit:
You're shadowing your instance variable int data[]; with the local variable in the constructor, double data[] = new double[6]; and that is the reason you're getting the NPE. Remove the local variable from the constructor and instead initialize it like this
data[] = new int[5];
And the following for loop to get the input from the user to start from the index 0 and not 1.
for(int i = 0; i < data.length; i++){

ArrayIndexOutOfBoundsException for my PrintList function and I have no idea why

I am writing a really simple program which automatically extends the array when the user reaches the limit of the current array.
The problem is that I am getting a java.lang.ArrayIndexOutOfBoundsException when I run my PrintList method and I really don't know why. It's working perfectly if I use a random number, which is bigger than the array (e.g. 500), but if I use
for (int i = 0; i < stringArray.length; i++)
or
for (int i = 0; i <= stringArray.length; i++)
I get a nasty exception. How do I deal with this and why am I getting it in the first place?
Thanks a lot for your help!
Here's the source code of my program:
public static void main(String[] args) {
Scanner keyboard = new Scanner(System.in);
int index = 0;
String[] randomString = new String[1];
while (index <= randomString.length) {
out.println("Enter your string");
String input = keyboard.next();
randomString[index] = input;
PrintArray(randomString);
index++;
if (index >= randomString.length) {
ExtendArray(randomString);
continue;
}
}
}
public static void ExtendArray(String[] stringArray) {
String[] secondArray = new String[stringArray.length * 2];
// Copy first array into second array
for (int i = 0; i < stringArray.length; i++) {
stringArray[i] = secondArray[i];
stringArray = secondArray;
}
}
public static void PrintArray(String[] stringArray) {
for (int i = 0; i < stringArray.length; i++) {
out.println(" " + stringArray[i]);
}
}
Java does not work in the methods you are trying to employ. Everything in Java is passed by value, unless it is a data point in an object. What you are trying to employ is a pass by reference, which is not possible in Java.
What you are trying to do is an already existing data structure called a Vector: http://docs.oracle.com/javase/7/docs/api/java/util/Vector.html
I would suggest doing this: (not sure if it will work properly, as my current PC doesn't have dev tools):
public static String[] ExtendArray(String[] stringArray) {
String[] secondArray = new String[stringArray.length * 2];
// Copy first array into second array
for (int i = 0; i < stringArray.length; i++) {
secondArray[i] = stringArray[i];
}
return secondArray;
}
then calling it like so in main:
randomString = ExtendArray(randomString);
Relating to vectors, this is how it works in a Vector class:
public void incrementCount(int count){
int increment = (count * 2);
Object newElementData [] = new Object[increment];
for(int i = 0; i < count; i++)
{
newElementData[i] = elementData[i];
}
elementData = new Object[increment];
elementData = newElementData;
}
In this case, elementData is the original array, newElementData is a temp array that acts to up the bounds.
You cant get error on your PrintArray method, you get the error on the line before!
randomString[index] = input;
Because if you do this
index <= randomString.length
The last iteration is out of bounds, String of length 10 has values on 0-9. You have to change the while cycle to
index < randomString.length
Also your ExtendArray method is NOT functional!
You are supposed to swap out the randomString array for a new array with double length. You create a new array and copy the contents of the old one to the new one, but don't do anything with the new array.
I suppose you want the ExtendArray method to return the new array, and set the randomString variable to be the new array.
You need to return your second array from ExtendArray function:
public static String[] ExtendArray(String[] stringArray) {
String[] secondArray = new String[stringArray.length * 2];
// Copy first array into second array
for (int i = 0; i <= stringArray.length; i++) {
stringArray[i] = secondArray[i];
}
return secondArray;
}
and in your main:
randomString = ExtendArray(randomString);
also your while condition should be:
while (index < randomString.length)

Categories