Generic Collection - java

This is part of the Java (1.6) Collection interface:
public interface Collection<E> extends java.lang.Iterable<E> {
/* ... */
boolean containsAll(java.util.Collection<?> objects);
boolean addAll(java.util.Collection<? extends E> es);
boolean removeAll(java.util.Collection<?> objects);
boolean retainAll(java.util.Collection<?> objects);
/* ... */
}
Why does addAll have <? extends E> while removeAll has <?>

I did not know, I googled. I got this explaination here: http://www.ibm.com/developerworks/java/library/j-jtp01255/index.html
Copying the part:
One element of the generifed Collections API that is often confusing at first is the signatures of containsAll(), removeAll(), and retainAll(). You might expect the signatures for remove() and removeAll() to be:
interface Collection<E> {
public boolean remove(E e); // not really
public void removeAll(Collection<? extends E> c); // not really
}
But it is in fact:
interface Collection<E> {
public boolean remove(Object o);
public void removeAll(Collection<?> c);
}
Why is this? Again, the answer lies in backward compatibility. The interface contract of x.remove(o) means "if o is contained in x, remove it; otherwise, do nothing." If x is a generic collection, o does not have to be type-compatible with the type parameter of x. If removeAll() were generified to only be callable if its argument was type-compatible (Collection<? extends E>), then certain sequences of code that were legal before generics would become illegal, like this one:
// a collection of Integers
Collection c = new HashSet();
// a collection of Objects
Collection r = new HashSet();
c.removeAll(r);
If the above fragment were generified in the obvious way (making c a Collection<Integer> and r a Collection<Object>), then the code above would not compile if the signature of removeAll() required its argument to be a Collection<? extends E>, instead of being a no-op. One of the key goals of generifying the class libraries was to not break or change the semantics of existing code, so remove(), removeAll(), retainAll(), and containsAll() had to be defined with a weaker type constraint than they might have had they been redesigned from scratch for generics.

For any collection containing elements of type E, addAll must be able to deal with input collections not just of E, but all of its subclasses as well. Hence <? extends E>. Without this, you could not add all elements of a List<Integer> to a List<Number>, which would clearly not be right.*
For removal, the limits need not be so strictly set, and there is no harm in trying to remove elements of a collection of some totally unrelated type. E.g. you can have a collection of Numbers, about which you happen to know that it only contains Integers, so passing it to removeAll on a List<Integer> should work fine, and it would be stupid for the compiler to disallow this.
Note that according to the Javadoc, removeAll may optionally throw a ClassCastException, depending on implementation.
*The reason behind this is that in Java, generics are invariant. For more details, see e.g. this thread.

<?> is less restrictive than <? extends E>.
There is nothing wrong with removing an orange from a collection of apples; there are a lot of things wrong with adding an orange to a collection of apples.

When you add item to your collection you want to be sure that they do have a certain type.
When you remove them, only those in the collection are removed. Regardless of their type.

Java implements generics through erasure. These info are only for compilation time only. I guess the java collection designers did this to retain more ascendent compatibility with pre-generics java version.

when you add an object, it needs to be a subclass (or sub-subclass, etc.) of the main type. When you remove an object, it returns it as the type oc the collection. This is a good example of polymorphism in action.

A simple example to illustrate what has been said:
public class Test {
public static void main(String[] args) {
List<String> l = new ArrayList<String>();
System.out.println(l.remove(new Object())); //false
System.out.println(l.contains(new Object())); //false
// l.add(new Object()); // does not compile
}
}

Who cares what you try to remove ?
Adding is something else; we wouldn't want to end up with something strange in our collection.
as requested; an example:
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
public class Main {
private static class A {
}
public static void main(String[] args) {
Collection<A> collection_A = new ArrayList<A>();
Collection<String> collection = new ArrayList<String>();
// no problem to try and remove things that wouldn't be there in the first place; either way, they are gone afterwards
collection.removeAll(collection_A);
// we can't allow this; you would end up with things in your collection that don't belong there
collection.addAll(collection_A);
}
}

