In java, I can initialize an array with predefined content either by :
int[] myArr = new int[]{1,2,3};
Or by :
int[] myArr = {1,2,3};
Essentially, is there any difference between these two ways ? Are they completely identical in Java ? Which way is better and why?
In your case there is no difference.
There will be a difference when you are not assigning your array to variable and doing inline creation.
for example, conside there is method, which takes an array as argument.
private void someX(int[] param){
// do something
}
Your case:
someX(myArr); // using some declared array .I.e your case
Now see the difference while calling it in other cases.
someX(new int[] {1,2,3}); // yes, compiler satisfied.
someX({1,2,3}); //Error. Sorry boss, I don't know the type of array
is there any difference between these two ways ? Are they completely identical in Java ?
No there is no difference. Both of them will create an array of length 3 with the given values.
The 2nd one is just a shorthand of creating an array where you declare it. However, you can't use the 2nd way of creating an array, at any other place than the declaration, where the type of array is inferred from the declared type of array reference.
No, the first and second are the same. The second is just syntactic sugar. Your end result is the same.
int[] myArr = new int[]{1,2,3};
Here it means you are initializing the three variable which will create the length of array 3
int[] myArr = {1,2,3};
Here it means you are initializing the three variable which will by default create the length of array 3
Both ways generate exactly the same result. Both are arrays of length 3 with predefined values. The second one is just shorter. The second method of declaring an array is better if you think that you need less time to write that code.
In the case you need to use that array to directly pass it to a method you should use the first one:
//Correct
someMethod(new int[]{1,2,3});
//Incorrect
someMethod({1,2,3});
But if your goal is only to declare and initialize the array in a variable either ways are correct:
int[] myArr = new int[]{1,2,3}; //Correct
int[] myArr = {1,2,3}; //Also Correct
Related
I have a float[] and i would like to get a list with the same elements. I could do the ugly thing of adding them one by one but i wanted to use the Arrays.asList method. There is a problem though. This works:
List<Integer> list = Arrays.asList(1,2,3,4,5);
But this does not.
int[] ints = new int[] {1,2,3,4,5};
List<Integer> list = Arrays.asList(ints);
The asList method accepts a varargs parameter which to the extends of my knowledge is a "shorthand" for an array.
Questions:
Why does the second piece of code returns a List<int[]> but not List<int>.
Is there a way to correct it?
Why doesn't autoboxing work here; i.e. int[] to Integer[]?
There's no such thing as a List<int> in Java - generics don't support primitives.
Autoboxing only happens for a single element, not for arrays of primitives.
As for how to correct it - there are various libraries with oodles of methods for doing things like this. There's no way round this, and I don't think there's anything to make it easier within the JDK. Some will wrap a primitive array in a list of the wrapper type (so that boxing happens on access), others will iterate through the original array to create an independent copy, boxing as they go. Make sure you know which you're using.
(EDIT: I'd been assuming that the starting point of an int[] was non-negotiable. If you can start with an Integer[] then you're well away :)
Just for one example of a helper library, and to plug Guava a bit, there's com.google.common.primitive.Ints.asList.
How about this?
Integer[] ints = new Integer[] {1,2,3,4,5};
List<Integer> list = Arrays.asList(ints);
Because java arrays are objects and Arrays.asList() treats your int array as a single argument in the varargs list.
Enter Java 8, and you can do following to collect in a boxed Array:
Integer[] boxedInts = IntStream.of(ints).boxed().toArray(Integer[]::new);
Or this to collect in a boxed List
List<Integer> boxedInts = IntStream.of(ints).boxed().collect(Collectors.toList());
However, this only works for int[], long[], and double[]. This will not work for byte[].
Note that Arrays.stream(ints) and IntStream.of(ints) are equivalent. So earlier two examples can also be rewritten as:
Integer[] boxedIntArray = Arrays.stream(ints).boxed().toArray(Integer[]::new);
List<Integer> boxedIntList = Arrays.stream(ints).boxed().collect(Collectors.toList());
This last form could be favored as it omits a primitive specific subtype of Stream. However, internally it is still a bunch of overloaded's which in this case still create a IntStream internally.
The problem is not with Arrays.asList(). The problem is that you expect autoboxing to work on an array - and it doesn't. In the first case, the compiler autoboxes the individual ints before it looks at what they're used for. In the second case, you first put them into an int array (no autoboxing necessary) and then pass that to Arrays.asList() (not autoboxing possible).
Arrays.asList(T... a) effectively takes a T[] which will match any array of true objects (subclasses of Object) as an array. The only thing that won't match like that is an array of primitives, since primitive types do not derive from Object. So an int[] is not an Object[].
What happens then is that the varags mechanism kicks in and treats it as if you had passed a single object, and creates a single element array of that type. So you pass an int[][] (here, T is int[]) and end up with a 1-element List<int[]> which is not what you want.
You still have some pretty good options though:
Guava's Int.asList(int[]) Adapter
If your project already uses guava, it's as simple as using the adapter Guava provides: Int.asList(). There is a similar adapter for each primitive type in the associated class, e.g., Booleans for boolean, etc.
int foo[] = {1,2,3,4,5};
Iterable<Integer> fooBar = Ints.asList(foo);
for(Integer i : fooBar) {
System.out.println(i);
}
The advantage of this approach is that it creates a thin wrapper around the existing array, so the creation of the wrapper is constant time (doesn't depend on the size of the array), and the storage required is only a small constant amount (less than 100 bytes) in addition to the underlying integer array.
The downside is that accessing each element requires a boxing operation of the underlying int, and setting requires unboxing. This may result in a large amount of transient memory allocation if you access the list heavily. If you access each object many times on average, it may be better to use an implementation that boxes the objects once and stores them as Integer. The solution below does that.
Java 8 IntStream
In Java 8, you can use the Arrays.stream(int[]) method to turn an int array into a Stream. Depending on your use case, you may be able to use the stream directly, e.g., to do something with each element with forEach(IntConsumer). In that case, this solution is very fast and doesn't incur any boxing or unboxing at all, and does not create any copy of the underlying array.
Alternately, if you really need a List<Integer>, you can use stream.boxed().collect(Collectors.toList()) as suggested here. The downside of that approach is that it fully boxes every element in the list, which might increase its memory footprint by nearly an order of magnitude, it create a new Object[] to hold all the boxed elements. If you subsequently use the list heavily and need Integer objects rather than ints, this may pay off, but it's something to be aware of.
Why doesn't autoboxing work here; i.e. int[] to Integer[]?
While autoboxing will convert an int to an Integer, it will not convert an int[] to an Integer[].
Why not?
The simple (but unsatisfying) answer is because that is what the JLS says. (You can check it if you like.)
The real answer is fundamental to what autoboxing is doing and why it is safe.
When you autobox 1 anywhere in your code, you get the same Integer object. This is not true for all int values (due to the limited size of the Integer autoboxing cache), but if you use equals to compare Integer objects you get the "right" answer.
Basically N == N is always true and new Integer(N).equals(new Integer(N)) is always true. Furthermore, these two things remain true ... assuming that you stick with Pure Java code.
Now consider this:
int[] x = new int[]{1};
int[] y = new int[]{1};
Are these equal? No! x == y is false and x.equals(y) is false! But why? Because:
y[0] = 2;
In other words, two arrays with the same type, size and content are always distinguishable because Java arrays are mutable.
The "promise" of autoboxing is that it is OK to do because the results are indistinguishable1. But, because all arrays are fundamentally distinguishable because of the definition of equals for arrays AND array mutability. So, if autoboxing of arrays of primitive types was permitted, it would undermine the "promise".
1 - ..... provided that you don't use == to test if autoboxed values are equal.
If you pass an int[] to Arrays.asList(), the list created will be List<int[]>, which is not vaild in java, not the correct List<Integer>.
I think you are expecting Arrays.asList() to auto-box your ints, which as you have seen, it won't.
It's not possible to convert int[] to Integer[], you have to copy values
int[] tab = new int[]{1, 2, 3, 4, 5};
List<Integer> list = ArraysHelper.asList(tab);
public static List<Integer> asList(int[] a) {
List<Integer> list = new ArrayList<Integer>();
for (int i = 0; i < a.length && list.add(a[i]); i++);
return list;
}
Alternatively, you can use IntList as the type and the IntLists factory from Eclipse Collections to create the collection directly from an array of int values. This removes the need for any boxing of int to Integer.
IntList intList1 = IntLists.mutable.with(1,2,3,4,5);
int[] ints = new int[] {1,2,3,4,5};
IntList intList2 = IntLists.mutable.with(ints);
Assert.assertEquals(intList1, intList2);
Eclipse Collections has support for mutable and immutable primitive List as well as Set, Bag, Stack and Map.
Note: I am a committer for Eclipse Collections.
int is a primitive type. Arrays.asList() accept generic type T which only works on reference types (object types), not on primitives. Since int[] as a whole is an object it can be added as a single element.
There is a better solution for this starting with Java 9:
List<Integer> list = List.of(null, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8);
I've just recently started with Java and have gotten to Arrays. from what I can tell there are two ways of creating Arrays.
The first method makes the most sense to me coming from a python background.
type[] ArrayName;
i.e.
int[] agesOfParticipants;
However a lot of resources online use a different method of creating arrays.
ArrayList<ArrayType> Name = new ArrayList<ArrayType>;
not only is this different but from what I can tell the term ArrayList is at least partially interchangeable depending on circumstance. For instance in this response ArrayList is replaced by class A, which is declared earlier.
A<String> obj=new A<String>();
Sorry if this is all basic stuff, but I can't find anywhere that really distinguishes between the two.
In java objects are created using new keyword
creating new Integer array with size 10, array consists of square brackets []
Integer[] array = new Integer[10];
System.out.println(Arrays.toString(array)); // print array values `[..]`
creating Integer object with value 10
Integer object = new Integer(10);
System.out.println(object); // print object value 10
creating List that only holds Integer values
List<Integer> list = new ArrayList<>();
list.add(object);
System.out.println(object); // prints list with values [10]
Angular brackets <> are Generics, that are used to define homogeneous type of objects (for example list of Integers only)
I have a float[] and i would like to get a list with the same elements. I could do the ugly thing of adding them one by one but i wanted to use the Arrays.asList method. There is a problem though. This works:
List<Integer> list = Arrays.asList(1,2,3,4,5);
But this does not.
int[] ints = new int[] {1,2,3,4,5};
List<Integer> list = Arrays.asList(ints);
The asList method accepts a varargs parameter which to the extends of my knowledge is a "shorthand" for an array.
Questions:
Why does the second piece of code returns a List<int[]> but not List<int>.
Is there a way to correct it?
Why doesn't autoboxing work here; i.e. int[] to Integer[]?
There's no such thing as a List<int> in Java - generics don't support primitives.
Autoboxing only happens for a single element, not for arrays of primitives.
As for how to correct it - there are various libraries with oodles of methods for doing things like this. There's no way round this, and I don't think there's anything to make it easier within the JDK. Some will wrap a primitive array in a list of the wrapper type (so that boxing happens on access), others will iterate through the original array to create an independent copy, boxing as they go. Make sure you know which you're using.
(EDIT: I'd been assuming that the starting point of an int[] was non-negotiable. If you can start with an Integer[] then you're well away :)
Just for one example of a helper library, and to plug Guava a bit, there's com.google.common.primitive.Ints.asList.
How about this?
Integer[] ints = new Integer[] {1,2,3,4,5};
List<Integer> list = Arrays.asList(ints);
Because java arrays are objects and Arrays.asList() treats your int array as a single argument in the varargs list.
Enter Java 8, and you can do following to collect in a boxed Array:
Integer[] boxedInts = IntStream.of(ints).boxed().toArray(Integer[]::new);
Or this to collect in a boxed List
List<Integer> boxedInts = IntStream.of(ints).boxed().collect(Collectors.toList());
However, this only works for int[], long[], and double[]. This will not work for byte[].
Note that Arrays.stream(ints) and IntStream.of(ints) are equivalent. So earlier two examples can also be rewritten as:
Integer[] boxedIntArray = Arrays.stream(ints).boxed().toArray(Integer[]::new);
List<Integer> boxedIntList = Arrays.stream(ints).boxed().collect(Collectors.toList());
This last form could be favored as it omits a primitive specific subtype of Stream. However, internally it is still a bunch of overloaded's which in this case still create a IntStream internally.
The problem is not with Arrays.asList(). The problem is that you expect autoboxing to work on an array - and it doesn't. In the first case, the compiler autoboxes the individual ints before it looks at what they're used for. In the second case, you first put them into an int array (no autoboxing necessary) and then pass that to Arrays.asList() (not autoboxing possible).
Arrays.asList(T... a) effectively takes a T[] which will match any array of true objects (subclasses of Object) as an array. The only thing that won't match like that is an array of primitives, since primitive types do not derive from Object. So an int[] is not an Object[].
What happens then is that the varags mechanism kicks in and treats it as if you had passed a single object, and creates a single element array of that type. So you pass an int[][] (here, T is int[]) and end up with a 1-element List<int[]> which is not what you want.
You still have some pretty good options though:
Guava's Int.asList(int[]) Adapter
If your project already uses guava, it's as simple as using the adapter Guava provides: Int.asList(). There is a similar adapter for each primitive type in the associated class, e.g., Booleans for boolean, etc.
int foo[] = {1,2,3,4,5};
Iterable<Integer> fooBar = Ints.asList(foo);
for(Integer i : fooBar) {
System.out.println(i);
}
The advantage of this approach is that it creates a thin wrapper around the existing array, so the creation of the wrapper is constant time (doesn't depend on the size of the array), and the storage required is only a small constant amount (less than 100 bytes) in addition to the underlying integer array.
The downside is that accessing each element requires a boxing operation of the underlying int, and setting requires unboxing. This may result in a large amount of transient memory allocation if you access the list heavily. If you access each object many times on average, it may be better to use an implementation that boxes the objects once and stores them as Integer. The solution below does that.
Java 8 IntStream
In Java 8, you can use the Arrays.stream(int[]) method to turn an int array into a Stream. Depending on your use case, you may be able to use the stream directly, e.g., to do something with each element with forEach(IntConsumer). In that case, this solution is very fast and doesn't incur any boxing or unboxing at all, and does not create any copy of the underlying array.
Alternately, if you really need a List<Integer>, you can use stream.boxed().collect(Collectors.toList()) as suggested here. The downside of that approach is that it fully boxes every element in the list, which might increase its memory footprint by nearly an order of magnitude, it create a new Object[] to hold all the boxed elements. If you subsequently use the list heavily and need Integer objects rather than ints, this may pay off, but it's something to be aware of.
Why doesn't autoboxing work here; i.e. int[] to Integer[]?
While autoboxing will convert an int to an Integer, it will not convert an int[] to an Integer[].
Why not?
The simple (but unsatisfying) answer is because that is what the JLS says. (You can check it if you like.)
The real answer is fundamental to what autoboxing is doing and why it is safe.
When you autobox 1 anywhere in your code, you get the same Integer object. This is not true for all int values (due to the limited size of the Integer autoboxing cache), but if you use equals to compare Integer objects you get the "right" answer.
Basically N == N is always true and new Integer(N).equals(new Integer(N)) is always true. Furthermore, these two things remain true ... assuming that you stick with Pure Java code.
Now consider this:
int[] x = new int[]{1};
int[] y = new int[]{1};
Are these equal? No! x == y is false and x.equals(y) is false! But why? Because:
y[0] = 2;
In other words, two arrays with the same type, size and content are always distinguishable because Java arrays are mutable.
The "promise" of autoboxing is that it is OK to do because the results are indistinguishable1. But, because all arrays are fundamentally distinguishable because of the definition of equals for arrays AND array mutability. So, if autoboxing of arrays of primitive types was permitted, it would undermine the "promise".
1 - ..... provided that you don't use == to test if autoboxed values are equal.
If you pass an int[] to Arrays.asList(), the list created will be List<int[]>, which is not vaild in java, not the correct List<Integer>.
I think you are expecting Arrays.asList() to auto-box your ints, which as you have seen, it won't.
It's not possible to convert int[] to Integer[], you have to copy values
int[] tab = new int[]{1, 2, 3, 4, 5};
List<Integer> list = ArraysHelper.asList(tab);
public static List<Integer> asList(int[] a) {
List<Integer> list = new ArrayList<Integer>();
for (int i = 0; i < a.length && list.add(a[i]); i++);
return list;
}
Alternatively, you can use IntList as the type and the IntLists factory from Eclipse Collections to create the collection directly from an array of int values. This removes the need for any boxing of int to Integer.
IntList intList1 = IntLists.mutable.with(1,2,3,4,5);
int[] ints = new int[] {1,2,3,4,5};
IntList intList2 = IntLists.mutable.with(ints);
Assert.assertEquals(intList1, intList2);
Eclipse Collections has support for mutable and immutable primitive List as well as Set, Bag, Stack and Map.
Note: I am a committer for Eclipse Collections.
int is a primitive type. Arrays.asList() accept generic type T which only works on reference types (object types), not on primitives. Since int[] as a whole is an object it can be added as a single element.
There is a better solution for this starting with Java 9:
List<Integer> list = List.of(null, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8);
Is there any way to check if an array has already been set to a length in Java?
In my case, I have a recursive method, and in the first iteration of the method, I want the array to have the length of a variable n. However, after the first recursion of the method, I don't want the array to be reassigned a new size.
Additionally, I don't know what the size should be until the first iteration of the method.
Thanks!
The array variable would be null until you assign an instance to it. Once an instance is assigned, it will have a fixed length. Therefore, a simple null check would suffice.
The Array Reference Variable Would be NULL until you assign to it.
You cannot create an Array Object without a lenght; if you want that, maybe you should create a ArrayList, and you can add objects to it without care about the size.
If you just want to see the lenght of your Array; after CREATE, do this:
public static void main (String[] args){
String[] x = new String[2]; // you cannot create here without a lenght, you MUST set
System.out.println(x.length);
}
OUTPUT: 2
Can you please let me know which version of java below flower bracket ({}) is introduced? what is concept name for this.
Object[] arg = {abc.getAbctNumber()};
here abc is object of java class and getAbcNumber() is a java method. I understand that arg object will be assigned with the value of return value of getAbcNumber() method.
{} is used to specify an array literal. So in your case you're specifying an array of objects with one element.
There is no such thing as a "flower bracket" in java. What you are seeing here, is an array being populated by a method.
You are creating an array with this syntax similar to:
int myarray[] = {1, 2, 3};
which will create an array of three ints. Your array will be created with an object.
This looks like a list initializer (not sure about the terminology, I don't do a lot of Java). In this case arg is an array of type Object and it's being initialized with a single value, which is the result of abc.getAbctNumber().
Consider an initializer with more than one value and it starts to become more clear:
Object[] arg = {
abc.getAbctNumber(),
abc.getSomeOtherNumber(),
abc.getSomethingElse()
};
That would initialize the arg array with three elements, the results of three different methods.
There is nothing called Flower bracket(at least I don't know about that). And in your Object[] arg = {abc.getAbctNumber()}; {} represent an array of one element and that element being an Object that is returned by method getAbctNumber()