What is the error Java ArrayLists - java

I am throughly convinced that this is snippet of code has an error. The Java from the ground up programming book says that there is no error. This is the code:
ArrayList temp = new ArrayList();
temp.add("35");
temp.add(35);
Isn't there an error with line 2? An arrayList cannot have a string and an integer within the same ArrayList correct? Please correct me if I am wrong, I have a test on this tomorrow. Thank you all in advance!

Yes, it is correct.
Since you haven't declared any type in ArrayList it allow all Objects.
Now your ArrayList as same as
ArrayList<Object> temp = new ArrayList<Object>();
And see below examples
ArrayList<String> temp = new ArrayList<String>();
temp.add("35");
temp.add(35); //compiler error, Only Strings please
see below example
ArrayList<Integer> temp = new ArrayList<Integer>();
temp.add("35");//compiler error, Only Integers please
temp.add(35);
And it's highly discouraged to use Raw types, Always prefer to use with specific type.
Now in first case ArrayList temp = new ArrayList();, when you return it returns an Object which is unkown type. It may be an Integer or a String, you need to check it manually after you got it back from List

ArrayList temp = new ArrayList(); There is no issue here. This is an ArrayList which will accept any data type since it is not defined specific data type (raw ArrayList).

it is correct because its a raw type means you can add any object.You can add anything that extends Object class
you can write temp.add(x); where x can be any thing String,int,long Date anything that extends Object
example
String x="";
int x1=1;
Date df=new Date();
temp.add(x);// will work
temp.add(x1);//will work
temp.add(df);// will work

