Java, How Iterate through Collection<? extends E>? - java

so I was given an interface where one method I need to implement gives me a Collection and wants me to "addAll" the data in the collection to my object. I'm still not sure what exactly a collection is. Is it an array list? I don't belive it is, but can I use a for each loop for each piece of data in the collection? Or is there another way to iterate through the collect accessing all of the value.

Iterating a Collection<? extends E> can be done with an Iterator (and you can get one with Collection.iterator() which can iterate the Collection) like
public static <E> void iterateWithIterator(Collection<? extends E> coll) {
Iterator<? extends E> iter = coll.iterator();
while (iter.hasNext()) {
E item = iter.next();
// do something with the item.
}
}
or, with Java 5+, with a for-each loop like
public static <E> void forEachIterate(Collection<? extends E> coll) {
for (E item : coll) {
// do something with the item.
}
}

From the documentation of Collection :
The root interface in the collection hierarchy. A collection
represents a group of objects, known as its elements. Some collections
allow duplicate elements and others do not. Some are ordered and
others unordered.
You can iterate over it with for or for-each loop or using an Iterator.
The most common type of collections are :
Set
List
Deque
SortedSet
Queue

Related

What algorithm is used for converting an ArrayList<T> to a LinkedHashSet<T> in JRE

I wanted to get a list of unique elements from a list with duplicate elements and the order of elements occurring in the list should be maintained.
To achieve this, I could have written an algorithm like:
private ArrayList<T> getUnique(ArrayList<T> list)
{
// maintain a hashmap of numbers and a uniqueList to be returned(ArrayList<T>)
// Add element in result list and the hashmap if the element isn't already present in the hashmap, else just add in the hashmap
HashMap<T, Boolean> map = new HashMap<>();
ArrayList<T> uniqueList = new ArrayList<>();
for (T t: list)
{
if (map.get(t) == null)
{
// t wasn't present so, adding them in map as well as in the list
map.put(t, true);
uniqueList.add(t);
}
}
return uniqueList;
}
This algorithm will take O(n) time with O(n) extra space (for HashMap).
Or simply, I could have used the below syntax:
Set<T> set = new LinkedHashSet<>(list);
The above syntax in Java is used for getting a set of unique elements from list with occurrence order of elements same as that of list.
Then convert this set in a list. (ArrayList<T> uniqueList = new ArrayList<>(set);)
I am assuming the time complexity here is also O(n). I wanted to know what algorithm Java uses for it.
I see the class is named LinkedHashSet, so I thought that they might be using some LinkedList concepts for achieving this, So I looked into the source code, and found these stuff:
In LinkedHashSet.java, the constructor looks like:
143: public LinkedHashSet(Collection<? extends T> c)
144: {
145: super(c);
146: }
here is the source.
So, I looked at the parent class constructor i.e. HashSet, I found:
public HashSet(Collection<? extends E> c) {
map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
addAll(c);
}
Next, I searched for addAll method, I found it in AbstractCollection class(which is the grandparent of HashSet class), the definition of the function is:
public boolean addAll(Collection<? extends E> c) {
boolean modified = false;
for (E e : c)
if (add(e))
modified = true;
return modified;
}
This is calling add which is like:
public boolean add(E e) {
throw new UnsupportedOperationException();
}
here.
I couldn't understand this. What algorithm do they use for this task?
For someone looking for the whole story
Base on the source code of LinkedHashSet, HashSet, LinkedHashMap.
When constructing a LinkedHashSet which extends HashSet with other collection(LinkedHashSet.java line 143),
public LinkedHashSet(Collection<? extends T> c)
{
super(c);
}
Which will call (HashSet.java line 136):
public HashSet(Collection<? extends T> c)
{
this(Math.max(2 * c.size(), HashMap.DEFAULT_CAPACITY));
addAll(c);
}
and then call (HashSet.java line 122):
public HashSet(int initialCapacity, float loadFactor)
{
map = init(initialCapacity, loadFactor);
}
Since the init method is overrided in LinkedHashSet
HashMap<T, String> init(int capacity, float load)
{
return new LinkedHashMap<T, String>(capacity, load);
}
The backing map is a LinkedHashMap.
According to java doc of LinkedHashMap
This class provides all of the optional Map operations, and permits null elements. Like HashMap, it provides constant-time performance for the basic operations (add, contains and remove), assuming the hash function disperses elements properly among the buckets. Performance is likely to be just slightly below that of HashMap, due to the added expense of maintaining the linked list, with one exception: Iteration over the collection-views of a LinkedHashMap requires time proportional to the size of the map, regardless of its capacity. Iteration over a HashMap is likely to be more expensive, requiring time proportional to its capacity.
And the add method of HashSet is
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
Hence the average time complexity is O(n) for the construction.
For the algorithm, I think you can read the code of LinkedHashMap for details.
Further reading How is the internal implementation of LinkedHashMap different from HashMap implementation?, HashSet vs LinkedHashSet
To answer your confusion, the add method is overridden in HashSet as follows:
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
Note that LinkedHashSet extends HashSet extends AbstractSet extends AbstractCollection.
In summary, the algorithm used is:
for (E e : c)
add(e);
which is O(N) for a LinkedHashSet since the average complexity of add for LinkedHashSet is O(1).
this is LinkedHashSet constructor :
public LinkedHashSet(Collection<? extends E> c) {
super(Math.max(2*c.size(), 11), .75f, true);
addAll(c);
}
this is addAll function from java.util.AbstractCollection:
public boolean addAll(Collection<? extends E> c) {
boolean modified = false;
for (E e : c)
if (add(e))
modified = true;
return modified;
}
this is add function from java.util.HashSet:
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
easy-peasy if you use Intellij to find the source of the function.

