We can determine the length of an ArrayList<E> using its public method size(), like
ArrayList<Integer> arr = new ArrayList(10);
int size = arr.size();
Similarly we can determine the length of an Array object using the length property
String[] str = new String[10];
int size = str.length;
Whereas the size() method of ArrayList is defined inside the ArrayList class, where is this length property of Array defined?
Arrays are special objects in java, they have a simple attribute named length which is final.
There is no "class definition" of an array (you can't find it in any .class file), they're a part of the language itself.
10.7. Array Members
The members of an array type are all of the following:
The public final field length, which contains the number of components of the array. length may be positive or zero.
The public method clone, which overrides the method of the same name in class Object and throws no checked exceptions. The return type of the clone method of an array type T[] is T[].
A clone of a multidimensional array is shallow, which is to say that it creates only a single new array. Subarrays are shared.
All the members inherited from class Object; the only method of Object that is not inherited is its clone method.
Resources:
JLS - Arrays
It's "special" basically, with its own bytecode instruction: arraylength. So this method:
public static void main(String[] args) {
int x = args.length;
}
is compiled into bytecode like this:
public static void main(java.lang.String[]);
Code:
0: aload_0
1: arraylength
2: istore_1
3: return
So it's not accessed as if it were a normal field. Indeed, if you try to get it as if it were a normal field, like this, it fails:
// Fails...
Field field = args.getClass().getField("length");
System.out.println(field.get(args));
So unfortunately, the JLS description of each array type having a public final field length is somewhat misleading :(
It's defined in the Java language specification:
The members of an array type are all of the following:
The public final field length, which contains the number of components of the array. length may be positive or zero.
Since there is a limitless number of array types (for every class there is a corresponding array type, and then there are multidimensional arrays), they cannot be implemented in a class file; the JVM has to do it on the fly.
Even though this is not a direct answer to the question, it is an addition to the .length vs .size() argument. I was researching something related to this question so when I came across it I noticed that the definition(s) provided here
The public final field length, which contains the number of components of the array.
is not "exactly" correct.
The field length contains the number of available places to put a component, not the number of components present in the array. So it represents the total available memory allocated to that array, not how much of that memory is filled.
Example:
static class StuffClass {
int stuff;
StuffClass(int stuff) {
this.stuff = stuff;
}
}
public static void main(String[] args) {
int[] test = new int[5];
test[0] = 2;
test[1] = 33;
System.out.println("Length of int[]:\t" + test.length);
String[] test2 = new String[5];
test2[0] = "2";
test2[1] = "33";
System.out.println("Length of String[]:\t" + test2.length);
StuffClass[] test3 = new StuffClass[5];
test3[0] = new StuffClass(2);
test3[1] = new StuffClass(33);
System.out.println("Length of StuffClass[]:\t" + test3.length);
}
Output:
Length of int[]: 5
Length of String[]: 5
Length of StuffClass[]: 5
However, the .size() property of the ArrayList does give the number of elements in the list:
ArrayList<Integer> intsList = new ArrayList<Integer>();
System.out.println("List size:\t" + intsList.size());
intsList.add(2);
System.out.println("List size:\t" + intsList.size());
intsList.add(33);
System.out.println("List size:\t" + intsList.size());
Output:
List size: 0
List size: 1
List size: 2
it's public final field , which contains the number of components of the array (length may be positive or zero)
An array thus has the same public fields and methods as the following class:
class A implements Cloneable, java.io.Serializable {
public final int length = X;
public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
throw new InternalError(e.getMessage());
}
}
}
more info at
10.7 Array Members
http://java.sun.com/docs/books/jls/second_edition/html/arrays.doc.html
To answer it as it-is, where is this length property of array defined? In a special Object header.
Easy to see via JOL
int [] ints = new int[23];
System.out.println(ClassLayout.parseInstance(ints).toPrintable());
One of the lines from this output is going to be:
OFFSET SIZE TYPE DESCRIPTION
16 4 (object header) 17 00 00 00 (00010111 00000000 00000000 00000000) (23)
Usually Objects have two headers (mark and klass), arrays have one more that always occupy 4 bytes in length, as size is an int.
The keyword length acts like a data filed defined. When using in an array, we can use it to access how many elements in an array. Regarding to String[], we can invoke length() method defined in String class. With regard to ArrayList, we can use size() method defined in ArrayList. Note that when creating an array list with ArrayList<>(capacity), the initial size() of this array list is zero since there is no element.
Related
There is a multidimensional String array being passed in as an Object.
I'm supposed to "unfold" it and process each of its primitive entries.
There's no way to know the dimensions other than by looking at the Object itself.
The difficulty i'm having is in casting. I can look up the array dimension by invoking its getClass().getName() and counting the [-s there.
But then how to cast it?
String[] sa = (String[]) arr;
is giving
Exception in thread "main" java.lang.ClassCastException: [[Ljava.lang.String; cannot be cast to [Ljava.lang.String;
Can this casting be done without any use of reflection?
Note - The array can be of any dimension - not just 1 or 2.
TIA.
If you want to work with an array which dimension is not known at the compile time, I would suggest you to recursively process all of its entries instead of trying to cast it.
You can use object.getClass().isArray() method to check if the current entry is an array and then iterate over it using Array.getLength(object) and Array.get(object, i):
public static void main(String[] args) {
Object array = new String[][] {new String[] {"a", "b"}, new String[] {"c", "d"}};
processArray(array, System.out::println);
}
public static void processArray(Object object, Consumer<Object> processor) {
if (object != null && object.getClass().isArray()) {
int length = Array.getLength(object);
for (int i = 0; i < length; i ++) {
Object arrayElement = Array.get(object, i);
processArray(arrayElement, processor);
}
} else {
processor.accept(object);
}
}
If the size of the array is not known statically (at compile time), then it's logically impossible to get the length relying solely on static means, i.e. without use of dynamic means.
Perhaps this question has the solution you need:
Getting the field "length" in a Java array using reflection
In the main method I make a new object of the DotComClass and set
locationOfShips array to 14 numbers. Then send those values as an
argument over to the setter method (setLocations) in the other class
(see below). My question is why does it allow that pass over without
issue, since I set the max number of elements of the locations
instance variable is 5?
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
DotComClass dotCom = new DotComClass();
int[] locationOfShips = {6,7,8,9,1,2,3,4,4,4,4,5,5,5};
dotCom.setLocations(locationOfShips);
}
}
public class DotComClass {
int [] locations = new int[5]; // is this not related to the locations in the setter?
public void setLocations (int[] locations){
this.locations= locations;
System.out.println(Arrays.toString(locations));
}
}
The locations field is a reference to an array.
This points that reference to a new array of 5 integers.
int [] locations = new int[5]; // is this not related to the locations in the setter?
This re-points that reference to a different array.
this.locations= locations;
The new array has its own size. It's not limited by the size of the array that the reference formerly pointed to.
There is a simple mistake you are making, the variable int [] locations = new int[5]; does not actually contain an array of length 5. It is actually just holding the reference to the array of length 5 somewhere on the heap.
This is exactly what this statement below is also doing,
int[] locationOfShips = {6,7,8,9,1,2,3,4,4,4,4,5,5,5};
so when you are running this.locations= locations;, you are actually saying the variable now refers to the array locationOfShips
If this is not clear i suggest you read about pass by reference good explanation here (Are arrays passed by value or passed by reference in Java?)
When creating an array of a class in java there are three steps: Declaration, instantiation and initiation.
But when creating an array of primitive data types, does the new keyword instantiate or initiate?
I found it confusing as in many places the word instantiate is used only for array of a class/classes. So, i want to know if the step of instantiating is also used for array of PRIMITIVE data type. Or, is it that the whole statement of initiating an array is as shown below.
int intArray[]; //declaring array
intArray = new int[20]; // allocating memory to array
Can array of primitive data type be instantiated?
Yes.
Does the new keyword in new int[20] instantiate or initiate?
In that example, it both instantiates the primitive array and initializes it1 to the default value for the primitive type; i.e. zero for an array of a primitive numeric type and false for an array of boolean.
On the other hand:
int intArray[];
is declaring an array variable and not either initializing the variable, or instantiating an array. If that is a local variable declaration, the compiler won't let you use the variable until it is assigned to. If it is a field, then the variable will be default initialized to null; i.e. no array is instantiated.
Java does not allow a program to access a variable or array element that has not been initialized, either explicitly or by default initialization. This is a fundamental property of the language.
1 - The correct term is initialize NOT initiate. Initiate (in English) means either "to begin" (e.g. an action or process) or "to admit (someone) into a secret or obscure society or group, typically with a ritual.". This not the correct meaning in this context.
In Java , when we instantiate a primitive array (like new int[10]), items in the array are initialized with default value of that primitive. (Default value for int is 0, default value for boolean is false etc.)
When we instantiate an object array (e.g. String array), items in the array are initialized with null.
See below program and its output.
public class PrimitiveArray
{
public static void main(String[] args)
{
int[] intArray = new int[10];
boolean[] booleanArray = new boolean[10];
String[] stringArray = new String[10];
System.out.println("intArray[3] = " + intArray[3]);
System.out.println("booleanArray[3] = " + booleanArray[3]);
System.out.println("stringArray[3] = " + stringArray[3]);
}
}
Output is:
intArray[3] = 0
booleanArray[3] = false
stringArray[3] = null
I have two questions:
First:
I have a function which returns a HashMap. To read the returned value, I write it like this:
HashMap<Integer,String> hs=my_func2();
I do the same if the function returns a HashSet.
HashSet<Integer> hs=my_func();
I wanted to know if in this way the returned value is copied into hs, or I should write a deep copy for it or I should write it like this:
HashSet hs=new HashSet(my_func());
HashMap hm=new HashMap(my_func2());
Second quesion:
I make a matrix by calling make_matrix_funciton. matrix woule be a 2-dimensional array containing:
[0 1 1
0 0 0
0 0 0]
Then I give this matrix to sort_vec, and in this function the elements of matrix change. I think java is not pointer based, so when I come out of sort_vec, matrix should be as it had been. But, it has changed! It is
[0 0 0
0 0 0
1 1 0]
which shows the changes that had been applied to it inside the sort_vec function. Is it normal and if yes, what should I do to prevent it. The code below is compilable.
public static void main(String args[]) {
int matrix[][]=new int[3][3];
matrix=make_matrix("011000000");
int indexes[]={2,1,0};
int[][] mat=sort_vec(3,matrix,indexes);
}
private static int[][] sort_vec(int motifsize,int [][]mat,int[] indexes)
{
int[] main_index={0,1,2};
int l=indexes.length;
for (Integer i=0;i<l;i++)
if(indexes[i]!=main_index[i])
{
int j=indexes[i];
int k=main_index[i+1];
for(;k<l;k++)
if(indexes[k]==main_index[i])
break;
indexes[k]=j;
mat=exchange(motifsize,mat,j,main_index[i]);
}
return mat;
}
private static int[][] exchange(int motifsize,int [][]matrix,int x,int y)
{
int temp;
for(int i=0;i<motifsize;i++)
{
temp=matrix[i][x];
matrix[i][x]=matrix[i][y];
matrix[i][y]=temp;
}
for(int i=0;i<motifsize;i++)
{
temp=matrix[x][i];
matrix[x][i]=matrix[y][i];
matrix[y][i]=temp;
}
return matrix;
}
private static int[][] make_matrix(String id)
{
int matrix[][]=new int[3][3];
int c=0;
for(int x=0;x<3;x++)
for(int y=0;y<3;y++)
{
if(id.charAt(c)=='1' || id.charAt(c)=='5')
matrix[x][y]=1;
c++;
}
return matrix;
}
Java always passes Objects by reference, so if you return a HashMap-Object from a function, the reference will be passed to the hs variable in your example. Passing the HashSet to the constructor of a new HashSet instance will not work. It will create a new HashSet with the same object references as in the original one. If you modify one of these objects, the change will appear on all other reference points, too.
If you want to totally detach the copy, you will need your own method for deep copying because in the JavaDoc for the clone() method it says:
Returns a shallow copy of this HashSet instance: the elements themselves are not cloned.
The same goes for arrays. Every array is an object, so if you modify an element, it will be modified for all references to this array. To create a deferred copy, use System.arrayCopy
You are misunderstanding how Java's references work.
In the first part, your object will be a reference to a HashMap - i.e., whatever object you've returned from the function
In the second part, you are passing a reference to an int[][], it is not pass by value when it's an array of primitives. Thus, your function will modify the array. If you want a function that does not modify the input array, you need to copy what is passed in to the function or you will need to copy the array before you pass it to your function.
The behavior in Java sorting routines is that they modify the original array.
In sum, there is no way to 'pass by value' an object or array in Java. If you want this behavior, you have to clone (e.g., copy) the object manually or using #user3001's suggestion
Once you figure this out, you may want to read this as well: http://javadude.com/articles/passbyvalue.htm
ArrayList<yellowPage> ob1 = new ArrayList<yellowPage>();
yellowPage thing = new yellowPage(100,100);
thing.calc(i,y,s3);
ob1.add(thing);
I stored some data in thing. How can I retrieve the value stored in ob1.thing?
If you know the index, you can do yellowPage
yellowPage yp = ob1.get(index);
Otherwise you need to iterate over the list.
Iterator<yellowPate> iter = ob1.iterator();
while(iter.hasNext())
{
yellowPage yp = iter.next();
yp.whateverYouwantGet();
}
Note: I just typed code here, there may be syntax errors.
int x=5;
int info=ob1.get(x).getInfo();
The above example will get whatever information you wanted from your yellow pages class (by using a getter method) at the 6th index (because 0 counts) of your array list ob1. This example assumes you want an integer from the yellow page. You will have to create a getter method and change the x to the index of the yellow page you want to retrieve information from.
An example getter method (which you should put in your yellow pages class) could look like this:
public int getInfo() { return z; }
In the above case z may be an instance variable in your yellow pages class, containing the information you're looking for. You will most probably have to change this to suit your own situation.
If you wanted to get information from all yellow pages stored in the array list then you will need to iterate through it as Chrandra Sekhar suggested
Use an Iterator object to do this.
ArrayList<yellowPage> ob1 = new ArrayList<yellowPage>();
yellowPage thing = new yellowPage(100,100);
thing.calc(i,y,s3);
ob1.add(thing);
yelloPage retrievedThing = null;
Iterator<yelloPage> i = ob1.iterator();
if(i.hasNext()){
retrievedThing = i.next();
}
You could have the data stored in thing (horribly named variable) simply returned from the calc method. That way you don't need to maintain state for prior calculations in subsequent calls. Otherwise you just need a getter type method on the YellowPage class.
public class YellowPage {
private int result;
public void calc(...) {
result = ...
}
public int getResult() {
return result;
}
}
Print the list and override toString method.
public String toString()
{
return (""+ a+b); //Here a and b are int fields declared in class
}
System.out.print(ob1);
Class ArrayList<E>
Syntax
ArrayList<Integer> list = new ArrayList<Integer>();
You replace "Integer" with the class that the list is of.
An application can increase the capacity of an ArrayList instance before adding a large number of elements using the ensureCapacity operation. This may reduce the amount of incremental reallocation.
E represents an Element, which could be any class.
ensureCapacity is used to ensure that the list has enough capacity to take in the new elements. It's called internally every time you add a new item to the list. As the name suggests, ArrayList uses an Array to store the items. So when the array is initialized, it's given an arbitrary length, say 10. Now once you've added 10 items, if you go to add the 11th item, it'll crash because it exceeds the arrays capacity. Hence, ensureCapacity is called (internally) to ensure that there's enough space. So if you were adding the 11th element, the array size might be, say, doubled, to 20.