yes your array list can hold both String and integer.
but array list only store objects String and Integer objects it doesnt support int primitive datatypes only objects inside arraylist
ArrayList<Object> arr=new ArrayList<>();
String s="35";
Integer in=35;
arr.add(in);
arr.add(s);`

It is correct. Since you haven't declare any type for list, it treats all the elements as Object class. Your definition is
ArrayList<Object> arr=new ArrayList<>();
for compiler. In this case 35 will be boxed to Integer and "35" will be a String. Both Integer and String are subclass of Object and there wan't be any compile time error.

In java there is something named as Generics which allows programmers to abstract over types.
Arraylist code internally uses it.So when you don't define any generic type the default type it takes is the Object class type.
And as String as well as Integer both are subclasses of Object class, so this operation is allowed according to OOPs.

Related

Java 2D Int Arraylist

I dont quite understand what is the problem with the second declaration.
// Compiles fine
ArrayList<ArrayList<String>> array = new ArrayList<ArrayList<String>>();
// error (Unexpected type, expected -reference ,found :int)
ArrayList<ArrayList<int>> intarray = new ArrayList<ArrayList<int>>();
ArrayList is an implementation of List<T>, your problem is that you are trying to create an arraylist of int, its impossible since int is not an object. using Integer will solve your problem.
ArrayList<ArrayList<Integer>> intarray = new ArrayList<ArrayList<Integer>>();
The way generics work is simple. The header of List looks a little like this:
public interface List<T>
Where T is some Object. However, int is not a subclass of Object. It is a primitive. So how do we get around this? We use Integer. Integer is the wrapper class for int. This allows us to use int values in a List, because when we add them, they get auto boxed into Integer.
Primitive types are actually scheduled for deprecation in Java 10. Taken from Wikipedia:
There is speculation of removing primitive data types, as well as moving towards 64-bit addressable arrays to support large data sets somewhere around 2018.
Just a Note on your Code
In Java, the convention is to have the declaration using the most generic type and the definition using the most specific concrete class. For example:
List myList;
// List is the interface type. This is as generic as we can go realistically.
myList = new ArrayList();
// This is a specific, concrete type.
This means that if you want to use another type of List, you won't need to change much of your code. You can just swap out the implementation.
Extra Reading
Read about Wrapper Classes.
Read about Auto Boxing and Unboxing.
Read about Primitive Types.
You can only make List of Objects. int is a primitive type.
Try use:
ArrayList<ArrayList<Integer>> intarray = new ArrayList<ArrayList<Integer>>();
You must create an ArrayList<Integer> not an ArrayList<int>
A class(Arraylist in your case) can be a type of a CLASS (Integer)
ArrayList does not except primitive types as an argument. It only accepts Object types you should use:
ArrayList<ArrayList<Integer>> intArray = new ArrayList<ArrayList<Integer>>();

ArrayList Generic without Type

recently I read a piece of code which seems weird to me. As we know, we need to initialize the generic type in collections when we need to use them. Also, we know Collections can contain Collections as their elements.
The code:
public class Solution {
public static void main(String args[]) {
ArrayList res = returnlist();
System.out.print(res.get(0));
}
public static ArrayList<ArrayList<Integer>> returnlist() {
ArrayList result = new ArrayList();
ArrayList<Integer> content = new ArrayList<Integer>();
content.add(1);
result.add(content);
return result;
}}
My question is
why can we use ArrayList result = new ArrayList(); to create an object, since we have not gave the collection the actual type of element.
why can we use result.add(content); to add a collection to a collection with collection "result" is just a plain collection. We have not defined it as a ArrayList of ArrayList
Java generic collections are not stored with a type to ensure backwards compatibility with pre J2SE 5.0. Type information is removed when added to a generic collection. This is called Type Erasure.
This means that a generic collection can be assigned to a non generic reference and objects in a generic typed collection can be placed in an non generic, nontyped collection.
All Java generics really does is make sure you can't add the wrong type to a generic list and saves you from doing an explicit cast on retrieval; even though it is still done implicitly.
Further to this
the Java section of this answer goes a little deeper into what I just said
this article also covers basically what you were asking in a more complete way
other things to watch out for with Type Erasure
Just adding up to provide summarized answer
Old way :
(A) ArrayList result = new ArrayList();
will create an Arraylist to hold "Object"
New Way :
ArrayList<Integer> content = new ArrayList<Integer>();
this represents an Arraylist which will hold "Integer" objects. This was introduced for compile-time type check purposes.
why ?
Consider the first case. Its input type is Object. We know that Object is the super class of all classes. We can pass in an Integer object, String object and so on. When fetching the data the developer has to perform proper type casting. Say if the developer initially thinks the code will accept Integer objects so he adds the following typecast while fetching the data
Integer integer=(Integer) content.get(0);
This is supposed to work. But if mistakenly he passes a String it will result in run-time error.
How it can be avoided ?
By introducing compile time checks
How it works ?
when we specify parameterized type only Integer objects can be added to the ArrayList collection. Else it will show error.
content.add(3); // will work
content.add("HARSHAD"); // error shown
If parameterized generic types are for type checking purposes how correct data can be retrieved from the list ?
The compiler implicitly performs type conversion. See the sample code
List<Integer> list=new ArrayList<Integer>();
list.add(1);
list.add(2);
Integer integer=list.get(0);
System.out.println(integer);
What the compiler actually does when you perform compilation ?
//perform type erasure
(B) List list=new ArrayList();
list.add(1);
list.add(2);
// the arraylist inturn accepts Object when you run the code
//add casting
Integer integer=(Integer)list.get(0);
Conclusion
If you see the codes (A) and (B) both are the same. Only difference is that in the second case the compiler implicitly does the same operation.
Finally to answer your question ...
ArrayList result = new ArrayList();
is allowed for backward compatibility purposes. Although this is not recommended.
Official link from Oracle docs explaining the same concept.
Generics were added to Java only in Java 5. Before that, when you use a collection, it always meant collection of objects. The old syntax is left as is for backward compatibility. So ArrayList result = new ArrayList() is actually creating an ArrayList<Object>. Since ArrayList is also an object, you can add content to the variable result.
why can we use ArrayList result = new ArrayList(); to create an object, since we have not give the collection the actual type of element.
Because java wants to it backward compatible. Generics is more of compiler feature for ensure type safety, collections can store any type of object at runtime.
Java compiler will not give you compiler error for this but it must have given you compiler warning that it is unsafe to use generic classes without type.
It may be a remnant from before generics came along to java (Java 4 or 5 I think).

A Java ArrayList Qusetion

Question: If you have a List and it has String objects, which declaration(s) of your List does not require that objects retrieved using the get method be cast to Strings, before calling a String method? List <Object> a = new ArrayList <Object>();
I. List<Object> a = new ArrayList <Object>();
II. List<String> a = new ArrayList <String>();
III.List a = new ArrayList();
I don't really understand this question. I think you must cast to a String to use it as a String, then it must be a declaration that does not return a String object as a String.
Here's how you should think about the answer: What does each of the following return?
I. and III. are the same thing. Both instances will return a java.lang.Object if you call get. You'll have to cast that to a java.lang.String in order to use it.
Only II. will return a String if you call get, because of the generic declaration.
2 will not require explicit casting. 1 and 3 are effectively the same thing.
The second one.
ArrayList<String> a = new ArrayList <String>();
This means that the arraylist can only hold string type variables. It says string in the pointy brackets. This is called generics and it allows the data you take out to be of the form you specify, in this case a String.
I. and III both are a list of Objects (and I. has a typo on the declaration, the correct class type is "Object"). You can store anything in them, including Strings, but as far as the compiler can tell... they're of type Object, so if you want to call a String method on an object you retrieved with the ArrayList.get(...) method you will have to cast the returned object to String.
II. is a list of Strings (the type of stored objects is specified by the generics part between <...>), the compiler knows the ArrayList will only store Strings, so the ArrayList.get() will return a String directly, without the need for a cast.
You can see an example of this exact thing in the Java Generics Tutorial.

ArrayList of ArrayList of ints in Java?

I am working on writing a sudoku solver and I want the grid to be stored as an arraylist of arraylist of ints...each spot will have an arraylist of ints of all possible numbers (or the definite value).
ArrayList<ArrayList<int>> sudoku_board = new ArrayList <ArrayList<int>>();
Java is throwing me an error saying "dimensions expected after token" on the ints.
Generic type parameters require reference types, rather than primitive types. Use
List<ArrayList<Integer>> sudoku_board = new ArrayList <ArrayList<Integer>>();
Also when coding to an interface use the interface as the reference type, in this case List. Everything that appears within the generics should remain as the implementation type due to the non co-variance of generics.
From #assylias comment, a more generic type of list is
List<List<Integer>> list = new ArrayList<List<Integer>>();
This will allow for List implementations types other than ArrayList to be added should refactoring be necessary later.
Use Integer wrapper class instead primitive.
ArrayList wont allow primitive as type argument.
List<ArrayList<Integer>> list= new ArrayList <ArrayList<Integer>>();
Arraylist is used to store objects not primitives, so change the signature accordingly.

ArrayList.toArray() method in Java

I am wondering why did they design the toArray method in ArrayList to take a input of an array in Java?
ArrayList<String> listArray = new ArrayList<String>();
listArray.add("Germany");
listArray.add("Holland");
listArray.add("Sweden");
String []strArray = new String[3];
String[] a = (String [])listArray.toArray(strArray);
To me it appears that, they dont need this input because the instance of the ArrayList itself has enough details to convert the data into an array.
My question is why do they still need the array to be passed in? Thanks.
Two reasons I can think of:
Erasure means that the generic parameters aren't available at runtime, so an ArrayList<String> doesn't know that it contains strings, it's just the raw type ArrayList. Thus all invocations of toArray() would have to return an Object[], which isn't strictly correct. You'd have to actually create a second array of String[] then iterate over the first, casting all of its parameters in turn to come out with the desired result type.
The way the method is defined means that you can pass in a reference to an existing array, and have this populated via the method. In some cases this is likely very convenient, rather than having a new array returned and then copying its values elsewhere.
In your code, the ArrayList can contain anything, not only Strings. You could rewrite the code to:
ArrayList<String> listArray = new ArrayList<String>();
listArray.add("Germany");
listArray.add("Holland");
listArray.add("Sweden");
String []strArray = new String[3];
String[] a = listArray.toArray(strArray);
However, in Java arrays contain their content type (String) at runtime, while generics are erased by the compiler, so there is still no way for the runtime system to know that it should create a String[] in your code.
You need it to get array types other than Object[]. listArray.toArray(new String[3]) shouldn't actually need a cast to String[], but it lets you write into arrays for specific types, rather than the (rather unsafe) approach of just casting Object[] to whatever your type is.
It is so that when you have an non-empty array you want object to be appended to from the arraylist conversion you can do that without having to create a new array, and do post processing of merging it, save resource and extra work.
Read the second paragraph of the javadoc: http://docs.oracle.com/javase/1.5.0/docs/api/java/util/ArrayList.html#toArray(T[])
ArrayList doesn't have enough information given that the "data" itself is stored in buckets of Object arrays. So, if you know "what" kind of items you have in your array list, you can achieve type safety by using this variant of the toArray method.
It is not compulsory to pass an Array as an argument to toArray(), you can directly call ArrayList.toArray()
As we know that Collection framework with generics works with the concept of Type Erasure. So the ArrayList becomes List of Object, so when you convert to array it will give an Object[] if you don't pass any argument.
Because the array into which the elements are to be copied should be specified to the JVM.
See this documentation

Categories