In general to decalre the arrayList we can declare as below.
ArrayList Obj = new ArrayList();
This is correct only. But in our code we will not do like this.we do as below
List Obj = new ArrayList();
Why we will do like this? Why Upcasting ?
And While Upcasting we are restricting its functionality. Any specific reason we declare ArrayList or LinkedList like this?
Yes - because unless you need the specific functionality only exposed via the concrete type, it's generally a good idea to refer to the more general type. That way, if you ever decide to use a different implementation, you know that you're not tied to anything specific to the current implementation. You can later change the single statement:
List<String> list = new ArrayList<String>();
to (say)
List<String> list = new LinkedList<String>();
and know that everything will still compile. Of course the behaviour can change in terms of performance, thread safety etc - but that would be the case anyway.
You're also expressing that you don't need any members which are specific to ArrayList<String>, which can be important when reading the code later.
All of this is particularly relevant when it comes to picking the return type and parameter types of methods. The more specific you are about a return type, the less flexibility you have to change the implementation later. The more specific you are about a parameter type, the less flexibility you give your callers.
The point is that ArrayList and LinkedList are both used as lists. Our program logic shouldn't rely on how they store the list, just that they can be used to store items in an ordered way, which can be accessed based on that fact.
It is not upcasting. It is the right way to work. Actually when you are using List it does not matter how is it implemented. It is important that it is list. All method you are using are defined in interface. The same is correct for all other classes. Always try to use interface in the left side of assignment operator and in interfaces you define. In this case it will be easy to change ArrayList to LinkedList. Just change it in one place: replace new ArrayList by new LinkedList and you are done.
Moreover in most cases you even do not need List. if then you only iterate over the elements it is enough to use Collection. Because Collection interface is implemented by both lists and sets. So in future if you will prefer to store your elements in set you will again have to perform only one change.
The definitive answer can be found in
Joshua Bloch's Effective Java, Item 52: Refer to objects by their interfaces.
Its plain and simple - Polymorphism
You program to a more general or abstract class or interface type like List, and Java's polymorphic behavior will be able to automatically find out at runtime what actual definiton the implemented object belongs to. Here List is an interface.
Polymorphism helps in maintenance and refactoring without much hassle. If you know Polymorphism, you will know this.
ArrayList<String> list;
list = new ArrayList<String>(); //possible
list = new LinkedList<String>(); //not possible
LinkedList<String> list;
list = new ArrayList<String>(); //not possible
list = new LinkedList<String>(); //possible
but
List<String> list;
list = new ArrayList<String>(); //possible
list = new LinkedList<String>(); //possible
to increase this possibility u need to practice this actually :P
Example and use with below example :-
public static List<Integer> intList;
public static List<Integer> ArrayListDemo() {
intList = new ArrayList<>();
intList.add(100);
intList.add(200);
intList.add(500);
return intList;
}
public static List<Integer> LinkedListDemo() {
intList = new LinkedList<>();
intList.add(10);
intList.add(20);
intList.add(50);
return intList;
}
public static void main(String[] args) {
System.out.println(ArrayListDemo());
System.out.println(LinkedListDemo());
}
}
Related
I just wanted to clarify this question I had for a while for more efficient and 'correct' code.
I gave a class 'Student' with objects in an array list of objects. I have another class called Class which has an array list of references to the very same objects in the Student class.
Should I declare the 'Class' class as
ArrayList<Student> myStudents = new ArrayList<Student>();
or
ArrayList<Class> myStudents = new ArrayList<Class>();
Also another part of the question is I have seen people declare arrayLists as ArrayList<Student> myStudents = new ArrayList<>();
where the second half of the carrots are left empty. What exactly does the difference mean? Does this mean that the array list is not an object of any class?
Thank you so much for your time and help
Cheers
It depends on what you want to store in the list rather than where you are using it. If you're storing Student objects, then you'll use ArrayList<Student>().
The type omitted on the right side is called type inference (added in java 7), which means the type parameter on the right side will be inferred from the type of the assignment variable on the left. It helps to write the code in a cleaner way. For e.g.
Writing below is easier:
List<Some<Type<Another>>> var = new ArrayList<>();
than:
List<Some<Type<Another>>> var = new ArrayList<Some<Type<Another>>>();
Technically, neither.
You would want to do:
List<Student> myStudents = new ArrayList<>();
if you want to create an ArrayList with Student objects and
List<Class> myClasses = new ArrayList<>();
if you want to create an ArrayList with Class objects.
1) Note the variable names.
2) Note that you should always try to code to an interface (the left side is a List, not an ArrayList). This allows much greater flexibility since you're not dependent on the specific implementation of an ArrayList later on. This point is so powerful! You can write method signatures to accept objects of type List and then use an ArrayList, LinkedList or Stack or any class that implements a List. Depending on how you are using your ArrayList later, the Collection interface may be sufficient instead.
The diamond operator allows the compiler to infer the value of the type argument without having to type it all out. It's needed for backward compatibility for older Java versions.
As a general practice for performance optimization, you will also want to supply an initial capacity of an ArrayList if it's possible. So if you know that there are only 5 classes, then you would do:
List<Class> myClasses = new ArrayList<>(5);
What's the difference between using a typed vs. non-typedArrayList in Java?
For example, Using an ArrayList of CustomObject:
Typed:
ArrayList<CustomObject> typedArray = new ArrayList<>();
typedArray.add(new CustomObject);
or non-typed:
ArrayList<> nonTypedArray = new ArrayList<>();
nonTypedArray.add(new CustomObject);
Is there any situation where the latter is preferred? Is there any difference when the ArrayList is holding different datatypes, e.g. an ArrayList of String, Int, etc.?
In the Second Approach, it is not mandatory to add only CustomObject whereas it is in 1st Approach, otherwise, you will get Compilation Error.
ArrayList<CustomObject> typedArray = new ArrayList<>();
typedArray.add(new CustomObject());
This approach is generally preferable as there are no chances of having Class Cast Exception but in second approach there are high chances of that !!
JavaDocs explains it beautifully : Why to prefer Generics
Stronger type checks at compile time.
Elimination of casts.
Enabling programmers to implement generic algorithms.
It's never preferable to use the latter option. I don't think that is even possible. I think you meant:
ArrayList nonTypedArray = new ArrayList();
This syntax is left over from Java 1.4 and earlier. It still compiles for the purposes of backwards compatibility.
Generics was introduced in Java 1.5 which allowed you to specify the types between angled brackets.
It is always preferable to use generics because it is more type-safe.
That is, if you specify
ArrayList<String> typedArray = new ArrayList<String>();
Then you cannot accidentally add an integer to this array list; if you tried to add an integer, the program would not compile.
Of course, Generics ensures type safety at compile time. At runtime ArrayList<String> typedArray = new ArrayList<String>(); becomes ArrayList typedArray = new ArrayList();. This is to maintain backwards compatibility.
What's the difference between using a typed vs. non-typed ArrayList in
Java?
A typed/generic ArrayList is a collection of objects in which the "type" of the object is defined in angled brackets. Generics were introduced in Java 5 to create type-safe collections.
Before Generics the collection was called untyped/raw type collection because there was no way to specify the compiler the type of the collection being created.
The difference between both is to detect type-safe operations at compile time.
In both of your cases, you are adding object(s) of type 'CustomObject' to the ArrayList. There will be no issue while adding elements in the list, as both lists will consider them as typed objects.
Typed:
ArrayList<CustomObject> typedArray = new ArrayList<CustomObject>();
typedArray.add(new CustomObject);
Untyped:
ArrayList<> nonTypedArray = new ArrayList<>();
nonTypedArray.add(new CustomObject);
Is there any situation where the latter is preferred?
I don't think so. As generics are recommended to be used while creating a list to ensure type-safe operations.
Is there any difference when the ArrayList is holding different
datatypes, e.g. an ArrayList of String, Int, etc.?
Surely, there is a reasonable difference. For an untyped list, you will need to add type-cast while fetching elements from a list. As there is a possibility of the compiler throwing a ClassCastException at runtime due to different types of elements.
In runtime, there is absolutely no difference, however in compilation time, using type parameters can save you from a plethora of errors, so it is always preferable to use generics properly.
The only case where raw types are used reasonably is in legacy applications, but even in this case, you try to use typed parameters if you can.
The use of type simplifies your coding removing the need of casting and also stores your data efficiently
https://docs.oracle.com/javase/tutorial/java/generics/why.html
Yeah, I know this is an old post. But I wanted to share an instance where an untyped ArrayList is useful: when you're writing a function that supposed to act on arbitrary element types. For example, suppose you want to make a generic shuffle function that knows how to shuffle an array. Like so:
ArrayList<Die> diceRolls = getGetPossibleDiceRolls();
ArrayList<Card> cardDeck = getPossibleCards();
ArrayList<GirlToDate> blackbook = getBlackbook();
shuffle(diceRolls);
shuffle(cardDeck);
shuffle(blackbook);
.
.
void shuffle(ArrayList array) {
int size = array.size();
for (int i=0; i<size; ++i) {
int r = random.nextInt(size - i) + i;
// Swap
Object t = array.get(i);
array.set(i, array.get(r));
array.set(r, t);
}
}
Some might argue "yeah, but the proper way to do this is to create an interface or subclass of something like a Shuffleable type..." But really?
In Java 1.7 and upwards you should normally use the constructor like this:
ArrayList<MyObject> list = new ArrayList<>();
or else for a more general List object:
List<MyObject> list = new ArrayList<>();
Observe that you only specify the type <MyObject> once, not twice. This makes your code easier to maintain. The <> causes the constructor to return an ArrayList which is already typed to match the field/variable to which it is being assigned - so that no cast will be required in the calling code.
Do not use new ArrayList() as the constructor. This returns an untyped ArrayList which then has to be cast to a type to match the field/variable to which it is being assigned. This means unnecessary type checking and casting and so generally reduces performance.
This question already has answers here:
When to use LinkedList over ArrayList in Java?
(33 answers)
Closed 8 years ago.
When do I use List and when do I use ArrayList in Java? Please phrase in terms of practical situations where you would rather apply one over another. Thank you!
Edit : Also, LinkedList. Business situations where these are used, thanks, thats what's different about this question.
List is an interface. The other two are implementations of which.
You mostly want to code against interfaces. That is you wil do something like
List<String> strList = new ArrayList<String>();
Later on in the coding process, you may find that LinkedList has better performance for your scenario, so you just need to change one single place. Or maybe you don't care which concrete implementation is used, you just need "some sort of list". Then you could use an injected List implementation. Like this:
class ExampleClass{
private List<String> strList = null;
// We don't know and we don't care if Array or Linked List.
public ExampleClass( List<String> aList ){
strList = aList;
}
//...
}
For the differences between the implementations, see the links given in the comments as "possible duplicate of ..." or the JavaDoc.
***There's no difference between list implementations in both of your
examples. There's however a difference in a way you can further use
variable myList in your code.
When you define your list as:
List myList = new ArrayList(); you can only call methods and reference
members that belong to List class. If you define it as:
ArrayList myList = new ArrayList(); you'll be able to invoke ArrayList
specific methods and use ArrayList specific members in addition to
those inherited from List.
Nevertheless, when you call a method of a List class in the first
example, which was overridden in ArrayList, then method from ArrayList
will be called not the one in the List.
That's called polymorphism. You can read upon it.***
This answer was given by ATrubka here
I am iterating over a List of Lists. In my code listofuserdetailsperAccount is List<List>. I am considering the two methods below, please let me know which way is correct, more efficient and should be followed in java coding.
Way 1-----
for(int i=0;i<=listofuserdetailsperAccount.size();i++){
List list=(List) listofuserdetailsperAccount.get(0);
}
Way 2---
for(int i=0;i<=listofuserdetailsperAccount.size();i++){
List list= new ArrayList();
list=(List) listofuserdetailsperAccount.get(0);
}
I'll go with for each loop
for( List userDetailsPerAccount : listOfUserDetailsPerAccount ) {
//anything you want to do with userDetailsPerAccount
}
Way 1 is better approach than Way 2. In Way 2 List list= new ArrayList(); it will create a extra ArrayList object which does not have any use, which will cause memory consumption for sometime.
And it is also recommended use type specific List<E> so that you dont cast at runtime it will be typesafe.
for(List<E> list : listOfUserDetailsPerAccount){
...
}
In Java 5 and above use for-each.
You have a couple of problems here, with both proposed solutions.
Your List<List> listofuserdetailsperAccount object is not properly typed, as the inner List is a raw type, something to be avoided. Assuming your inner list holds UserDetail objects, your list of lists should be of type List<List<UserDetail>>.
You don't use the for-each loop syntax to iterate over a List, which is Iterable.
for(List<UserDetail> innerList : listofuserdetailsperAccount)
In Way 2 you initialize List to a new ArrayList (which is a raw type, it should be new ArrayList<>() if you needed this) and then promptly overwrite this value with the contents of your outer list. This means you ask Java to construct a new object that is then immediately cleaned up by the garbage collector, unused. This is wasteful and unnecessary.
In summary, you likely want to do:
List<List<UserDetail>> listofuserdetailsperAccount = // initialize your list
for(List<userDetail> innerList : listofuserdetailsperAccount) {
// do work with your innerList now
}
You commented (tidied up):
So while initializing I am doing something like this now, can you please let me know if this is correct:
List<List<String>> listofAccountdetailsLoggedinUser = null;
listofAccountdetailsLoggedinUser = new ArrayList<List<String>>();
OR I should not put it as null and directly create an object like this:
List<List<String>> listofAccountdetailsLoggedinUser =
new ArrayList<List<String>>();
That is the right track, but you do not need to initialize the variable to null. It doesn't hurt anything, since it doesn't construct an unnecessary object, but there's no reason to - you can declare and initialize the variable in one line, like you do in your second example.
Additionally, you don't need to specify the type of the ArrayList on the right hand side, simply use the diamond operator <>, like so:
List<List<String>> listofAccountdetailsLoggedinUser = new ArrayList<>();
Also, consider a shorter variable name, there's no need to use such a long one, and it's no fun to type :)
I always learn when we declare a collection we should do, Interface ob = new Class(), if i want to use for example a LinkedList i'll do List ob = new LinkedList(), but then i can't have access to all methods from LinkedList.. Isn't LinkedList ob = new LinkedList() 100% correct?
Isn't LinkedList ob = new LinkedList() 100% correct?
Well I'd suggest using the generic form, but sure - if you want to use functionality which is specific to LinkedList, you need to declare the variable accordingly.
You might want to check whether the Deque<E> or Queue<E> interfaces have what you want though. If they do, use those in-keeping with the idea of describing what you need rather than what implementation you'll use.
Yes,
LinkedList<...> items = new LinkedList<...>();
is perfectly correct if you know that items will depend on methods of LinkedList<T> that are not captured in the List<T> interface.
You should always try to keep the declaration at the highest level possible, meaning that you should stop at the highest level that provides all the functionality that you need: if List methods are not enough, you're perfectly fine with your LinkedList declaration.
If you actually have a need to use methods that are not on the List interface, there is certainly nothing wrong with using LinkedList's API. The general rule of programming to the List interface recognizes that 1) it's pretty rare to need those methods, and 2) in most people's experience, it's way more likely that I discover I need to sort the list and/or use a lot of random access, and decide to switch to an ArrayList, than it is I need one of the methods only LinkedList has.
It may be also that you could be programming to the Queue interface, if you find List isn't giving you what you need.
The rule "always code to interfaces" must be taken with some flexibility. What you are suggesting is fine, and as you came to the conclusion, the only option.
As a side note, coding to concrete classes like this is faster is most JVMs. Deciding whether the performance is worth breaking the rule is the hard thing to decide.
LinkedList is a generic. You should be doing:
LinkedList<String> linkedList = new LinkedList<String>();
(or whatever else you need to store in there instead of String)
Not exactly 100% correct.
A preferred way to declare any collection is to include the data type it's holding. So, for your example, it'd be LinkedList<Integer> ob = new LinkedList<Integer>();.
Nope.. This would be wrong, at the later stages if he wants to change his implementation from linked list to any other implementation of list type he will go wrong... So better to use the interface level declaration.
I won't always suggest you to use generics .....
Coz sometimes you may need to wrap different objects as here....
String str="a string";
boolean status=false;
LinkedList ll = new LinkedList();
ll.add(str);
ll.add(status);
In some situations like case of RMI, u can only send serialized data.....and suppose you want to send a class object(which is unserialized).......There you can wrap the members of the class(primitives) in a LinkedList and pass that object as a whole.......not worrying about the huge number of arguments......
Consider for eg:
public Class DataHouse
{
public int a;
public String str;
.
.
.
}
Now Somewhere u need to pass the objects....
You can do the following....
DataHouse dh =new DataHouse();
LinkedList ll = new LinkedList();
ll.add(dh.a);
ll.add(dh.str);
// Now the content is serialized and can pass it as a capsuled data......
you can still have access to LinkedList methods by using List, all you have to do is to type cast
for example
((LinkedList)ob).add()
The point of using generic List and not LinkedList is because in case you simply change the type of lists you are using (let's say double linked list) your program will still work Generics are to simplify your code to be more portable and more "changeable"
Actually it would be better if it would be parametrized as both are raw types.