To remove restriction is not needed, so only <?>, but while adding we have to check and then add for type safety, so addAll is with restriction <? extends E>

With addAll you want to be able to add all elements that are a subtype of the generic type. This includes adding all elements of a List<String> to a List<Object>. We use ? extends E to accept any Collection that contains the type stored in this collection or any subtype.
boolean addAll(java.util.Collection<? extends E> es);
List<Number> numbers = ...;
List<Integer> integers = ...;
numbers.addAll(integers);//works
boolean addAll(java.util.Collection<E> es);
numbers.addAll(integers);//does not work E != Integer
we can't use ? as that would remove any security provided by generics.
boolean addAll(java.util.Collection<? extends E> es);
List<Number> numbers = ...;
List<Integer> integers = ...;
List<String> strings = ...;
numbers.addAll(integers);//works
numbers.addAll(strings);//error
boolean addAll(java.util.Collection<?> es);
numbers.addAll(strings);//works - now we have strings in our Number collection
We can use ? to remove objects since trying to remove a String from List of Numbers wont affect a List<Number>.
boolean removeAll(java.util.Collection<?> objects);
List<Objects> objects = ...;
List<Integer> integers = ...;
List<Number> numbers = ...;
numbers.removeAll(objects);//works
numbers.removeAll(integers);//works
boolean removeAll(java.util.Collection<? extends E> objects);
numbers.removeAll(objects);//does not work
numbers.removeAll(integers);//works
boolean removeAll(java.util.Collection<? super E> objects);
numbers.removeAll(objects);//works
numbers.removeAll(integers);//does not work

Related

How to assign List<? extends BaseClass> to List<BaseClass>

having
class BaseClass implements IData ();
class ChildClassA() extends BaseClass;
class ChildClassB() extends BaseClass;
since cannot do
List<BaseClass> aList = new ArrayList<ChildClassA>()
so there is a
List<? extends IData> aList
for pointint to either
ArrayList<ChildClassA>(),
or
ArrayList<ChildClassB>()
the aList is built by other routing at runtime, and that part of code has a function to take a List<IData> from the the aList
the question is if the List<? extends IData> aList is point to ArrayList<ChildClassA>() or ArrayList<ChildClassB>(),
can it do ListData<IData> outputList = (List<IData>) aList? something like below:
(seems it is working, but not sure if there is better way to assign the generics array other than casting.)
Edit: the output of the List<IData> outputList is for read only use (immutable), no insert/delete on it, it will only iterate the IData to react on what the IData really is.
List<? extends IData> aList = new ArrayList<ChildClassA>();
ListData<IData> outputList = (List<IData>)aList
List<? extends IData> aList = new ArrayList<ChildClassB>();
ListData<IData> outputList = (List<IData>)aList
tl;dr Use Collections#unmodifiableList:
List<IData> outputList = Collections.unmodifiableList(aList);
For more information on this topic, you might want to get familiar with the PECS principle.
It's not possible, because the two types are incompatible.
A List<BaseClass> is just what it is declared, a list of BaseClass objects. More precisely, it makes two guarantees:
objects retrieved from it are assignable to BaseClass
every object that is assignable to BaseClass can be added to it (and no other)
A List<? extends BaseClass> is a more loose declaration. Precisely, it simply does not make the second guarantee. However, not only the guarantee is gone, but it is now impossible to add items to it, since the exact generic type of the list is undefined. It might even change for the same list declaration (not the same list object) at runtime.
As a consequence, a List<? extends BaseClass> is not assignable to a List<BaseClass>, since the latter makes a guarantee the first is unable to fulfill.
Practically speaking, consider the following method:
public List<BaseClass> makeList() {
// TODO implement method
return null;
}
If someone implements this method, returning a List<? extends BaseClass>, a client using this method would be unable to add items to it, although its declaration indicates otherwise.
Because of that, such an assignment results in a compilation error.
To fix the example problem the loose declaration can be added to the method:
public List<? extends BaseClass> makeList() {
// TODO implement method
return null;
}
This will signal every client, that the list returned from this method is not meant for adding items to it.
Now let's get back to your use case. In my opinion the most appropriate fix is to the rephrase the function that
take[s] a List from the the aList.
As it seems it is currently declared as
public void useList(List<BaseClass> list);
but since it does not add items to the list, it should be declared as
public void useList(List<? extends BaseClass> list);
However, if that method is part of a currently unchangeable API, you can still do:
List<? extends BaseClass> list;
....
List<BaseClass> tmp = Collections.unmodifiableList(list);
useList(tmp);
No, it is unsafe.
After that cast it would be legit to add to the list that is supposed to contain only ChildClassA typed elements, element of the other child type ChildClassB type and vice-versa.
We can simply your code a bit to make it more obvious why this should not be allowed:
List<ChildClassA> aList = new ArrayList<ChildClassA>();
aList.add(a1);
aList.add(a2);
//...
List<IData> iDataList = (List<IData>) aList;
iDataList.add(b1);
iDataList.add(b2);
//...
for (ChildClassA a : aList) {
// a some point a is going to be assigned b1 or b2 and they results in cast
// exception.
}
Note that iDataList makes reference to the very same list object as aList.
If that cast was allowed then you would be able to add elements to aList that are not ChildClassA instances.
The best solution is on the details.
If the problem is that a third-party library requires a List<IData> typed reference and as long as it is only for reading you can use a unmodifiable proxy as returned by Collections.unmodifiableList:
import java.util.Collections;
//...
final List<ChildClassA> aList = new ArrayList<>();
//... add stuff to aList
final List<IData> readOnlyIDataList = Collections.unmodifiableList(aList);
//... read only access operations readOnlyIDataList

