private static class ArrayList in java.util.Arrays - Why? - java

In java.util.Arrays there is a private static class called "ArrayList" defined.
It is only referred from Arrays.asList method.
What is the benifit of doing this?
Why is java.util.ArrayList not referred instead?
Code below:
/**
* #serial include
*/
private static class ArrayList<E> extends AbstractList<E>
implements RandomAccess, java.io.Serializable

Despite the fact that the private static ArrayList class shares the same name as java.util.ArrayList, they behave differently by design. Given that, there's no reason that the implementations should be one and the same.
Arrays#asList() returns a fixed-size list backed by the specified array. (Changes to the returned list "write through" to the array.) This method acts as bridge between array-based and collection-based APIs.

What is the benefit of doing this? Why is java.util.ArrayList not referred instead?
One reason is that the actual implementation class is not a public API detail. Doing this means that they can change the implementation class it in the future ... without any risk of breaking customer code.
Another reason for doing this is that this private class implements some operations differently to ArrayList. In particular operations that would involve changing the size of the list need to be implemented to throw an exception ... in order to conform to the behavior specified in the javadocs for the Arrays.asList(...) method.
In reality, the list returned by Arrays.asList(...) is a wrapper for the original array, and not a full-function, free-standing list. This is has advantages and disadvantages:
On the down-side, certain operations don't work; e.g. adding and removing elements.
On the up-side, creating a wrapper is a lot cheaper than creating a first-class list out of an array. (The latter entails copying the array contents into the list ... and that will be expensive for a large array.)
Also, there is the issue that changes to the original array are visible via the wrapper (and vice versa) ... which can be useful if that is what you need.
You asked this in a comment:
a) Why return non resizable list?
Because returning a regular resizable list entails copying the array contents at some point... which is expensive. (And if the implementation deferred the copying until a size-changing operation was performed, the relationship between the original array and the list would be really difficult to understand. Think about it ...)
b) Why not use Collections.unmodifiableList and pass the java.util.ArrayList object?
That doesn't achieve anything. You still have to copy the array contents to the ArrayList. The whole point of this "strange" behavioral spec is to avoid the need to copy.

Related

What are the differences between these two object declarations which uses an Interface and a Class in Java? [duplicate]

