Java class does not recognize indexing - java

I made a Matrix class in JAVA that consists of a 2D int array with row and column variables. The constructor of the class generates a Matrix of dimensions n x m and I also implemented two methods that print the values of the Matrix and its transpose (getMatrixValues and getTransposedValues).
However, I would like to make a function that takes as input a matrix and returns its transpose, but since this class is not an array I cannot iterate over it using AT[j][i] = A[i][j], if I understand the exception correctly that IntelliJ is returning me ("java: array required, but Matrix found").
Obviously, I could simply use an int[][] class to begin with instead of defining a new class, but since I am new to JAVA and object-oriented programming in general I wondered whether there is not another possibility without discarding my Matrix class?
Here is my code:
import java.util.Random;
import java.util.Arrays;
public class Matrix {
private int n; // rows
private int m; // cols
private int[][] A; // matrix
public static void main(String[] args){
Matrix A = new Matrix(4,4);
A.getMatrixValues();
System.out.println("\n");
A.getTransposedValues();
Matrix AT = transposeMatrix(A);
}
// constructor (randomly generates matrix)
public Matrix(int rows, int cols){
n = rows;
m = cols;
A = new int[rows][cols];
Random r = new Random();
// r.setSeed(1);
for(int i = 0; i < rows; i++)
{
for(int j = 0; j < cols ; j++)
{
A[i][j] = r.nextInt(10);
}
}
}
// print matrix
public void getMatrixValues(){
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
System.out.print(A[i][j]+"\t");
}
System.out.print("\n");
}
}
// print transposed matrix
public void getTransposedValues(){
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
System.out.print(A[j][i]+"\t");
}
System.out.print("\n");
}
}
public static Matrix transposeMatrix(Matrix A){
Matrix AT = new Matrix(A.get_n(), A.get_m());
for(int i = 0; i < A.get_n(); i++)
{
for(int j = 0; j < A.get_m(); j++)
{
AT[j][i] = A[i][j];
}
}
return AT;
}
// getters
public int get_n(){
return n;
}
public int get_m(){
return m;
}
}

Preface
What I have noticed only afterwards was, that when creating the transposed matrix, you actually want to create one with m-rows and n-columns.
That means, you have mixed up m and n in transposeMatrix() when instantiating the new object.
That also means that your code -as it is- only works for square matrices. Just create the object like this: new Matrix(matrix.get_m(), matrix.get_n()).
Note: I re-named your variables; see below in section "Solution".
However, since this is not part of you question, I have not fixed it in the code-snippets below.
Scopes
When in every other method, you are in the lexical scope of the object you are in. This allows you to access its fields (like int[][] A).
But when inside transposeMatrix(Matrix A), you are inside the static scope, meaning, not in the scope of an object.
What adds to the confusion is, that your instance-variable is called A, much like the parameter Matrix A of transposeMatrix(). While you were able to access the 2D-array via A, you now access a Matrix-object via A. That is both because we are not in an object anymore, and because the new local variable overrides the access to the similarly named instance-/static-variable (you would have to use this.A or Matrix.A respectively).
Access modifier
When trying to fix your code, you will stumble upon the restriction of the access modifier you used: private.
private int[][] A will make A (your array) only accessible when referenced from inside your object. But when calling transposeMatrix(), we are in a static-context, meaning, not inside your object anymore.
To fix this, can change the access modifier to allow us to access that field from outside the object. To enable this, you can change the modifier to any other option, with the easiest being to just remove it. However, I suggest you to read more about Access Modifier in the official documentation.
Solution
Let's say we removed private from int[][] A. Will the code work?
No. That's because of the confusion I talked about when explaining scopes. To clear up the confusion, let's rename some variables: (Changed int[][] A to int[][] array, Matrix A to Matrix matrix, Matrix AT to Matrix matrixTransposed)
int[][] array; // <-- Notice the removed access modifier!
// ...
public static Matrix transposeMatrix(Matrix matrix){
Matrix matrixTransposed = new Matrix(matrix.get_n(), matrix.get_m());
for (int i = 0; i < matrix.get_n(); i++) {
for(int j = 0; j < matrix.get_m(); j++) {
matrixTransposed[j][i] = matrix[i][j]; // Won't work!
}
}
}
The code above is still faulty. That is -as we can clearly see now- because we are trying to access a Matrix-object as if it was an array. However, we need to access its instance variable. So, instead of accessing the array the wrong way, we add a .array after every Matrix-object where we try to access its array.
public static Matrix transposeMatrix(Matrix matrix){
Matrix matrixTransposed = new Matrix(matrix.get_n(), matrix.get_m());
for (int i = 0; i < matrix.get_n(); i++) {
for(int j = 0; j < matrix.get_m(); j++) {
matrixTransposed.array[j][i] = matrix.array[i][j]; // NOW we are accessing their arrays respectively
}
}
}
Another solution
With changing the access modifier of the array (like we did above), we enable one to not only override the values of the array, but also to override the array itself.
To restrict one from doing so, we can use "Getters and Setters". They are like a middle-man, allowing us to access the array only indirectly, but with that much control over it as we seem necessary.
We can define them simply creating two new methods (hence its name):
public int get(int i, int j) {
return array[i][j];
}
public void set(int i, int j, int value) {
array[i][j] = value;
}
As you see, we simply forward the request to the "middle-man", which handles it accordingly.
Note: We might encounter a Runtime Exception since we are not checking if the fields at the specified indices actually exist. You might want to add some if-statements before accessing them.
By using the getter and setter, we can modify the code to this:
private int[][] array; // We still want to restrict access to 'array'...
// ...
// ...but still allow accessing them, be it indirectly
public int get(int i, int j) {
return array[i][j];
}
public void set(int i, int j, int value) {
array[i][j] = value;
}
// Now using getter and setter
public static Matrix transposeMatrix(Matrix matrix) {
Matrix matrixTransposed = new Matrix(matrix.get_n(), matrix.get_m);
for (int i = 0; i < matrix.get_n(); i++) {
for (int j = 0; j < matrix.get_m; j++) {
matrixTransposed.set(j, i, matrix.get(i, j));
}
}
}
Sidenote
You should also take a look at naming conventions. They are not critical to make your code function, but make reading and understanding (and thus debugging) it a lot easier.
What I think is also good, is to take a look at a style-guide to see how you can make your code more readible with easy tricks, or just to have a consistent style across your code. I enjoy Google's style-guide for Java, however, there are a lot others as well.
And, you don't have to stick to an existing style-guide, you can have your own style, too! But try to be as consistent as possible. That makes it easier for others and yourself in the future when re-reading your code.