Understanding the Basics of Generics Sorting

There are a number of question on Stack Overflow about sorting Generics; however, I am interested in sorting Generics in the simplest way: nothing nested. The code I have below is an attempt to sort a generic set - or, list - of elements.
List<E> l = new LinkedList<>(arbSet);
Collections.sort(l);
arbSet is just a set of elements: Set<E> arbSet.
Clearly, this is problematic - it shouldn't work. To make sure I know this, Eclipse gives me the following for my attempt to call .sort:
Bound mismatch: The generic method sort(List < T >) of type Collections is not applicable for the arguments (List < E >). The inferred type E is not a valid substitute for the bounded parameter < T extends Comparable < ? super T >>
So, I do a bit of documentation consultation, looking at sort's specifications.
As a result, I attempt to ensure that sort knows E extends Comparable:
The first line now looking like:
List<E extends Comparable<? super E>> l = new LinkedSet<>(arbSet);
Now, Eclipse states :
Syntax error on token "extends", , expected
What am I missing? I feel like this is a very basic example and that I am just missing something "palm-to-face" esque. Just to simplify it even further, all arbSet elements are elements which implement the Comparable interface.
You can use Collections.sort() only if you provide a custom Comparator or if the elements you are trying to sort implement the Comparable interface. So it depends on what elements are stored in arbSet.
For example, if you wanted to create a method that accepts a set, and returns a list with the set elements sorted, you would do something like this:
static <E extends Comparable<E>> List<E> sortedListFrom(Set<E> set) {
List<E> l = new LinkedList<>(set);
Collections.sort(l);
return l;
}
Edit:
If you want to do this inside a constructor you have two options:
Declare the type E just before the constructor. Of course, this won't do much, since list is lost after the constructor finishes.
class Test {
<E extends Comparable<E>> Test(Set<E> arbSet) {
List<E> list = new LinkedList<>(arbSet);
Collections.sort(list);
System.out.println(list);
}
}
Declare the type E in the class, so you can store the result in a attribute.
class Test<E extends Comparable<E>> {
List<E> list;
Test(Set<E> arbSet) {
this.list = new ArrayList<>(arbSet);
Collections.sort(this.list);
System.out.println(this.list);
}
}

Java Generics: How does method inference work when wildcard is being used in the method parameters?