PMD would report a violation for:
ArrayList<Object> list = new ArrayList<Object>();
The violation was "Avoid using implementation types like 'ArrayList'; use the interface instead".
The following line would correct the violation:
List<Object> list = new ArrayList<Object>();
Why should the latter with List be used instead of ArrayList?
Using interfaces over concrete types is the key for good encapsulation and for loose coupling your code.
It's even a good idea to follow this practice when writing your own APIs. If you do, you'll find later that it's easier to add unit tests to your code (using Mocking techniques), and to change the underlying implementation if needed in the future.
Here's a good article on the subject.
Hope it helps!
This is preferred because you decouple your code from the implementation of the list. Using the interface lets you easily change the implementation, ArrayList in this case, to another list implementation without changing any of the rest of the code as long as it only uses methods defined in List.
In general I agree that decoupling interface from implementation is a good thing and will make your code easier to maintain.
There are, however, exceptions that you must consider. Accessing objects through interfaces adds an additional layer of indirection that will make your code slower.
For interest I ran an experiment that generated ten billion sequential accesses to a 1 million length ArrayList. On my 2.4Ghz MacBook, accessing the ArrayList through a List interface took 2.10 seconds on average, when declaring it of type ArrayList it took on average 1.67 seconds.
If you are working with large lists, deep inside an inner loop or frequently called function, then this is something to consider.
ArrayList and LinkedList are two implementations of a List, which is an ordered collection of items. Logic-wise it doesn't matter if you use an ArrayList or a LinkedList, so you shouldn't constrain the type to be that.
This contrasts with say, Collection and List, which are different things (List implies sorting, Collection does not).
Why should the latter with List be used instead of ArrayList?
It's a good practice : Program to interface rather than implementation
By replacing ArrayList with List, you can change List implementation in future as below depending on your business use case.
List<Object> list = new LinkedList<Object>();
/* Doubly-linked list implementation of the List and Deque interfaces.
Implements all optional list operations, and permits all elements (including null).*/
OR
List<Object> list = new CopyOnWriteArrayList<Object>();
/* A thread-safe variant of ArrayList in which all mutative operations
(add, set, and so on) are implemented by making a fresh copy of the underlying array.*/
OR
List<Object> list = new Stack<Object>();
/* The Stack class represents a last-in-first-out (LIFO) stack of objects.*/
OR
some other List specific implementation.
List interface defines contract and specific implementation of List can be changed. In this way, interface and implementation are loosely coupled.
Related SE question:
What does it mean to "program to an interface"?
Even for local variables, using the interface over the concrete class helps. You may end up calling a method that is outside the interface and then it is difficult to change the implementation of the List if necessary.
Also, it is best to use the least specific class or interface in a declaration. If element order does not matter, use a Collection instead of a List. That gives your code the maximum flexibility.
Properties of your classes/interfaces should be exposed through interfaces because it gives your classes a contract of behavior to use, regardless of the implementation.
However...
In local variable declarations, it makes little sense to do this:
public void someMethod() {
List theList = new ArrayList();
//do stuff with the list
}
If its a local variable, just use the type. It is still implicitly upcastable to its appropriate interface, and your methods should hopefully accept the interface types for its arguments, but for local variables, it makes total sense to use the implementation type as a container, just in case you do need the implementation-specific functionality.
In general for your line of code it does not make sense to bother with interfaces. But, if we are talking about APIs there is a really good reason. I got small class
class Counter {
static int sizeOf(List<?> items) {
return items.size();
}
}
In this case is usage of interface required. Because I want to count size of every possible implementation including my own custom. class MyList extends AbstractList<String>....
Interface is exposed to the end user. One class can implement multiple interface. User who have expose to specific interface have access to some specific behavior which are defined in that particular interface.
One interface also have multiple implementation. Based on the scenario system will work with different scenario (Implementation of the interface).
let me know if you need more explanation.
The interface often has better representation in the debugger view than the concrete class.

Why list of String has no forEach method?

I have problem with understand why String[] args variable has no forEach method? I can not find any information that this type is not Serializable or Collection because forEach methos implements Serializable.
For example, I have simple main Java class. If I want to use forEach method, I have to first import Arrays class and then on stream use forEach method like below:
import java.util.Arrays;
public class MyClass {
public static void main(String[] args) {
Arrays.stream(args).forEach(System.out::println);
}
}
Why it is not possible to make it just simple like this?
args.forEach(System.out::println);
Short answer: Arrays don't have a forEach method defined on them.
Longer answer: Because it doesn't need it. An array type (using [], not List<>) represents a low level structure in memory, more suited to low level optimisations rather than higher level functional-style code. The hardware of a machine much more closely resembles the imperative, stateful style from languages like C, rather than the functional stateless style from languages like Haskell. Because of this, when creating a lower level data structure like a basic array, it doesn't necessarily make sense to give it more advanced functionality. If you really want a forEach() method, trivially wrap it using Arrays.asList(), Arrays.stream(), or List.of() (depending on Java version).
The main method takes one parameter of type String[]. Which is an Array of Strings.
Lists and Arrays are two different things and only the former does provide a foreach method.
Not just String array, Array of any object or primitive types do not have this feature since arrays are the data stricture that is different from other collection implementations
The direct superclass of an array type is Object.
Every array type implements the interfaces Cloneable and java.io.Serializable.
https://docs.oracle.com/javase/specs/jls/se7/html/jls-10.html
Any array type doesn't define forEach.
Why?
It simply wasn't implemented and the authors apparently want to keep array types as fundamentally pure as possible.
I don't think this method would be superfluous; on the contrary, I am sure it would be very handy. It's not a trivial task, though. Think about primitive arrays and how you would implement, let's say, a boolean consumer. You would have to bound a plain JDK class BooleanConsumer to a fundamental JVM concept boolean[], or to grand the interface a special status, or to generate the interface on the fly.

