Easy way to convert Iterable to Collection - java

In my application I use 3rd party library (Spring Data for MongoDB to be exact).
Methods of this library return Iterable<T>, while the rest of my code expects Collection<T>.
Is there any utility method somewhere that will let me quickly convert one to the other? I would like to avoid creating a bunch of foreach loops in my code for such a simple thing.

In JDK 8+, without using any additional libs:
Iterator<T> source = ...;
List<T> target = new ArrayList<>();
source.forEachRemaining(target::add);
Edit: The above one is for Iterator. If you are dealing with Iterable,
iterable.forEach(target::add);

With Guava you can use Lists.newArrayList(Iterable) or Sets.newHashSet(Iterable), among other similar methods. This will of course copy all the elements in to memory. If that isn't acceptable, I think your code that works with these ought to take Iterable rather than Collection. Guava also happens to provide convenient methods for doing things you can do on a Collection using an Iterable (such as Iterables.isEmpty(Iterable) or Iterables.contains(Iterable, Object)), but the performance implications are more obvious.

Concise solution with Java 8 using java.util.stream:
public static <T> List<T> toList(final Iterable<T> iterable) {
return StreamSupport.stream(iterable.spliterator(), false)
.collect(Collectors.toList());
}
Since Java 16, you can use Stream.toList():
public static <T> List<T> toList(final Iterable<T> iterable) {
return StreamSupport.stream(iterable.spliterator(), false)
.toList();
}

You may write your own utility method for this as well:
public static <E> Collection<E> makeCollection(Iterable<E> iter) {
Collection<E> list = new ArrayList<E>();
for (E item : iter) {
list.add(item);
}
return list;
}

