Related
in java if we have:
int[][] x = new int[3][3];
the memory address of x is different from the memory address of x[0]. As x[0] gives the memory address of the first column. So the memory address of x[0][0] is different than the memory address of x[0].
are there any computer languages that store a 2d array as a matrix and not as an array of arrays?
would the address of x always be different from x[0] and the address of x[0] equal x[0][0]?
are there any computer languages that store a 2d array as a matrix and
not as an array of arrays?
Yes. Or, at least, there used to be.
There is the possibility of using an assembler language, where the programmer has extreme control over how arrays might be handled. But, let's assume the question is about high-level languages (>=3GL).
I don't know about modern version of Fortran, but the early versions of FORTRAN stored any array, including multi-dimensional arrays, in consecutive storage locations. So, for example, if you declared an array as INTEGER FOO (3,4,5), then FOO and FOO (1,1,1) would have the same memory address. FOO would occupy a block of 60 INTEGER sized locations. The compiler generates code to find, from the subscript values, the location of an element in a manner similar to what #Jesse described in a comment on the question. It's slightly different to allow for the fact that FORTRAN subscripts started at one instead of zero.
By the way, FORTRAN subscript are in opposite order of most other languages. In Java, C, C++, and COBOL, the major subscripts are to the left. In FORTRAN, they were to the right.
FORTRAN syntax didn't allow missing subscripts. So, continuing the example, something like FOO (2,3) would generate a compiler error.
Now, suppose there was the following method:
REAL FUNCTION MEAN (ARR, N)
INTEGER N, ARR (N)
REAL SUM
DO 400 I = 1,N,1
SUM = SUM + ARR (I)
400 CONTINUE
RETURN SUM / N
END
A programmer could it use to calculate the mean of the entire FOO array, or any part of it:
REAL ALLMEAN, LEVEL3MEAN, ROWMEAN
ALLMEAN = MEAN (FOO(1,1,1), 60)
LEVEL3MEAN = MEAN (FOO(1,1,3), 12)
ROWMEAN = MEAN (FOO(1,2,3), 4)
Suppose, for some strange reason, there was this:
AVGPART = MEAN (FOO (2,3,2), 20)
This would use 20 consecutive elements of FOO, even if those elements were in different rows or levels.
When I took a C++ course, someone didn't like having to type separate [x] subscripts for multidimensional arrays. Instead of foo [2][1][0], he would rather type something like foo.get (2,1,0), so wrote a convenience wrapper class for an array. Such code might still have foo [t][r][c] inside the wrapper class. Or, it could allocate a 1D array. Once the class was created, it allowed him to specify subscripts as arguments in a call to a method.
Code in Java to do that, using the 1D array option, might look like this:
public class Block {
// class for regular 3D Array
private int [] array;
private int rows, int columns, int levels;
public Block (int t, int r, int c) {
rows = r;
columns = c;
levels = t;
array = new array [ t * r * c];
}
public int get (int t, int r, int c) {
return array [ t * rows * columns + r * columns + c ];
}
public void set (int value, int t, int r, int c) {
array [ t * rows * columns + r * columns + c ] = value;
}
...
}
Well, that might be a strange question, and maybe just because I'm not familiar enough with Java.
So, I declared a 2D int array:
int[][] arr = new int[0][10]
Now, as you can see, the second dimension's length is 10, while the first dimension's length is 0. I'm not sure how Java treats these kind of arrays, but the compiler doesn't produce any errors, which means it's a legit declaration.
Well, I passed the array to some function, and I want to retrieve from within the function, the length of the second dimension.
Of course something like:
arr[0].length
won't work. is there another way to do this?
The objects created by new int[0][10] and new int[0][20] are equivalent. There is no logical "second dimension" here. Effectively you're running something like this:
int[][] createArray(int d1, int d2) {
int[][] ret = new int[d1][];
for (int i = 0; i < d1; i++) {
ret[i] = new int[d2];
}
return ret;
}
Now if you translate that into your scenario, you'll end up with code which never reads d2.
If you want to represent a general-purpose rectangular array (instead of an array of arrays) you might want to consider creating your own type for it.
Arrays in Java, and most every other programming language, are zero-based. Consider this 2D array:
int[][] arr = new int[1][10];
This means that there is one row and ten columns in it.
Now, consider this array:
int[][] arr = new int[0][10];
This means that there are zero rows and (an irrelevant amount of columns) in it.
If you try to index into the second array, you'll find that you can't - an array of length zero has no starting point.
The compiler sees it as valid because you declared dimensions with it, but you won't be able to actually use it in any meaningful way in Java.
There is no such thing as the length of the second dimension. Consider:
int[][] arr = new int[10][10];
arr[5] = new int[42];
What is the length of the second dimension? 10 or 42?
No. It doesnt work this way. arr is an array with ten elements, each of which must be a reference of an int array (or null). That's all there is to say.
I've come across this piece of code in a program I'm editing for an assignment:
double[] colour = new double [3];
colour[0] = 255; colour[1] = 0; colour[2] = 0;
I think it means that the value colour is a double which is made by combining three other values. Is there anything more that needs to be said about this? I mean, is that why the double has the [] brackets directly after it - to specify that it needs to take more than one value? I'm slightly confused by this...
The [] means that you have an array of doubles. Arrays let you have multiple things in a sort of list, so you can have three numbers: [255, 0, 0]
More info is available in the Java array documentation: http://docs.oracle.com/javase/tutorial/java/nutsandbolts/arrays.html
The [] indicates you are creating an "array of double". This is primitive array which means the size is fixed. In your case an array of size 3 is being allocated.
An alternate method would be to use the List interface:
List<Double> colour = new ArrayList<Double>(3);
colour.add(255);
colour.add(0);
colour.add(0);
For this example you could also have a class:
public class Colour {
double r;
double g;
double b;
public Colour(double r, double g, double b) {
this.r = r;
this.g = g;
this.b = b;
}
....
}
A double[] is an array of double values.
In your particular case, colour is an array of size 3 (as specified on the right hand side of the assignment), and so you will access the three components using colour[0], colour[1] and colour[2] respectively.
In Java the [] after a type denote Array data structures.
In your case, you are creating an array of 3 double values.
Please refer to this Oracle tutorial for more information regarding the matter.
The line:
double[] colour = new double [3];
say: length colour[] = 3, datatype double,
and:
colour[0] = 255; colour[1] = 0; colour[2] = 0;
asign to colour the values [255, 0, 0]
PD: I can't comment sorry.
Keeping in mind that [] denotes array, which can be thought of as a collection of objects (in this case, numbers of the double data type), you can think of it in layman's terms like this:
The double[] colour part of the statement kind of says "I am going to have this collection called colour and it's going to be a type of double number, but I don't know what values or how many it's going to have." Emphasis on the word collection, since that's what an array is.
The new double [3] part says "I am creating 3 new doubles". Since you never said what the 3 doubles are, you begin to state them:
"The first one is 255, the second one is 0, and the third one is 0.", which in the code looks like this now:
colour[0] = 255; colour[1] = 0; colour[2] = 0
And I'm sure you might already know, but in computers, the numbers start counting up from 0 instead of 1.
[0] [1] [2]
First Element Second Element Third Element
Another example that helped me better understand arrays when I first started programming was thinking of a box of Oreos that has different flavors inside. The box is an array, the type of cookie is Oreos, the order in which they sit in the box represents their position (a.k.a. it's index), and the values are the flavor.
This code is valid
int h;
byte r;
h=r;
but these are not
int[] h;
byte[] r;
h=r;
or say
int[] h =new byte[4];
I would like to know why?
There's an implicit conversion from byte to int, but not from byte[] to int[]. This makes a lot of sense - the JIT compiler knows that to get to a value in an int[], it just needs to multiply the index by 4 and add that to the start of the data (after validation, and assuming no extra padding, of course). That wouldn't work if you could assign a byte[] reference to an int[] variable - the representations are different.
The language could have been designed to allow that conversion but make it create a new int[] which contained a copy of all the bytes, but that would have been pretty surprising in terms of the design of the rest of Java, where the assignment operator just copies a value from the right hand side of the operator to the variable on the left.
Alternatively, we could have imposed a restriction on the VM that every array access would have to look at the actual type of the array object in question, and work out how to get to the element appropriately... but that would have been horrible (even worse than the current nastiness of reference-type array covariance).
That's the design. When you assign byte to wider int, that's okay. But when you declare new byte[4], that's a ["continuous"] part of memory which is, roughly speaking, equal to 4 * 8 bits (or 4 bytes). And one int is 32 bits, so, technically, all your byte array's size is equal to size of one int. In C, where you have a direct memory access, you could do some pointer magic and get your byte pointer casted to int pointer. In Java, you cant and that's safe.
Anyway, why do you want that?
Disclaimer: the code below is considered to be extremely unlikely seen anywhere except for the most critical sections in some performance-sensitive libraries/apps. Ideone: http://ideone.com/e14Omr
Comments are explanatory enough, I hope.
import sun.misc.Unsafe;
import java.lang.reflect.Field;
public class Main {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, InstantiationException {
/* too lazy to run with VM args, use Reflection */
Field f = Unsafe.class.getDeclaredField("theUnsafe");
f.setAccessible(true);
/* get array address */
Unsafe unsafe = (Unsafe)f.get(null);
byte four_bytes[] = {25, 25, 25, 25};
Object trash[] = new Object[] { four_bytes };
long base_offset_bytes = unsafe.arrayBaseOffset(Object[].class);
long four_bytes_address = unsafe.getLong(trash, base_offset_bytes); // <- this is it
long ints_addr = unsafe.allocateMemory(16); // allocate 4 * 4 bytes, i.e. 4 ints
unsafe.copyMemory(four_bytes_address + base_offset_bytes, ints_addr, 4); // copy all four bytes
for(int i = 0; i < 4; i++) {
System.out.println(unsafe.getInt(ints_addr + i)); //run through entire allocated int[],
// get some intestines
}
System.out.println("*****************************");
for(int i = 0; i < 16; i++) {
System.out.println(unsafe.getByte(ints_addr + i)); //run through entire allocated int[],
// get some intestines
}
}
}
The difference is firstly due to the difference in behavior between primitive types and reference types.
In case you're not familiar with it, primitive types have "value semantics". This means that when you do a = b; when a and b are a primitive type (byte, short, int, long, float, double, boolean, or char) the numeric/boolean value is copied. For example:
int a = 3;
int b = a; // int value of a is copied to b
a = 5;
System.out.println(b); // outputs: 3
But arrays are objects, and objects have "reference semantics". That means that when you do a = b; where a and b are both declared as an array type, the array object that is referred to becomes shared. In a sense the value is still copied, but here the "value" is just the pointer to the object located elsewhere in memory. For example:
int[] a = new int[] { 3 };
int[] b = a; // pointer value of a is copied to b, so a and b now point at the same array object
a[0] = 5;
System.out.println(b[0]); // outputs: 5
a = null; // note: 'a' now points at no array, although this has no effect on b
System.out.println(b[0]); // outputs: 5
So it is okay to do int = byte because the numeric value is going to be copied (as they are both primitive types) and also because any possible value of type byte can be safely stored in an int (it is a "widening" primitive conversion).
But int[] and byte[] are both object types, so when you do int[] = byte[] you are asking for the object (the array) to be shared (not copied).
Now you have to ask, why can't an int array and a byte array share their array memory? And what would if mean if they did?
Ints are 4 times the size of bytes, so if the int and byte arrays were to have the same number of elements, then this causes all sorts of nonsense. If you tried to implement it in a memory efficient way, then complex (and very slow) run-time logic would be needed when accessing elements of int arrays to see if they were actually byte arrays. Int reads from byte array memory would have to read and widen the byte value, and int stores would have to either lose the upper 3 bytes, or throw an exception saying that there isn't enough space. Or, you could do it in a fast but memory-wasting way, by padding all byte arrays so that there are 3 wasted bytes per element, just in case somebody wants to use the byte array as an int array.
On the other hand, perhaps you want to pack 4 bytes per int (in this case, the shared array won't have the same number of elements depending on the type of the variable you use to access it). Unfortunately this also causes nonsense. The biggest problem is that it is not portable across CPU architectures. On a little-endian PC, b[0] would refer to the low byte of i[0], but on an ARM device b[0] might point at the high byte of i[0] (and it could even change while the program is running as ARM has a switchable endianness). The overhead of accessing the array's length property would also be made more complicated, and just what should happen if the byte array's length is not divisible by 4?!
You can do this in C, but that's because C arrays don't have a well-defined length property and because C doesn't try to protect you from the other issues. C doesn't care if you go outside the array bounds or muddle up endianness. But Java does care, so it is not feasible to share the array memory in Java. (Java doesn't have unions.)
That's why int[].class and byte[].class both separately extend class Object, but neither class extends the other. You can't store a reference to a byte array in a variable that is declared to point at int arrays, in the same way you can't store a reference to a List in a variable of type String; they're just incompatible classes.
When you say
int[] arr = new byte[5];
you copy references. On the right hand side is a reference to a byte array. Essentially, this looks like:
|__|__|__|__|__|
0 1 2 3 4 offset of elements, in bytes
^
|
reference to byte array
On the left hand side is a reference to an int array. This, however, is expected to look thus:
|________|________|________|________|________|
0 4 8 12 16
^
|
reference to int array
Hence, simply copying the reference is not possible. For, to get arr[1], the code would look at the starting address+4 (rather than starting adress+1).
The only way to achieve what you want is to create an int[] that has the same number of elements and copy the bytes there.
The rationale behind not doing that automatically:
interpreting a single byte as an int comes at essentially no cost, especially no memory must be allocated.
copying a byte array is completly different. The new int array must be allocated, which is at least 4 times at big as the byte array. The copy process itself could take some time.
Conclusion: In Java, you can always say "I want to treat this special byte as if it were an int." But you can not say: "I want to treat some data structure (like an array, or a class instance) that contains bytes as if it contained ints."
Simply, Type byte[] does not extend int[]
you cant because its like big element is going to be stored in smaller one.Integer cant be stored in byte.Its our memory design who decides these type of allocation
Today i did learn two ways of accessing the array, i would like to know the various ways of accessing an array element and the best practice of it. I am a student learning algorithm.
int [] arr;
long [] arr;
Advantages of long datatype declaration over int.
class ArrayApp{
public static void main(final String[] args){
long [] arr;
arr= new long[2];
int i;
arr[0]=112;
arr[1]=111;
**// Way one**
for(long l:arr)
{
System.out.println(l);
}
**// Way Two**
for(i=0;i<arr.length;i++) {
System.out.println(arr[i]);
}
}
}
There is no real difference between the ways here. Way one is just a syntax sugar for not to create an additional interation value.
The first way is preferable as it doesn't require an int i; variable and requires less printing. The second should be used when you don't want to iterate through the all array, but just a part of it.
There is no other ways to access the elements of array in java.
We've one declaration of an array:
long[] values = new long[100];
This creates an array for 100 long type values. Each value has an index (position) inside the array, the first index (an int value!) is 0, the last one is 99.
The traditional for loop increments an integer value to generate index position numbers. Those int values are used to access the long values of the array:
for (int index=0; index < values.length; index++) { // index is int
long value = values[index]; // value is long
// do something with value
}
The "enhanced" for loop simply hides this index and gives access to the long values with less code:
for (long value:values) {
// do something with value
}
That's all. If you don't need the index variable in your code, just use the enhanced for loop (second version in my answer)
The first way
for(long l:arr)
{
System.out.println(l);
}
The java runtime will autobox the l to a Long, as iterating this way requires that the class implement the Iterable interface. This way, also does not provide the current index of the array.
The second way
for(i=0;i<arr.length;i++) {
System.out.println(arr[i]);
}
Requires no casts to Long and you also have access to the current index. You also however have to be careful about iterating past the end of the array or accessing array elements below 0.
An int is shorter as a long. You can make an array of any object or primitive type. int[], Integer[], CustomClass[], whatever.
From java documentation:
int: The int data type is a 32-bit
signed two's complement integer. It
has a minimum value of -2,147,483,648
and a maximum value of 2,147,483,647
(inclusive). For integral values, this
data type is generally the default
choice unless there is a reason (like
the above) to choose something else.
This data type will most likely be
large enough for the numbers your
program will use, but if you need a
wider range of values, use long
instead.
long: The long data type is a 64-bit
signed two's complement integer. It
has a minimum value of
-9,223,372,036,854,775,808 and a maximum value of
9,223,372,036,854,775,807 (inclusive).
Use this data type when you need a
range of values wider than those
provided by int.