Related

How to get length from array as a cass memeber?

I have a class that has some arrays as members. In some member functions i want to then iterate over said arrays. But when i try to get the length of the array i see the error non static variable cannot be referenced from a static context.
I have the line for(int i = 0; i < this.blue; i++){} and the array is private int[][] blue;
For example:
public class M{
private int[][] arr;
public static void func(){
for(int i = 0; i < this.arr.length; i++){
// ^^^^ compiler does not like this
}
}
}
I understand that i am not looking at an instance of the class, so the value could be anything, but then how will i ever be able to preform such basic operations if i have to know everything before hand?
I have tried to create another member that holds the dimensions, but that leads to the same issue.
public class M{
private int[][] arr;
public void func(){
for(int i = 0; i < this.arr.length; i++){
// ^^^^ compiler does not like this
}
}
}
This removes the error. That is removing static from func(). At some point I learned to write it and then stopped questioning it. Thanks for the input in the comments.

java arrays reverse not understanding the logic

I was trying to use this code I made to reverse a array. I don't understand why I was getting [I#7a84639c as my output in my console.
And for some reason why doesn't this method actually save my reversed array into the array? If i add a print at the bottom of x[i]=c[i]; it shows the array reversed but when i add a call for example karn[0] it shows that my array isn't actually reversed. I want to solve this by staying true to the code i made.
import java.util.Arrays;
public class HelloWorld {
public static void main(String[] args) {
int[]karn={1,2,3};
rev(karn);
System.out.println(karn.toString());
}
public static void rev(int[]x){
int[]c=new int[x.length];
for(int i=x.length-1;i>-1;i--){
c[i]=x[i];
x[i]=c[i];
}
}
}
in your rev method you are using a local variable for c. So this value will not be transferred over to your main method. You must return your array and assign the value to your old array:
public static int[] rev(int[]x){
//Creates new array this array is different from karn and local to the method.
//nothing outside of this method can see this array.
int[]c=new int[x.length];
for(int i = 0; i < c.length; i++){
//Here is where we are swapping the values by placing the first
//value at the last spot of the array and so on
c[c.length - i - 1] = x[i];
}
//we must return the new array we made and assign it to karn so our
//changes will be saved and seen outside of the method
return c;
}
In main method you must assign the changes of the rev method to karn. You can assign the value and display it like so:
karn = rev(karn);
//for each loop
for(int i : karn)
System.out.println(i);
//traditional for loop
for(int i = 0; i < karn.length; i++)
System.out.println(karn[i]);
Arrays do not have a default toString() method. That is why you are seeing the values of the array as you would like. You need to iterate through the array to display them to the console.
Your initial approach looked almost correct, you can do this in-place or through a copy. I posted a comment showing a copy, so I thought I might expand on in-place. I would start with a simple swap method, like
private static void swap(int[] x, int i, int j) {
if (i != j) {
int t = x[i];
x[i] = x[j];
x[j] = t;
}
}
Then you only need to iterate the first half of the array, swapping each element with the same index (but from the other half). Like,
public static void rev(int[] x) {
for (int i = 0; i < x.length / 2; i++) {
swap(x, i, x.length - i - 1);
}
}
Then you might call it like
public static void main(String[] args) throws IOException {
int[] karn = { 1, 2, 3 };
rev(karn);
System.out.println(Arrays.toString(karn));
}
for an output of
[3, 2, 1]