IteratorUtils from commons-collections may help (although they don't support generics in the latest stable version 3.2.1):
#SuppressWarnings("unchecked")
Collection<Type> list = IteratorUtils.toList(iterable.iterator());
Version 4.0 (which is in SNAPSHOT at this moment) supports generics and you can get rid of the #SuppressWarnings.
Update: Check IterableAsList from Cactoos.

When you get your Iterable from Spring Data you have a couple of additional alternatives.
You can override the method that returns the Iterable in the repository with a version that returns a List, Set or Streamable. This way Spring Data is doing the conversion for you.
You may do so in a super interface of your repositories so you don't have to repeat the override in all your repository interfaces.
If you happen to use Spring Data JPA this is already done for you in JpaRepository
You may do the conversion using the just mentioned Streamable yourself:
Iterable<X> iterable = repo.findAll();
List<X> list = Streamable.of(iterable).toList();
And since you mention being upset, maybe a little background for the decision to use Iterable help as well.
It is expected that it is actually fairly rare to actually require a Collection so in many cases it shouldn't make a difference.
Using the overriding mechanics one can return different types which wouldn't be possible with a more specific return type like Collection.
This would make it impossible to return a Streamable which is intended for cases where a store may decide to return a result before all elements have been fetched.
Streamable would actually be a flexible return type, since it offers easy conversions to List, Set, Stream and is itself an Iterable. But this would require you to use a Spring Data specific type in your application which many users wouldn't like.
There is a section about this in the reference documentation.

From CollectionUtils:
List<T> targetCollection = new ArrayList<T>();
CollectionUtils.addAll(targetCollection, iterable.iterator())
Here are the full sources of this utility method:
public static <T> void addAll(Collection<T> collection, Iterator<T> iterator) {
while (iterator.hasNext()) {
collection.add(iterator.next());
}
}

I use FluentIterable.from(myIterable).toList() a lot.

I came across a similar situation while trying to fetch a List of Projects, rather than the default Iterable<T> findAll() declared in CrudRepository interface. So, in my ProjectRepository interface (which extends from CrudRepository), I simply declared the findAll() method to return a List<Project> instead of Iterable<Project>.
package com.example.projectmanagement.dao;
import com.example.projectmanagement.entities.Project;
import org.springframework.data.repository.CrudRepository;
import java.util.List;
public interface ProjectRepository extends CrudRepository<Project, Long> {
#Override
List<Project> findAll();
}
This is the simplest solution, I think, without requiring conversion logic or usage of external libraries.

While at it, do not forget that all collections are finite, while Iterable has no promises whatsoever. If something is Iterable you can get an Iterator and that is it.
for (piece : sthIterable){
..........
}
will be expanded to:
Iterator it = sthIterable.iterator();
while (it.hasNext()){
piece = it.next();
..........
}
it.hasNext() is not required to ever return false. Thus in the general case you cannot expect to be able to convert every Iterable to a Collection. For example you can iterate over all positive natural numbers, iterate over something with cycles in it that produces the same results over and over again, etc.
Otherwise: Atrey's answer is quite fine.

This is not an answer to your question but I believe it is the solution to your problem. The interface org.springframework.data.repository.CrudRepository does indeed have methods that return java.lang.Iterable but you should not use this interface. Instead use sub interfaces, in your case org.springframework.data.mongodb.repository.MongoRepository. This interface has methods that return objects of type java.util.List.

I use my custom utility to cast an existing Collection if available.
Main:
public static <T> Collection<T> toCollection(Iterable<T> iterable) {
if (iterable instanceof Collection) {
return (Collection<T>) iterable;
} else {
return Lists.newArrayList(iterable);
}
}
Ideally the above would use ImmutableList, but ImmutableCollection does not allow nulls which may provide undesirable results.
Tests:
#Test
public void testToCollectionAlreadyCollection() {
ArrayList<String> list = Lists.newArrayList(FIRST, MIDDLE, LAST);
assertSame("no need to change, just cast", list, toCollection(list));
}
#Test
public void testIterableToCollection() {
final ArrayList<String> expected = Lists.newArrayList(FIRST, null, MIDDLE, LAST);
Collection<String> collection = toCollection(new Iterable<String>() {
#Override
public Iterator<String> iterator() {
return expected.iterator();
}
});
assertNotSame("a new list must have been created", expected, collection);
assertTrue(expected + " != " + collection, CollectionUtils.isEqualCollection(expected, collection));
}
I implement similar utilities for all subtypes of Collections (Set,List,etc). I'd think these would already be part of Guava, but I haven't found it.

As soon as you call contains, containsAll, equals, hashCode, remove, retainAll, size or toArray, you'd have to traverse the elements anyway.
If you're occasionally only calling methods such as isEmpty or clear I suppose you'd be better of by creating the collection lazily. You could for instance have a backing ArrayList for storing previously iterated elements.
I don't know of any such class in any library, but it should be a fairly simple exercise to write up.

In Java 8 you can do this to add all elements from an Iterable to Collection and return it:
public static <T> Collection<T> iterableToCollection(Iterable<T> iterable) {
Collection<T> collection = new ArrayList<>();
iterable.forEach(collection::add);
return collection;
}
Inspired by #Afreys answer.

Since RxJava is a hammer and this kinda looks like a nail, you can do
Observable.from(iterable).toList().toBlocking().single();

Here's an SSCCE for a great way to do this in Java 8
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class IterableToCollection {
public interface CollectionFactory <T, U extends Collection<T>> {
U createCollection();
}
public static <T, U extends Collection<T>> U collect(Iterable<T> iterable, CollectionFactory<T, U> factory) {
U collection = factory.createCollection();
iterable.forEach(collection::add);
return collection;
}
public static void main(String[] args) {
Iterable<Integer> iterable = IntStream.range(0, 5).boxed().collect(Collectors.toList());
ArrayList<Integer> arrayList = collect(iterable, ArrayList::new);
HashSet<Integer> hashSet = collect(iterable, HashSet::new);
LinkedList<Integer> linkedList = collect(iterable, LinkedList::new);
}
}

Two remarks
There is no need to convert Iterable to Collection to use foreach
loop - Iterable may be used in such loop directly, there is no
syntactical difference, so I hardly understand why the original question was asked at all.
Suggested way to convert Iterable to Collection is unsafe (the same relates to CollectionUtils) - there is no guarantee that subsequent calls to the next() method return different object instances. Moreover, this concern is not pure theoretical. E.g. Iterable implementation used to pass values to a reduce method of Hadoop Reducer always returns the same value instance, just with different field values. So if you apply makeCollection from above (or CollectionUtils.addAll(Iterator)) you will end up with a collection with all identical elements.

Try StickyList from Cactoos:
List<String> list = new StickyList<>(iterable);

Kinda late to the party, but I created a very elegant Java 8 solution that allows converting an Iterable of T to any Collection of T, without any libraries:
public static <T, C extends Collection<T>> C toCollection(Iterable<T> iterable, Supplier<C> baseSupplier)
{
C collection = baseSupplier.get();
iterable.forEach(collection::add);
return collection;
}
Usage Example:
Iterable<String> iterable = ...;
List<String> list = toCollection(iterable, ArrayList::new);

You can use Eclipse Collections factories:
Iterable<String> iterable = Arrays.asList("1", "2", "3");
MutableList<String> list = Lists.mutable.withAll(iterable);
MutableSet<String> set = Sets.mutable.withAll(iterable);
MutableSortedSet<String> sortedSet = SortedSets.mutable.withAll(iterable);
MutableBag<String> bag = Bags.mutable.withAll(iterable);
MutableSortedBag<String> sortedBag = SortedBags.mutable.withAll(iterable);
You can also convert the Iterable to a LazyIterable and use the converter methods or any of the other available APIs available.
Iterable<String> iterable = Arrays.asList("1", "2", "3");
LazyIterable<String> lazy = LazyIterate.adapt(iterable);
MutableList<String> list = lazy.toList();
MutableSet<String> set = lazy.toSet();
MutableSortedSet<String> sortedSet = lazy.toSortedSet();
MutableBag<String> bag = lazy.toBag();
MutableSortedBag<String> sortedBag = lazy.toSortedBag();
All of the above Mutable types extend java.util.Collection.
Note: I am a committer for Eclipse Collections.

If you could update to Spring Data 3, this has been addressed there. There is a new interface ListCrudRepository which do exactly what you want.
Here is the interface from https://spring.io/blog/2022/02/22/announcing-listcrudrepository-friends-for-spring-data-3-0:
public interface ListCrudRepository<T, ID> extends CrudRepository<T, ID> {
<S extends T> List<S> saveAll(Iterable<S> entities);
List<T> findAll();
List<T> findAllById(Iterable<ID> ids);
}
Note in version 3 you must implement two interfaces
So in version 2:
public interface PersonRepository<Person, Long> extends
PagingAndSortingRepository<Person, Long> {}
In version 3 should be changed to:
public interface PersonRepository<Person, Long> extends
PagingAndSortingRepository<Person, Long>,ListCrudRepository<Person, Long> {}
Other changes are mentioned in https://spring.io/blog/2022/02/22/announcing-listcrudrepository-friends-for-spring-data-3-0

Related

Is there a way of foreaching an Iterator in Java?

Java now has a convenient way to foreach a Collection eg.
for (MyClass c : aCollection) {
...
}
Is there something similarly elegant to foreach an Iterator or am I stuck with :
for (;it.hasNext();) {
MyClass c = it.next();
...
}
Update : for people who find this a strange question, I'm used to Python where
for x in xs :
f(x)
works whether xs is a collection OR an iterator (or even a generator). I was kind of caught out and surprised that Java didn't work like this.
I'm implementing a library where I'm returning iterators to some internal collections rather than the collections themselves. But I'm now concerned that this will force the users of my library back to using an older / uglier way of traversing than the foreach. Does this effectively deprecate iterators if people are used to using the foreach construct?
Well, apart from arrays which are a peculiar beast, the "extended for" loop you use here is just a result of the class implementing Iterable. And this interface only provides one method which is to return an... Iterator.
Which means that if you write in code:
for (final Foo foo: someInstanceImplementingIterableOfFoo) {
doSomethingWith(foo);
}
it is in fact equivalent to:
final Iterator<Foo> iterator = someInstanceImplementingIterableOfFoo.iterator();
Foo foo;
while (iterator.hasNext()) {
foo = iterator.next();
doSomethingWith(foo);
}
So, the answer really is no, no elegant way...
That is, unless you use Java 8. It has added forEachRemaining() on Iterator.
Or just create a utility class:
public final class IteratorWrap<T>
implements Iterable<T>
{
private final Iterator<T> iterator;
public static <X> IteratorWrap<X> wrap(final Iterator<X> iterator)
{
return new IteratorWrap<>(iterator);
}
private IteratorWrap(final Iterator<T> iterator)
{
this.iterator = Objects.requireNonNull(iterator);
}
#Override
public Iterator<T> iterator()
{
return iterator;
}
}
In code you'd then just:
for (final Foo foo: IteratorWrap.wrap(iteratorOfX))
doSomethingWith(foo);
Well, since you want something modern, using Java 8 you can do
Iterator<String> names = Arrays.asList("one","two","three").iterator();
for(String name : (Iterable<String>) () -> names) {
System.out.println(name);
}
Since the for-loop expects an Iterable Object, with this technique you can provide an Iterable out of an Iterator by using a lambda expression.
As mentioned by fge in another answer, though, this is equivalent to the following Java 8 expression using method references and avoiding the creation of the Iterable:
names.forEachRemaining(System.out::println);
So, you can pack your logic into a Consumer and solve your problem.
Java's "enhanced" for loop requires that the target to be iterated must implement Iterable. But if you have only an Iterator, which doesn't implement Iterable, there is no built-in way of using the Iterator as the target of a foreach loop in Java.
If you can't use Java 8, you can create an adapter class that wraps the Iterator, implements Iterable, and returns the wrapped iterator in the iterator() method.
class IterableIterator<T> implements Iterable<T>
{
private Iterator<T> iterator;
public IterableIterator(Iterator<T> iterator)
{
this.iterator = iterator;
}
#Override
public Iterator<T> iterator()
{
return iterator;
}
}
Then, if you have an Iterator, you can use it like this:
Iterator<MyClass> itr = getIteratorSomehow();
for (MyClass obj : new IterableIterator<MyClass>(itr))
{
// ...
}
Iterator<String> names = Arrays.asList("one", "two", "three").iterator();
String foo;
while((foo= Iterators.getNext(names, null))!=null){
System.out.println(foo);
}

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

How to subtract collections with Comparator interface instead of overriding equals

I want to compute differences between collections. When using CollectionUtils.subtract() for custom comparison I need to override the object's equals() method. But what if I need to compare collections of objects of the same type but different comparison criterion? What about the Comparator interface, it seems perfectly suited here? AFAIK Comparator is mainly used for sorting. Isn't there a method that uses Comparators for subtracting?
static <Type> Collection<Type> subtract(Collection<Type> a, Collection<Type> b, Comparator<Type> c) {
Set<Type> subtrahend = new TreeSet<Type>(c);
subtrahend.addAll(b);
Collection<Type> result = new ArrayList<Type>();
for (Type item: a) {
if (!subtrahend.contains(item)) result.add(item);
}
return result;
}
The subtrahent tree-set is not necessary, but will improve performance for large b.
If you have an ArrayList, multiple removes can be more expensive than taking a copy.
List<Type> list = /* ArrayList */
Set<Type> toRemove = /* HashSet */
List<Type> copy = new ArrayList<Type>(list.size());
for(Type t: list)
if(!toRemove.contains(t))
copy.add(t);
list = copy;
Personally I would use a loop. Its likely to be shorter and clearer.
Collection<Type> collection =
for(Iterator<Type> i=collection.iterator(); i.hasNext();)
if (i.next() is to be removed)
i.remove();
The reason an Iterator is used explicitly is to use the Iterator.remove() which avoids a ConcurrentModificationException. Another way to avoid it is to use a copy of the collection which might be preferred.
for(Type t : new ArrayList<Type>(collection))
if (t is to be removed)
collection.remove(t);
This doesn't perform as well but may perform well enough.

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