Sort Collection object by property in Java

If I want to sort the Collection below by a property called Order on the CSVInputHandler class, how do I do that? I tried the one a the very bottom with no luck. The error says The method sort(List<T>, Comparator<? super T>) in the type Collections is not applicable for the arguments (Collection<CSVInputHandler>, Comparator<CSVInputHandler>).
Object
Collection<CSVInputHandler> csvInputHandlers = new ArrayList<>(csvInputHandlerMap.values());
Tried
Comparator<CSVInputHandler> comparator = new Comparator<CSVInputHandler>() {
public int compare(CSVInputHandler c1, CSVInputHandler c2) {
return c1.Order < c2.Order;
}
};
Collections.sort(csvInputHandlers, comparator);
In order to sort a Collection (by using Collections.sort) you must explicitly convert it into a List
List<CSVInputHandler> myList = new ArrayList<>(csvInputHandlers);
Collections.sort(myList, comparator);
Remove .toArray() as that sort method accept only List types not Array
Collections.sort(csvInputHandlers, comparator);
Def
public static <T> void sort(List<T> list, Comparator<? super T> c) {
The Collections#sort method acts on Collections so the first method argument must be a Collection (i.e. any concrete subtype such as List, Set) while you are trying to as an array element as a first argument. It should be
Collections.sort(csvInputHandlers, comparator)
Collection :
The root interface in the collection hierarchy. A collection represents a group of objects, known as its elements. Some collections allow duplicate elements and others do not. Some are ordered and others unordered
source http://docs.oracle.com/javase/8/docs/api/java/util/Collection.html

Generic Collection

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

Java List.add() UnsupportedOperationException

I try to add objects to a List<String> instance but it throws an UnsupportedOperationException.
Does anyone know why?
My Java code:
String[] membersArray = request.getParameterValues('members');
List<String> membersList = Arrays.asList(membersArray);
for (String member : membersList) {
Person person = Dao.findByName(member);
List<String> seeAlso;
seeAlso = person.getSeeAlso();
if (!seeAlso.contains(groupDn)){
seeAlso.add(groupDn);
person.setSeeAlso(seeAlso);
}
}
The error message:
java.lang.UnsupportedOperationException
java.util.AbstractList.add(Unknown Source)
java.util.AbstractList.add(Unknown Source)
javax.servlet.http.HttpServlet.service(HttpServlet.java:641)
javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
Not every List implementation supports the add() method.
One common example is the List returned by Arrays.asList(): it is documented not to support any structural modification (i.e. removing or adding elements) (emphasis mine):
Returns a fixed-size list backed by the specified array.
Even if that's not the specific List you're trying to modify, the answer still applies to other List implementations that are either immutable or only allow some selected changes.
You can find out about this by reading the documentation of UnsupportedOperationException and List.add(), which documents this to be an "(optional operation)". The precise meaning of this phrase is explained at the top of the List documentation.
As a workaround you can create a copy of the list to a known-modifiable implementation like ArrayList:
seeAlso = new ArrayList<>(seeAlso);
Many of the List implementation support limited support to add/remove, and Arrays.asList(membersArray) is one of that. You need to insert the record in java.util.ArrayList or use the below approach to convert into ArrayList.
With the minimal change in your code, you can do below to convert a list to ArrayList. The first solution is having a minimum change in your solution, but the second one is more optimized, I guess.
String[] membersArray = request.getParameterValues('members');
ArrayList<String> membersList = new ArrayList<>(Arrays.asList(membersArray));
OR
String[] membersArray = request.getParameterValues('members');
ArrayList<String> membersList = Stream.of(membersArray).collect(Collectors.toCollection(ArrayList::new));
Form the Inheritance concept, If some perticular method is not available in the current class it will search for that method in super classes. If available it executes.
It executes AbstractList<E> class add() method which throws UnsupportedOperationException.
When you are converting from an Array to a Collection Obejct. i.e., array-based to collection-based API then it is going to provide you fixed-size collection object, because Array's behaviour is of Fixed size.
java.util.Arrays.asList( T... a )
Souce samples for conformation.
public class Arrays {
public static <T> List<T> asList(T... a) {
return new java.util.Arrays.ArrayList.ArrayList<>(a); // Arrays Inner Class ArrayList
}
//...
private static class ArrayList<E> extends AbstractList<E> implements RandomAccess, java.io.Serializable {
//...
}
}
public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {
public void add(int index, E element) {
throw new UnsupportedOperationException();
}
public E set(int index, E element) {
throw new UnsupportedOperationException();
}
public E remove(int index) {
throw new UnsupportedOperationException();
}
public Iterator<E> iterator() {
return new Itr();
}
private class Itr implements Iterator<E> {
//...
}
public ListIterator<E> listIterator() {
return listIterator(0);
}
private class ListItr extends Itr implements ListIterator<E> {
//...
}
}
Form the above Source you may observe that java.util.Arrays.ArrayList class doesn't #Override add(index, element), set(index, element), remove(index). So, From inheritance it executes super AbstractList<E> class add() function which throws UnsupportedOperationException.
As AbstractList<E> is an abstract class it provides the implementation to iterator() and listIterator(). So, that we can iterate over the list object.
List<String> list_of_Arrays = Arrays.asList(new String[] { "a", "b" ,"c"});
try {
list_of_Arrays.add("Yashwanth.M");
} catch(java.lang.UnsupportedOperationException e) {
System.out.println("List Interface executes AbstractList add() fucntion which throws UnsupportedOperationException.");
}
System.out.println("Arrays → List : " + list_of_Arrays);
Iterator<String> iterator = list_of_Arrays.iterator();
while (iterator.hasNext()) System.out.println("Iteration : " + iterator.next() );
ListIterator<String> listIterator = list_of_Arrays.listIterator();
while (listIterator.hasNext()) System.out.println("Forward iteration : " + listIterator.next() );
while(listIterator.hasPrevious()) System.out.println("Backward iteration : " + listIterator.previous());
You can even create Fixed-Size array form Collections class Collections.unmodifiableList(list);
Sample Source:
public class Collections {
public static <T> List<T> unmodifiableList(List<? extends T> list) {
return (list instanceof RandomAccess ?
new UnmodifiableRandomAccessList<>(list) :
new UnmodifiableList<>(list));
}
}
A Collection — sometimes called a container — is simply an object that groups multiple elements into a single unit. Collections are used to store, retrieve, manipulate, and communicate aggregate data.
#see also
HashMap vs HashTable
Object Serialization uses the Serializable and Externalizable interfaces
You will also get this exception if you attempt to add to a List<T> returned by Collections.singletonList(T o):
Returns an immutable list containing only the specified object. The returned list is serializable.
The JVM does not implement add() for Collections.singletonList
List membersList = Arrays.asList(membersArray);
returns immutable list, what you need to do is
new ArrayList<>(Arrays.asList(membersArray)); to make it mutable
You must initialize your List seeAlso :
List<String> seeAlso = new Vector<String>();
or
List<String> seeAlso = new ArrayList<String>();
You cannot modify a result from a LDAP query. Your problem is in this line:
seeAlso.add(groupDn);
The seeAlso list is unmodifiable.
instead of using add() we can use addall()
{ seeAlso.addall(groupDn); }
add adds a single item, while addAll adds each item from the collection one by one. In the end, both methods return true if the collection has been modified. In case of ArrayList this is trivial, because the collection is always modified, but other collections, such as Set, may return false if items being added are already there.

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