How to reset a sorted array to unsorted in Java?

I am writing a program to compare different sort methods. I random generated 100,000 integers and store these data to an array. I want to apply the same array to different sort methods in order to do the comparison. (I think create class for each method may solve my problem. But I don't want to create too many class). So I decided to create one class called Sorts and bunch of sort functions under this class. I want to my sorted array reset to unsorted in order apply the same array to different sort method. Could anyone tell me how?
Generate data:
int size = Integer.parseInt(br.readLine());
int [] data = new int[size];
for (int i = 0; i< size; i++){
data[i] = (int)(Math.random()*(10*size));
System.out.print(data[i]+" ");
}
Create object:
Sorts sort = new Sorts(size, data);
Invokeļ¼š
switch(index){
case "1" :
System.out.print("\nYou select bubble sort\n");
sort.bubbleSort();
break;
case "2" :
System.out.print("You select quick sort\n");
sort.quickSort();
break;
My class:
class Sorts{
private int size;
private int data[];
Sorts(int size, int [] data){
this.size = size;
this.data = data;
}
protected void bubbleSort(){
int temp = 0;
for (int i = 0; i< (data.length-1); i++){
for (int j = 0; j<(data.length-1);j++){
if(data[j]>data[j+1]){
temp = data[j];
data[j] = data[j+1];
data[j+1]= temp;
}
}
}
printResult();
}
protected void quickSort(){
}
protected void resetData(){
}
}
Well, you could use Collections.shuffle, which takes a 'List' parameter. This would obviously mean converting your 'int[]' to 'List' (and back again).
Here's the java spec for 'Collections.shufffle'.
See the 'Collections.shuffle' tutorial on tutorialspoint.
There's also a sample array ('int[]') version on Vogella.
On another point, rather than implement it as you have, Ithink it's better to use the Strategy pattern to implement multiple sort mechanisms like this. For instance:
interface Sort {
void sort(int data[], int size);
}
class QuickSort implements Sort {
void sort(int data[], int size) {
...
}
}
class MergeSort implements Sort {
void sort(int data[], int size) {
...
}
}
etc...
As a further aside:
this is only sorting ints so consider how to sort any type (and perhaps generics).
some sorts (e.g. MergeSort) are stable and use new arrays to represent the sorted data. How can you return that to the caller? You can't set 'data' to your new array.
You can use the Method shuffle of the class Collection
Collection.shuffle(yourList);
This will shuffle your list automatically without implementing an own function.
After that you can convert the list back to an array. :)
I think for the usecase OP seems to have, the array just needs a reshuffling, this method reshuffles although there is no guarantee that it would reset it to the original array
private void reset(final int arr[]) {
Random rand = new Random();
for (int i = 0; i < arr.length; i++) {
int nextInt = rand.nextInt(arr.length);
int temp = arr[i];
arr[i] = arr[nextInt];
arr[nextInt] = temp;
}
}

Java: Accessing pointers

I get: 'unexpected type
required: variable
found : value' on the marked lines (*)
for (int i = 0; i < boardSize; i++) {
for (int j = 0; j < boardSize; j++) {
rows[i].getSquare(j) = matrix[i][j]; // * points to the ( in (j)
columns[j].getSquare(i) = matrix[i][j]; // * points to the ( in
int[] b = getBox(i, j);
int[] boxCord = getBoxCoordinates(i + 1, j + 1);
boxes[b[0]][b[1]].getSquare(boxCord[0], boxCord[1]);
}
}
This is my Row class:
private Square[] row;
Row(int rowCount) {
this.row = new Square[rowCount];
}
public Square getSquare(int index) {
return this.row[index];
}
Please help me out by pointing out what I'm doing wrong here.
Thanks in advance.
You cannot assign something to the return value of a method. Instead, you need to add a setSquare() method to the Row class:
public Square setSquare(int index, Square value) {
this.row[index] = value;
}
and use it like this:
rows[i].setSquare(j, matrix[i][j]);
Java doesn't have pointers - references are not the same thing.
It's impossible to tell what's really going on based on the code you posted. I think you need a method to set the value of that Square in the private array your Row class owns.
public void setSquare(int index, Square newSquare) {
this.row[index] = newSquare;
}
It looks like a poor abstraction, in any case.
Java has no pointers. Objects are passed and returned by reference. In terms of C++, rows[i].getSquare(j) is an rvalue, not an lvalue, so you cannot assign to it.
Instead, you should create and use rows[i].setSquare(...).

Understanding constructors and "this"

I'm learning constructors and I understand them for the most part, but I must not understand it enough. I also don't understand this fully. But this code below is supposed to use these constructors:
default constructor, which will be used to fill the matrix with random doubles
constructor which takes a File object, which points to a file
containing a matrix,
constructor which takes a string, which contains the name of the file
constructor which takes a value of type Matrix, and makes a copy of it
constructor which takes a 2D array, and copies its values
And some more, along with a static multiply method. I am supposed to use the commands that are found in main. But I don't quite understand how using a String as the only parameter will do the constructor it's told to, and also the other ones like the default constructor that fills the array with random doubles. I think I should be using this more in my code, but I'm not quite sure.
I mainly just need to be able to set a matrix, fill m1 matrix with random doubles, do it again with m2 matrix, and then use the static multiply method to multiply them, then output the resulting matrix. Thank you.
(Just a heads up, I'm using a 3 by 3 matrix, originally I was supposed to set the size of the matrix to the one found in the text file, but I can also specify the size I want, which I am. And sorry for the messy code. It got all jumbled up while I was trying to figure this stuff out, and I'm afraid of altering it further.)
public class Matrix {
double A[][] = new double[3][3]
// Matrix file name
public Matrix(String name) {
this(new File(name));
}
// Matrix random fill
public Matrix() {
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
this.A[i][j] = (min + Math.random() * (max - min));
}
// Matrix copy
public Matrix(double[][] A) {
private double[][] arrcopy = new double[3][3];
private double[][] array = new double[3][3];
array = A;
for(int i = 0; i < 3; ++i){
for(int j = 0; j < array[i].length; ++j) {
arrcopy[i][j] = array[i][j];
}
}
}
// Set array from text file
public Matrix(File a) {
File f = a;
Scanner inputStreamOne = null;
try{
inputStreamOne = new Scanner(f);
}
catch(FileNotFoundException e){
System.out.printf("Error\n");
}
double arrayOne[][] = new double[3][3];
while(inputStreamOne.hasNextInt()) {
for(int i = 0; i < 3; ++i){
for(int j = 0; j < arrayOne[i].length; ++j){
arrayOne[i][j] = inputStreamOne.nextInt();
}
}
inputStreamOne.close();
}
}
// Gets array in file from string name
public Matrix(String a) {
String inputOne = a;
Scanner inputStreamOne = null;
try{
inputStreamOne = new Scanner(new File(inputOne));
}
catch(FileNotFoundException e){
System.out.printf("Error\n");
}
while(inputStreamOne.hasNextInt()){
for(int i = 0; i < size; ++i){
for(int j = 0; j < arrayOne[i].length; ++j){
arrayOne[i][j] = inputStreamOne.nextInt();
}
}
inputStreamOne.close();
}
}
public static multiply
public static void main(String args[]) {
Matrix m = new Matrix("matrix1.txt");
Matrix m2 = new Matrix("matrix2.txt");
Matrix r = Matrix.multiply(m, m2);
r.output(...);
}
}
Within a constructor or a method this refers to the current object. Within a constructor, if you just use a bare this ( which is to say this without a .method after it ) then it refers to another constructor of the same object that has a different type signature.
Constructors, like any function in Java, can be overloaded. Which is to say, because of Java's type system you can have multiple functions that are of the same name so long as they have different type signatures.
class Foo {
public Foo ( String arg ) {
this(arg, "World");
}
public Foo ( String arg1, String arg2 ) {
// do stuff with arg1 and arg2
}
}
In the above example, one constructor takes a single string and the other takes two. Java won't magically know what to do with the data passed into different constructors. What you have to do is write code in each method so that the resulting object is the same. ( Well technically you don't have to do that, but it's good form ( usually overloaded constructors are for setting default values or for the ease of use of other programmers ))
The this keyword refers to the current object in a constructor or a method, i.e. the object whose constructor or method is being called. Within a constructor, you can also use this to call another constructor in the class.
Refer to http://docs.oracle.com/javase/tutorial/java/javaOO/thiskey.html for a clear explanation from Java Tutorials.

Categories