Supposedy i have the following:
class x {
public static void main(String [] args) {
List <?> a = new LinkedList<Object>();
List <? extends Object> b = new LinkedList<Object>();
List <? super Object> c = new LinkedList<Object>();
abc(a, "Hello"); // (1) Error
abc(b, "Hello"); // (2) Error
abc(c, "Hello"); // (3) ok
def(b); // (4) ok
// Showing inference at work
Integer[] a = {10, 20, 30}; // (5)
T is inferred to be ? extends Object
Method signature: ppp(? extends Object, ? extends Object[])
Method call signature: ppp(String, Integer[]);
ppp("Hello", a); // ok
}
static <T> void abc(List<T> a, T b) {}
static <T> void def(List<T> a) {}
static <T> void ppp(T t1, T[] t2){}
}
To begin with, look at clause 5 showing inference at work. Now clause 5 section is a working section.
If that is what it is, then why does clause (1) & (2) have errors?
From my view, all these 3 methods calling have the same inference generated since no actual type parameters is used on the abc method call.
method parameter <T> abc (List <T> a, T b>)
inferred <Object> abc (List <Object>, Object) // (4)
Please bear in mind, method abc() and def() is my method. Compiler doesn't know what i want to do with the List in this method. I might just print the list size or might not even do anything at all as shown above. So there is no get or set involved here.
CONTINUATION -->
This is getting very confusing for me.
class y {
public static void main(String [] args) {
List <Integer> a = new LinkedList<Integer>();
List <Object> b = new LinkedList<Object>();
ppp("Hello", new Integer(1)); // (20) ok
qqq("Hello", a); // (21) error
qqq("Hello", b); // (22) ok
}
static <T> void ppp(T t1, T t2) {}
static <T> void qqq(T t1, List <T> t2) {}
}
Note that clause 21 is the same as clause 20 except 2nd parameter is being made to be a List instead of Integer.
Clause 20 is ok cos' T is inferred to be Object.
Clause 22 is ok. Same reason as clause 20.
Clause 21 failed? T could also be inferred to be Object too - would work too?
The hard thing about the wildcard is to realize ? extends Foo does not mean "anything that extends Foo", but instead it means "some specific type that extends Foo". And since you are outside that definition, you have no way to know which specific sub-type of Foo it is.
Update:
As I said, it's complicated. Here are some comments on your code.
// a list of some specific type, and you don't know what type that is.
// it's a sub-type ob Object, yes, which means that you can do
// Object foo = a.get(0); , but the compiler has no way of knowing
// whether it's a String so you can't pass in a String
List <?> a = new LinkedList<Object>();
// same here. '?' and '? extends Object' are equivalent
List <? extends Object> b = new LinkedList<Object>();
// this is a list of Objects and superclasses thereof.
// since there are no superclasses of Object, this is equivalent to
// List<Object>. And through inheritance, a String is an Object, so
// you can pass it in.
List <? super Object> c = new LinkedList<Object>();
Update 2:
The problem here is that you are dealing with fixed, but unresolveable variables.
// you can pass in a List<String> and a String,
// but if you pass in a List<?>, the compiler has no idea what
// '?' is and just can't substitute 'String'.
// 'T' doesn't help you here, because 'T' can't match both
// '?' and 'String'.
static <T> void abc(List<T> a, T b) {}
// this works because 'T' substitutes '?' and doesn't have to worry
// about a 2nd parameter
static <T> void def(List<T> a) {}
Read this question, it might shed some light on the problem:
What is PECS (Producer Extends Consumer Super)?
You've set up a bit of a straw man by creating a LinkedList<Object> in each case. That can make it difficult to see the problem. What you have to remember is that when the compiler gets to those method invocations, it doesn't know that you created a LinkedList<Object>. It could be a LinkedList<Integer>, for example.
So let's look at your code with more interesting initializations:
List<Integer> integers = new LinkedList<Integer>();
List <?> a = integers;
List <? extends Object> b = integers;
List <? super Object> c = new LinkedList<Object>();
//INVALID. T maps to a type that could be Object OR anything else. "Hello"
//would only be type-assignable to T if T represented String, Object, CharSequence,
//Serializable, or Comparable
abc(a, "Hello");
//INVALID. T maps to a type that could be Object OR anything else. "Hello"
//would only be type-assignable to T if T represented String, Object, CharSequence,
//Serializable, or Comparable
abc(b, "Hello");
//VALID. T maps to an unknown super type of Object (which can only be Object itself)
//since String is already type-assignable to Object, it is of course guaranteed to be
//type-assignable to any of Object's super types.
abc(c, "Hello");
Integer i1 = integers.get(0);
Integer i2 = integers.get(1);
It doesn't take much to see that if the implementation of abc was this:
//a perfectly valid implementation
static <T> void abc(List<T> a, T b) {
a.add(b);
}
That you would get a ClassCastException when initializing i1.
From my view, all these 3 methods calling has the following inference generated since no actual type parameters is used on the abc static method call.
method parameter <T> abc (List <T> a, T b>)
inferred <Object> abc (List <Object>, Object) // (4)
This is categorically wrong. It is not inferred that T is Object in any of your examples, not even in the case of ? super Object. T is resolved to the capture of a, and unless you can assign a String to that capture (as is the case when it's ? super Object) you will have a type error.
Edit #1
Regarding your update (I've replaced your generic array with a List<T> since generic arrays needlessly cloud the issue):
// Showing inference at work
List<Integer> a = Arrays.asList(10, 20, 30); // (5)
T is inferred to be ? extends Object
Method signature: ppp(? extends Object, List<? extends Object>)
Method call signature: ppp(String, List<Integer>);
ppp("Hello", a); // ok
This is not correct. The crucial mistake you're making is here:
Method signature: ppp(? extends Object, List<? extends Object>)
This is not at all what the capture engine does or should translate your invocation into. It resolves T as <? extends Object> but as one specific capture of <? extends Object>. Let's call it capture-1-of<? extends Object>. Thus your method must be like this:
Method signature: ppp(capture-1-of<? extends Object>, List<capture-1-of<? extends Object>>)
This means that there is a binding between the two parameters...they must resolve to the same capture. In general it is very difficult to tell the compiler that two things are the same capture. In fact, even this is not a valid invocation of ppp (even though they are clearly the same capture):
List<? extends Integer> myList;
ppp(myList.get(0), myList);
One way we could invoke ppp is through a generic intermediary:
public static <T> void pppCaller(List<T> items) {
ppp(items.get(0), items);
}
pppCaller(myList);
The only sure-fire way you could invoke ppp with a wildcarded list would be to invoke it like this:
List<? extends Integer> myList = new ArrayList<Integer>();
ppp(null, myList);
That's because the null is the only thing that you can assign to anything. On the other hand, if you had this method:
private static <T> void qqq(T item1, T item2) {}
You could indeed invoke it like this:
List<? extends Integer> myList;
qqq(myList.get(0), myList.get(1));
Because in this case, the inference can generalize T to Object. Since List<? extends Integer> is not covariant with List<Object>, it cannot do the same for ppp().
However, what most people do to get around this is to relax their method signature. Instead, declare ppp as the following:
public static <T> ppp(T item, List<? super T> items) {
}
This follows the guidelines that Sean put in his post of "PECS"
If (your method) produces, use extends, if it consumes, use super.
Edit #2
Regarding your latest edit:
public static void main(String [] args) {
List <Integer> a = new LinkedList<Integer>();
qqq("Hello", a); // (21) error
}
static <T> void qqq(T t1, List <T> t2) {}
Object is not a valid inference for T. I think this is something fundamental you're missing, so I'll say it clear:
A List<Integer> is NOT type-assignable to List<Object>
Not at all. If it were, you could do something like this which obviously violates type safety:
List<Integer> myInts = new ArrayList<Integer>();
List<Object> myObjects = myInts; //doesn't compile!
myObjects.add("someString");
Integer firstInt = myInts.get(0); //ClassCastException!
So T cannot be inferred as Object, since it would require assigning a List<Integer> to a variable of type List<Object>.
A wildcard would then needed to induce subtype covariance
I'd rather say "try to simulate" since even after using wild-cards you can't get the same functionality you get for arrays.
Then the question is why clause (3) works and not clause(2) or (1)?
Consider the first declaration:
List <?> a = new LinkedList<Object>();
This declaration effectively says, I really don't know (or care) what kind of element the collection a contains. This effectively shuts you off from "mutating" the collection since you might end up adding elements of type which are not really compatible with a. You can have List<?> a = new ArrayList<String>() but you still won't be able to put anything in it. Basically, in case an add is allowed, the compiler can't guarantee the type safety of the collection.
List <? extends Object> b = new LinkedList<Object>();
Here you say b is a collection which contains elements which extend an Object. What kind of element, you don't know. This again as per the previous discussion doesn't allow you to add anything since you could end up compromising type safety.
List <? super Object> c = new LinkedList<Object>();
Here you say, c is a collection which contains elements of type Object and it's super-classes or in other words, at least an Object. Since each reference type in Java is assignment compatible with Object, it works in the third case.
Integer[] is a subtype of Object[], however List<Integer> is not a subtype of List<Object>. This is quite confusing; arrays are more primitive and should be avoided.
If a method parameter type is T[], it accepts all S[] where S is a subtype of T.
To do this with List, the type should be List<? extends T>. It accepts all List<S> where S is a subtype of T.
List<?> a means that a holds a specific type, which is unknown. Consider this more complete example:
List<Float> floats = new ArrayList<Float>();
List<?> a = floats; /* Alias "floats" as "a" */
abc(a, "Hello"); /* This won't compile... */
float f = floats.get(0); /* .. if it did, you'd get a ClassCastException */
static <T> abc(List<T> a, T b) {
a.add(b); /* Absolutely no problem here. */
}
List<? extends Object> means essentially the same thing as List<?>, and would cause the same error.
List<? super Object> means that the list holds a specific, but unknown super-type of Object, and the parameterized method can accept any object that is-a Object for the second parameter. While the method invocation is type-safe, attempting to assign an unsafe value to c will cause an error:
List<Number> numbers = new ArrayList<Number>();
List<? super Object> a = numbers; /* This won't compile... */
abc(a, "Hello");
Number n = numbers.get(0); /* ...if it did, you'd get a ClassCastException */

Collection in Java

Quick Question...
Can collections in Java hold more than one type? Or do they all have to be the same type?
thanks
Simple answer
Yes.
More detailed answer
You can either use generic collection, without <T> value, for example:
ArrayList a = new ArrayList();
a.add(2);
a.add("String");
Using collections without <T> is a bad habit and most IDEs / compilers give a warning here. You can circumvent it by using a collection of Object, i.e.:
ArrayList<Object> a = new ArrayList<Object>();
Or you can find some common interface or supertype that these element must have in, for example ArrayList<Number> - and you can store various objects that have common Number superclass, i.e. BigDecimal, BigInteger, Byte, Double, Float, Integer, Long, Short:
ArrayList<Number> a = new ArrayList<Number>();
a.add(2); // integer
a.add(42L); // long
a.add(123.45d); // double
System.out.println(a.toString()); // => [2, 42, 123.45]
Note that it essentially means that a elements are of Number class — i.e. you can't ask to execute subclass-specific methods (for example, Double#isInfinite(), which doesn't exist in Number superclass), although you can typecast in run-time if you somehow know it's safe to typecast:
a.get(2).isInfinite() // compile-time error
((Double) a.get(2)).isInfinite() // => false
((Double) a.get(1)).isInfinite() // run-time error (ClassCastException)
Run-time typecasting is also generally frowned upon, as it effectively circumvents proper compile-time type safety.
Also note that it's impossible to assign (or use) ArrayList<Number> in place of ArrayList<Integer> and vice-versa, i.e. this will fail to compile:
public void printNumbers(ArrayList<Number> list) {
list.forEach(System.out::println);
}
ArrayList<Integer> a = new ArrayList<Integer>();
printNumbers(a); // "incompatible types"
as well as this:
public void printIntegers(ArrayList<Integer> list) {
list.forEach(System.out::println);
}
ArrayList<Number> a = new ArrayList<Number>();
printIntegers(a); // "incompatible types"
To declare a variable to be able to accept both ArrayList<Number> or any of its subclasses, one can use ArrayList<? extends Number> or ArrayList<? super Number> syntax. extends is generally used when you're going to consume (i.e. read) from the object in your method, super is used when you're going to produce (i.e. write). Given that printout is consuming, it's safe to use extends:
public void printNumbers(ArrayList<? extends Number> list) {
list.forEach(System.out::println);
}
ArrayList<Integer> listInt = new ArrayList<Integer>();
printNumbers(listInt); // works
ArrayList<Double> listDbl = new ArrayList<Double>();
printNumbers(listDbl); // also works
There is a good answer in
Difference between <? super T> and <? extends T> in Java for more in-depth explanation.
If you want them to hold any more than one type, use Collection<Object>. However, you won't know what you're getting without doing some if (x instanceof MyType) calls, which are rather inefficient.
They have to be of the same Supertype. So if you have objects of type A, then a Collection<A> can store objects of type A and of every subtype of A.
If you want to allow arbitrary types, then use Collection<Object>, otherwise take the most general appropriate super-class.
However, you will then have to manually cast from the most general type (Object) to the specific type you have in mind. You can use the typeof operator to find out what the type is.
Every Collection classes can contains heterogeneous objects except TreeSet and TreeMap. Since TreeSet and TreeMap stores elements according to some sorting order. so, if objects are of different type it will not be able to sort it because comparison between the objects will not be possible for sorting.
Yes they can but they should not (that's why generics have been put in place since 5th version of jdk) in general store different types, as this is the straight way to errors.
Yes collections in java can hold more than one type as below. But it will throw an exception if done using the following way.
ArrayList al = new ArrayList();
al.add(1);
al.add("name");
al.add(1.2f);
Iterator itr =al.iterator();
while(itr.hasNext())
{
System.out.println(itr.next());
}
Hence it's better to mention the type that you're using. To get rid of the exception the above program can be modified as below.
ArrayList<Integer> al = new ArrayList<Integer>();
al.add(1);
al.add(2);
al.add(3);
Iterator itr =al.iterator();
while(itr.hasNext())
{
System.out.println(itr.next());
}
ArrayList<String> al1 = new ArrayList<String>();
al1.add("Words");
al1.add("Names");
al1.add("Characters");
Iterator itr1 =al1.iterator();
while(itr1.hasNext())
{
System.out.println(itr1.next());
}
You can also use more than these types.
Yes,
My mistake the correct code is this one and
ArrayList<Elements>()=new ArrayList();
or
ArrayList<E>()=new ArrayList();
should be the correct declaration if you want to use Generics in Collection.
class Test
{
public static void main(String[] args)
{
// For Generic class of List
ArrayList<E> arrL1 = new ArrayList<E>();
arrL1.add("stackoverflow");
arrL1.add(1);
Iterator itr1=list.iterator();
while(itr1.hasNext())
{
System.out.println(itr1.next());
}
// for Particular datatype in List
ArrayList<String> list=new ArrayList<String>(); // Creating arraylist
list.add("Ravi"); // Adding object in arraylist
list.add("Vijay");
list.add("Ravi");
list.add("Ajay");
// transversing the values
Iterator itr=list.iterator();
while(itr.hasNext())
{
System.out.println(itr.next());
}
}
}
Output 1
stackoverflow
1
Output 2
Ravi
Vijay
Ravi
Ajay
I believe you can also use Collection<?>.
Yes, you can have more than one datatype in ArrayList of Collection.
class Test
{
public static void main(String[] args)
{
// For Generic class of List
ArrayList<> arrL1 = new ArrayList<>();
arrL1.add("stackoverflow");
arrL1.add(1);
// for Particular datatype in List
ArrayList<String> list=new ArrayList<String>(); // Creating arraylist
list.add("Ravi"); // Adding object in arraylist
list.add("Vijay");
list.add("Ravi");
list.add("Ajay");
// transversing the values
Iterator itr=list.iterator();
while(itr.hasNext())
{
System.out.println(itr.next());
}
}
}
Output 1:
stackoverflow
1
Output 2:
Ravi
Vijay
Ravi
Ajay

Is there a fast concat method for linked list in Java?

How can I concat two linked lists in O(1) with Java via jdk1.6, google or apache commons collection or whatever? E.g. in the jdk there is only the addAll method which is O(n).
Another feature I miss is to concat two lists where each of them could be in inverse order. To illustrate this assume two lists a->b->c and e->f->g could merged into
a->b->c->e->f->g
a->b->c->g->f->e
c->b->a->e->f->g
c->b->a->g->f->e
Do you know of such a list implemenation or do I have to implement my own linked list? It would be also helpful to know how to tweak existing solutions (e.g. the jdk LinkedList has a lot of private methods only). These features seems to me very obvious, hopefully I am not missing something stupid.
As MicSim pointed out the question Merge two lists in constant time in Java is related but not a real duplicate!
Now the questions are:
is it possible with other collection libs?
how to concat the inverse?
If you are willing to settle for Iterable result, you can use google-collections Iterables.concat and Iterables.reverse
http://google-collections.googlecode.com/svn/trunk/javadoc/com/google/common/collect/Iterables.html
public static <T> Iterable<T> concat(Iterable<? extends T> a,
Iterable<? extends T> b)
public static <T> Iterable<T> concat(Iterable<? extends T> a,
Iterable<? extends T> b,
Iterable<? extends T> c)
public static <T> Iterable<T> concat(Iterable<? extends T> a,
Iterable<? extends T> b,
Iterable<? extends T> c,
Iterable<? extends T> d)
public static <T> Iterable<T> concat(Iterable<? extends T>... inputs)
public static <T> Iterable<T> concat(Iterable<? extends Iterable<? extends T>> inputs)
The only solution I see at the moment is to implement List, make a constructor like:
public EnhancedList (List l1, List l2)
and override all methods. In such solution it's actually not important whether you want to concat LinkedLists or any other lists.
I'd think this wouldn't be too difficult to write with any kind of base list construct since insertion in the middle or the end of a list in a Linked list is O(1).
Adapting the LinkedList to get O(1) concat in the jdk will work if:
the method entry() and the variables header and size and the inner class Entry would be protected
addAll would detect LinkedList and then doing sth. like:
JdkLinkedList secondList = (JdkLinkedList) secondColl;
int numNew = secondList.size();
if (numNew == 0) return false;
modCount++;
Entry<E> successor = (index == size ? header : entry(index));
Entry<E> predecessor = successor.previous;
// TODO LATER if reverse
// connect the last element of this list with the first element of the second list
// linked list is implemented as a 'cycle' => header.next == first element of second list
Entry<E> first = secondList.header.next;
predecessor.next = first;
first.previous = predecessor;
// append the last element of the second list with the rest of this list
Entry<E> last = secondList.header;
successor.previous = last;
last.next = successor;
For the concat I would suggest you do the following:
Make sure all of your parameters/variables are declared as List<...> not LinkedList<...>
Change the new LinkedList<...>(); to new ArrayList<...>();
profile the application
Change the new ArrayList<...> to new LinkedList<...>();
profile the application
Depending on your usage ArrayList can be significantly faster than LinkedList. Also looking at the profile data you can see how much of a performance hit you have by using addAll - if it isn't that large don't bother "fixing" it.
For some things your experiences with other languages will not hold true. You may find that addAll meets your requirements in Java.
If you were to write your own concatable list make sure it conforms to the List interface then change your code and re-profile it and make sure it is faster. If it isn't then throw it away and stick with the standard List types.
FastList from javolution is not an out-of-the-box solution but with the tail() and head() quite close to my favourite.
I think trove is the solution, although no convenient method exist for invert or addAll in O(1).

Categories

Resources