Do Generic Nodes Need to be Part of a Generic List?

I am tasked with creating a class called Node that has instance variables: E data (Generic) and nextNode (singly linked-list implementation). To do that I created a class
public class Node<E>
and implemented all relevant methods.
I then have to create a List that has instance variables Node head and int size. In essence, the List contains a collection of Nodes. However, I am not sure how if I am supposed to define the class as a generic List or a regular List.
public class List<E>
vs
public class List
Which implementation makes more sense and why? Thanks to anyone who can help me understand the concept of generics.
When to use List<E>
If your list should only support adding elements of one type, use List<E>.
For example, you want to be able to create a list of Integers or a list of Doubles, but not a list that mixes the two.
Then you can support an add and remove interface that uses the generic type E in order to enforce the fact that only items of that type and no others can be added.
When to use List
If your list should support adding items of many different types, use List.
For example, if you want to be able to add a Node<Integer>, a Node<Scanner>, and a Node<Double>.
That way you can allow the programmer to add Nodes of any type they wish, because the list has no type parameter.
Warning
The above holds if you are writing your own List class (which the question makes it sound like you are). If you are using the built in java.util.List class, then you should never use it without a type parameter.

Why we should use Interface, instead of concrete types?

When using collections in Java, we are advised to use Interface instead of concrete types.
Like: List<Object> list = new ArrayList<Object>();
But, using ArrayList<Object> list = new ArrayList<Object>(); will also does the same job, right?
Yes, but if you later change your mind and use a LinkedList You have to change much more in your code.
That is the Polymorphism which is the core concept of OOP.
It means ‘a state of having many shapes’ or ‘the capacity to take on different forms’. When applied to OOP , it describes a language’s ability to process objects of various types and classes through a single, uniform interface.
List is a Uniform interface and its Different implementations are like ArrayList ,LinkedList.....etc
Prefer to read :What does it mean to program to a interface?
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.
Also the first has the advantage that the implementation of the List can change (to a LinkedList for example), without affecting the rest of the code. This is will be difficult to do with an ArrayList, not only because you will need to change ArrayList to LinkedList everywhere, but also because you may have used ArrayList specific methods.
There's a useful principle: for declared types, use the loosest (vaguest) interface possible (and List is 'looser' than ArrayList).
In practice, this means if you only need to access methods declared in List<Object> on your list instance (which is actually an ArrayList), then declare it as List<Object>. This means you can change your mind on the exact type of list later and you only need to change the line that actually instantiates the ArrayList (or LinkedList or whatever you choose).
This has implications for method signature too: if you were passing around an ArrayList instead of a List, and then changed your mind about it being an ArrayList, you have to go and edit lots of method signatures.
Please read up on Polymorphism if you'd like to know more.
Tangentially related is the Liskov Substitution Principle:
What is the Liskov Substitution Principle?
Interfaces or should I say base calsses are used to generalize things and problems at hand. So when you implement an interface you can always get the specific objects.
For example:
From Animal interface or super class you can always derive specific interfaces or calsses like Lion, but not the other way, becaus its true that a Lion is an animal but several other animals cannot be derived from Lion. Thats why it is advised to make things general and hence use interfaces.
Same applies in your case. You can always get ArrayList and other implementations from a List.
Say you have a class with the following method
public ArrayList<T> foo (ArrayList<T> someInput) {
//Do some operations on someInput here...
return someOutput;
}
Now, what happens if you change the program so that it uses LinkedList objects instead of ArrayList objects? You will get a compiler error wherever this method is called, and you would have to go through and refactor your code so that it accepts LinkedList objects.
If you had programmed to an interface and used a List instead:
public List<T> foo (List<T> someInput) {
//Do some operations on someInput here....
return someOutput;
}
If this was the case, no refactoring would be necessary as both the LinkedList and ArrayList classes implement List so there would be no compiler errors. This makes it incredibly flexible. It does not matter to the method what it takes in and what it returns, as long as the objects implement the List interface. This allows you to define behaviour without exposing any of the underlying implementation.

