I have a class holding a boolean, and two doubles, and then an array of that class, I need the boolean and doubles to have defaults values of false, 0.0, and 0.0, and then I have function that refers to an element of the array and the moment I try to access an one of the variables from the class it throws an exception saying its null. Here is my class and my function calling it.
public class PanelData {
boolean flag = false;
double tempStart = 0.0;
double tempEnd = 0.0;
}
private PanelData[] panelInfo = new PanelData[115];
private void panelInfoHandler (int i, double timeStart, double timeEnd) throws SQLException
{
if (!panelInfo[i].flag) {
delete();
insert();
panelInfo[i].flag = true;
panelInfo[i].tempStart = timeStart;
panelInfo[i].tempEnd = timeEnd;
}
else if (panelInfo[i].tempStart <= timeStart && panelInfo[i].tempEnd >= timeEnd) {
}
else
{
insert();
panelInfo[i].tempStart = timeStart;
panelInfo[i].tempEnd = timeEnd;
}
}
here is how I call the class.
panelInfoHandler(9, parsedStart, parsedEnd);
new PanelData[115] creates an array of 115 null references. Have you populated panelInfo with references to actual objects?
At a minimum, you then need to loop through that array and create new instances of PanelData for each element in the array, e.g.
for (int i = 0; i < panelInfo.length; i++)
panelInfo[i] = new PanelData();
Your array is full of null elements until you initialize it. To clarify, if you create an array of primitive objects, you get an array of default (i.e. 0) values. However, an array of Objects gets created with null elements.
int[] myIntArray = new int[10]; // 10 default values of 0
Integer[] myIntegerArray = new Integer[10]; // 10 null elements
add this line and then assign the values:
if(panelInfo[i] == null) panelInfo[i] = new PanelInfo();
You need to do something like
for(int i=0;i<115; i++)
{
PanelInfo[i] = new PanelData();
}
(Or whatever is the correct Java Syntax)
public class PanelData {
boolean flag = false;
double tempStart;
double tempEnd;
public PanelData() {
flag = false;
tempStart = 0.0;
tempEnd = 0.0;
}
private PanelData[] panelInfo = new PanelData[115];
for(int i = 0; i < 115; i++)
panelInfo[i] = new PanelData();
Creating the default constructor lets you instantiate the variables with the default values (false, 0.0, 0.0) in this case so you can test if you are getting a vanilla object back or not.
Related
Note: This is a troubling problem, possibly a bug, although I might be incorrect and missing something small
Problem:
Issue is the separately instantiated objects are referring to the same data structure.
Calling a.add() adds an object to data[NEXT], where is instantiated to NEXT = 0, followed by NEXT++ for increment purposes.
Thereafter, b.add() is called, and following the logic of the add() method, the array is extended,
BUT no initial value has been inserted into b i.e. b.data[0] = null
TL;DR
a.add() adds value to a.
b.add() extends a's array. This should not happen as a and b are 2 separate objects of the same type
main class code:
//...
SimpleSet<Integer> a = new SimpleSet<>();
SimpleSet<Integer> b = new SimpleSet<>();
// add a maximum of 20 unique random numbers from 0..99
Random rand = new Random();
for (int i = 0; i < 20; i++) {
a.add(rand.nextInt(100)); //i=0 - adds to data[0] with no issue
b.add(rand.nextInt(100)); //i=0 - extends a's array? why?
}
//...
class SimpleSet
public class SimpleSet<E> {
private static int MIN_SIZE = 1;
private static int NEXT = 0;
private Object[] data;
/**
* constructor of SimpleSet
*/
public SimpleSet() {
data = new Object[MIN_SIZE];
}
public void add(E e) {
if(NEXT > 0.75*MIN_SIZE){
extendArray();
}
if (data != null) {
data[NEXT] = e;
NEXT++;
}
}
private void extendArray() {
MIN_SIZE = MIN_SIZE*2;
Object[] newData = new Object[MIN_SIZE];
for (int i = 0; i < data.length; i++) {
newData[i] = data[i];
}
data = newData;
return;
}
//...
}
Am I missing something small or is this a bug?
IDE = IntelliJ 2016.3
When I try to reset a list Marked I get a Null Pointer Exception.
The problem must be cause I never said what B and C is. (Boolean B, Integer C) And I don't know how to do this.
Here is a part of my code :
Marked[] marked;
//Create list marked!
public class Marked<B,C>{
public B bool;
public C comp;
}
public Graph(int N)
{
//Fill marked with false and 0
marked = new Marked[N];
for(int i=0;i<N;i++){
marked[i].bool = false;
marked[i].comp=0;
}
Creating an array of Marked doesn't actually initialize the elements in the array:
marked = new Marked[N];
for(int i = 0; i < N; i++) {
marked[i] = new Marked<Boolean, Integer>();
marked[i].bool = false;
marked[i].comp = 0;
}
The statement marked = new Marked[N]; creates a new array of Marked objects with N elements, but does not initialize them. Each element in this array would be null.
You need to manually initialize them by calling the constructor.
So, your for loop should look like this:
for(int i=0;i<N;i++) {
marked[i] = new Marked();
marked[i].bool = false;
marked[i].comp=0;
}
I am currently working on a lab and would like to know how to handle the following problem which I have spent at least two hours on:
I am asked to create an ArrayList containing the values 1, 2, 3, 4 and 10. Whilst I usually never have any trouble creating an ArrayList with said values, I am having trouble this time. Should I create the ArrayList outside of the method or inside the method? Whichever way I have attempted it, I have been presented with numerous error messages. How do I add values to this ArrayList parameter? I have attempted to add values to it when calling it from the main method, but this still doesn't work. Here is the method in question.
public static double ScalesFitness(ArrayList<Double> weights){
//code emitted for illustration purposes
}
If anybody could help me it would be greatly appreciated. If any more code is required, then please let me know.
Thank you so much.
Mick.
EDIT: The code for the class in question is as follows:
import java.util.*;
public class ScalesSolution
{
private static String scasol;
//Creates a new scales solution based on a string parameter
//The string parameter is checked to see if it contains all zeros and ones
//Otherwise the random binary string generator is used (n = length of parameter)
public ScalesSolution(String s)
{
boolean ok = true;
int n = s.length();
for(int i=0;i<n;++i)
{
char si = s.charAt(i);
if (si != '0' && si != '1') ok = false;
}
if (ok)
{
scasol = s;
}
else
{
scasol = RandomBinaryString(n);
}
}
private static String RandomBinaryString(int n)
{
String s = new String();
for(int i = 0; i > s.length(); i++){
CS2004.UI(0,1);
if(i == 0){
System.out.println(s + "0");
}
else if(i == 0){
System.out.println(s + "1");
}
}
return(s);
}
public ScalesSolution(int n)
{
scasol = RandomBinaryString(n);
}
//This is the fitness function for the Scales problem
//This function returns -1 if the number of weights is less than
//the size of the current solution
public static double scalesFitness(ArrayList<Double> weights)
{
if (scasol.length() > weights.size()) return(-1);
double lhs = 0.0,rhs = 0.0;
double L = 0;
double R = 0;
for(int i = 0; i < scasol.length(); i++){
if(lhs == 0){
L = L + i;
}
else{
R = R + i;
}
}
int n = scasol.length();
return(Math.abs(lhs-rhs));
}
//Display the string without a new line
public void print()
{
System.out.print(scasol);
}
//Display the string with a new line
public void println()
{
print();
System.out.println();
}
}
The other class file that I am using (Lab7) is:
import java.util.ArrayList;
public class Lab7 {
public static void main(String args[])
{
for(int i = 0 ; i < 10; ++i)
{
double x = CS2004.UI(-1, 1);
System.out.println(x);
}
System.out.println();
ScalesSolution s = new ScalesSolution("10101");
s.println();
}
}
you can these
1) use varargs instead of list
public static double scalesFitness(Double...weights)
so you can call this method with :
scalesFitness(1.0, 2.0, 3.0, 4.0, 10.0);
2) create the list outside your method
ArrayList<Double> weights = new ArrayList<Double>();
weights.add(1.0);
weights.add(2.0);
weights.add(3.0);
weights.add(4.0);
weights.add(10.0);
scalesFitness(weights);
Towards your initial posting, this would work:
scalesFitness (new ArrayList<Double> (Arrays.asList (new Double [] {1.0, 2.0, 4.0, 10.0})));
You may explicitly list the values in Array form, but
you have to use 1.0 instead of 1, to indicate doubles
you have to prefix it with new Double [] to make an Array, and an Array not just of doubles
Arrays.asList() creates a form of List, but not an ArrayList, but
fortunately, ArrayList accepts a Collection as initial parameter in its constructor.
So with nearly no boilerplate, you're done. :)
If you can rewrite scalesFitness that would be of course a bit more easy. List<Double> as parameter is already an improvement.
Should I create the ArrayList outside of the method or inside the method?
The ArrayList is a parameter for the method so it need to be created outside the method, before you invoke the method.
You need to import ArrayList in the file that includes your methods. This is probably solved but that's the issue I was encountering.
I want a function / data structure that can do this:
func(int dim){
if(dim == 1)
int[] array;
else if (dim == 2)
int[][] array;
else if (dim == 3)
int[][][] array;
..
..
.
}
anyone know how?
Edit
Or you could use Array.newInstance(int.class, sizes). Where sizes is an int[] containing the desired sizes. It will work better because you could actually cast the result to an int[][][]...
Original Answer
You could use the fact that both int[] and Object[] are Objects. Given that you want a rectangular multidimensional array with sizes given by the list sizes
Object createIntArray(List<Integer> sizes) {
if(sizes.size() == 1) {
return new int[sizes.get(0)];
} else {
Object[] objArray = new Object[sizes.get(0)];
for(int i = 0; i < objArray.length; i++) {
objArray[i] = createIntArray(sizes.subList(1, sizes.size());
}
return objArray;
}
}
You lose all static type checking, but that will happen whenever you want a dynamically dimensioned array.
If your purpose is to create a truly dynamic array, then you should look at the Array object in the JDK. You can use that to dynamically generate an array of any dimension. Here is an example:
public void func(int dim) {
Object array = Array.newInstance(int.class, new int[dim]);
// do something with the array
}
Once the array Object has been created, you can use the methods of the java.lang.reflect.Array class to access, add, remove elements from the multi-dimension array that was created. In also includes utility methods to determine the length of the array instance.
You can even check the dimension of the array using:
public int getDimension(Object array) {
int dimension = 0;
Class cls = array.getClass();
while (cls.isArray()) {
dimension++;
cls = cls.getComponentType();
}
return dimension;
}
People have post good solutions already, but I thought it'd be cool (and good practice) if you wrap the dynamic multidimensional array into a class, which can use any data structure to represent the multi-dimensional array. I use hash table so you have virtually unlimited size dimensions.
public class MultiDimArray{
private int myDim;
private HashMap myArray;
public MultiDimArray(int dim){
//do param error checking
myDim = dim;
myArray= new HashMap();
}
public Object get(Integer... indexes){
if (indexes.length != myDim){throw new InvalidArgumentException();}
Object obj = myArray;
for (int i = 0; i < myDim; i++){
if(obj == null)
return null;
HashMap asMap = (HashMap)obj;
obj = asMap.get(indexes[i]);
}
return obj;
}
public void set(Object value, Integer... indexes){
if (indexes.length != myDim){throw new InvalidArgumentException();}
HashMap cur = myArray;
for (int i = 0; i < myDim - 1; i++){
HashMap temp = (HashMap)cur.get(indexes[i]);
if (temp == null){
HashMap newDim = new HashMap();
cur.put(indexes[i], newDim);
cur = newDim;
}else{
cur = temp;
}
}
cur.put(indexes[myDim -1], value);
}
}
and you can use the class like this:
Object myObj = new Object();
MultiDimArray array = new MultiDimArray(3);
array.put(myObj, 0, 1, 2);
array.get(0, 1, 2); //returns myObj
array.get(4, 5, 6); //returns null
What about a class like following?
class DynaArray {
private List<List> repository = new ArrayList<List>();
public DynaArray (int dim) {
for (int i = 0; i < dim; i++) {
repository.add(new ArrayList());
}
}
public List get(int i) {
return repository.get(i);
}
public void resize(int i) {
// resizing array code
}
}
Im working on this code and expecting a matrix to be printed but thats what came up
Matrix#2c78bc3b Matrix#2a8ddc4c
This is a code example:
public class Matrix
{
public static int rows;
public static int colms;//columns
public static int[][] numbers;
public Matrix(int[][] numbers)
{
numbers = new int[rows][colms];
}
public static boolean isSquareMatrix(Matrix m)
{
//rows = numbers.length;
//colms = numbers[0].length;
if(rows == colms)
return true;
else
return false;
}
public static Matrix getTranspose(Matrix trans)
{
trans = new Matrix(numbers);
for(int i =0; i < rows; i++)
{
for(int j = 0; j < colms; j++)
{
trans.numbers[i][j] = numbers[j][i];
}
}
return trans;
}
public static void main(String[] args)
{
int[][] m1 = new int[][]{{1,4}, {5,3}};
Matrix Mat = new Matrix(m1);
System.out.print(Mat);
System.out.print(getTranspose(Mat));
}
}
You need to implement toString() in a meaningful way.
This toString() (below) is perhaps suitable for debugging, but will be ugly and confusing if you use it for real user output. An actual solution would probably use a Formatter in some complicated way to produce neatly tabular rows and columns.
Some additional recommendations based on your code:
Suggest not storing the rows/columns sizes separately. SSOT / Single Source of Truth or DRY, Java+DRY. Just use the .length, and provide accessor methods if need be.
Use final in method args, it will eliminate bugs like you have above, aliasing numbers incorrectly int the constructor
Use an instance, not static
Paranoia is the programmer's lifestyle: I also modified my code to do a deepCopy of the provided int[][] array, otherwise there is reference leakage, and the Matrix class would be unable to enforce its own invariants if caller code later modified the int[][] they passed in.
I made my Matrix immutable (see final private numbers[][]) out of habit. This is a good practice, unless you come up with a good reason for a mutable implementation (wouldn't be surprising for performance reasons in matrices).
Here's some improved code:
public final class Matrix
{
final private int[][] numbers;
// note the final, which would find a bug in your cited code above...
public Matrix(final int[][] numbers)
{
// by enforcing these assumptions / invariants here, you don't need to deal
// with checking them in other parts of the code. This is long enough that you might
// factor it out into a private void sanityCheck() method, which could be
// applied elsewhere when there are non-trivial mutations of the internal state
if (numbers == null || numbers.length == 0)
throw new NullPointerException("Matrix can't have null contents or zero rows");
final int columns = numbers[0].length;
if (columns == 0)
throw new IllegalArgumentException("Matrix can't have zero columns");
for (int i =1; i < numbers.length; i++) {
if (numbers[i] == null)
throw new NullPointerException("Matrix can't have null row "+i);
if (numbers[i].length != columns)
throw new IllegalArgumentException("Matrix can't have differing row lengths!");
}
this.numbers = deepCopy(numbers);
}
public boolean isSquareMatrix() { return rowCount() == columnCount(); }
public int rowCount() { return numbers.length; }
public int columnCount() {return numbers[0].length; }
private static int[][] deepCopy(final int[][] source)
{
// note we ignore error cases that don't apply because of
// invariants in the constructor:
assert(source != null); assert(source.length != 0);
assert(source[0] != null); assert(source[0].length != 0);
int[][] target = new int[source.length][source[0].length];
for (int i = 0; i < source.length; i++)
target[i] = Arrays.copyOf(source[i],source[i].length);
return target;
}
public Matrix getTranspose()
{
int[][] trans = new int[columnCount()][rowCount()];
for (int i = 0; i < rowCount(); i++)
for (int j = 0; j < columnCount(); j++)
trans[i][j] = getValue(j, i);
return new Matrix(trans);
}
#Override
public String toString()
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < numbers.length; i++)
{
for (int j = 0; j < numbers[i].length; j++)
sb.append(' ').append(numbers[i][j]);
sb.append('\n');
}
return sb.toString();
}
public static void main(String[] args)
{
final int[][] m1 = new int[][] { { 1, 4 }, { 5, 3 } };
Matrix mat = new Matrix(m1);
System.out.print(mat);
System.out.print(mat.getTranspose());
}
}
for a quick and dirty method:
public String toString() {
return Arrays.deepToString(numbers);
}
On an unrelated note, the variables rows, colms, numbers and the methods isSquareMatrix should not be declared as static. Otherwise, when you get a transpose, you're going to end up with two matrix objects writing to the same class variables.
You didn't define a toString method for your Matrix class, so when you try to print a Matrix you see the result of the default toString method which prints the object's class and unique id.
System.out.print(Mat);
it will call the toString method of the Matrix class.
So, if you want to print your Matrix, you will have to override toString method
#Override
public String toString() {
// create here a String representation of your matrix
// ie: String myString = "1 0 0 1\n0 1 1 1\n...";
return "String representation of my matrix";
}
To display the Matrix class object when you can print on it you'll have to define the toString method in your class.
Another bug in the code it you are not setting the value of rows and colms. So when you do
numbers = new int[rows][colms];
in your constructor, rows and colms will always have their default value of 0. You need to fix that. And then you'll have to copy the matrix elements from the parameter array to numbers.