Why should the interface for a Java class be preferred?

PMD would report a violation for:
ArrayList<Object> list = new ArrayList<Object>();
The violation was "Avoid using implementation types like 'ArrayList'; use the interface instead".
The following line would correct the violation:
List<Object> list = new ArrayList<Object>();
Why should the latter with List be used instead of ArrayList?
Using interfaces over concrete types is the key for good encapsulation and for loose coupling your code.
It's even a good idea to follow this practice when writing your own APIs. If you do, you'll find later that it's easier to add unit tests to your code (using Mocking techniques), and to change the underlying implementation if needed in the future.
Here's a good article on the subject.
Hope it helps!
This is preferred because you decouple your code from the implementation of the list. Using the interface lets you easily change the implementation, ArrayList in this case, to another list implementation without changing any of the rest of the code as long as it only uses methods defined in List.
In general I agree that decoupling interface from implementation is a good thing and will make your code easier to maintain.
There are, however, exceptions that you must consider. Accessing objects through interfaces adds an additional layer of indirection that will make your code slower.
For interest I ran an experiment that generated ten billion sequential accesses to a 1 million length ArrayList. On my 2.4Ghz MacBook, accessing the ArrayList through a List interface took 2.10 seconds on average, when declaring it of type ArrayList it took on average 1.67 seconds.
If you are working with large lists, deep inside an inner loop or frequently called function, then this is something to consider.
ArrayList and LinkedList are two implementations of a List, which is an ordered collection of items. Logic-wise it doesn't matter if you use an ArrayList or a LinkedList, so you shouldn't constrain the type to be that.
This contrasts with say, Collection and List, which are different things (List implies sorting, Collection does not).
Why should the latter with List be used instead of ArrayList?
It's a good practice : Program to interface rather than implementation
By replacing ArrayList with List, you can change List implementation in future as below depending on your business use case.
List<Object> list = new LinkedList<Object>();
/* Doubly-linked list implementation of the List and Deque interfaces.
Implements all optional list operations, and permits all elements (including null).*/
OR
List<Object> list = new CopyOnWriteArrayList<Object>();
/* A thread-safe variant of ArrayList in which all mutative operations
(add, set, and so on) are implemented by making a fresh copy of the underlying array.*/
OR
List<Object> list = new Stack<Object>();
/* The Stack class represents a last-in-first-out (LIFO) stack of objects.*/
OR
some other List specific implementation.
List interface defines contract and specific implementation of List can be changed. In this way, interface and implementation are loosely coupled.
Related SE question:
What does it mean to "program to an interface"?
Even for local variables, using the interface over the concrete class helps. You may end up calling a method that is outside the interface and then it is difficult to change the implementation of the List if necessary.
Also, it is best to use the least specific class or interface in a declaration. If element order does not matter, use a Collection instead of a List. That gives your code the maximum flexibility.
Properties of your classes/interfaces should be exposed through interfaces because it gives your classes a contract of behavior to use, regardless of the implementation.
However...
In local variable declarations, it makes little sense to do this:
public void someMethod() {
List theList = new ArrayList();
//do stuff with the list
}
If its a local variable, just use the type. It is still implicitly upcastable to its appropriate interface, and your methods should hopefully accept the interface types for its arguments, but for local variables, it makes total sense to use the implementation type as a container, just in case you do need the implementation-specific functionality.
In general for your line of code it does not make sense to bother with interfaces. But, if we are talking about APIs there is a really good reason. I got small class
class Counter {
static int sizeOf(List<?> items) {
return items.size();
}
}
In this case is usage of interface required. Because I want to count size of every possible implementation including my own custom. class MyList extends AbstractList<String>....
Interface is exposed to the end user. One class can implement multiple interface. User who have expose to specific interface have access to some specific behavior which are defined in that particular interface.
One interface also have multiple implementation. Based on the scenario system will work with different scenario (Implementation of the interface).
let me know if you need more explanation.
The interface often has better representation in the debugger view than the concrete class.

Categories

Resources