Java ArrayList copy without creating a new array - java

I have a List implementation (not mine) with an underlying array.
The implementation does not give access to the array directly, but only through the LIST INTERFACE methods that are implemented (just as an ArrayList implementation)
At some point, i will not able to work with this list (because of its implementation), but i will need to access (READ only) the data (underlying array).
Is there a way this can be achieved? Can a new ArrayList be created using the underlying array of the old one, without the creation of an ARRAY COPY?

You're going to have to have a new array to back the ArrayList anyway - so why is it a problem that it calls c.toArray()? The only inefficiency would be if it ends up in the branch calling Arrays.copyOf.

ArrayList(int) also creates an array
public ArrayList(int initialCapacity) {
...
this.elementData = new Object[initialCapacity];
}
but ArrayList(Collection) uses fast copying
public Object[] toArray() {
return Arrays.copyOf(elementData, size);
}

Related

Adding element to observable list in RxJava [duplicate]

I have a collection c1<MyClass> and an array a<MyClass>. I am trying to convert the array to a collection c2 and do c1.removeAll(c2), But this throws UnsupportedOperationException. I found that the asList() of Arrays class returns Arrays.ArrayList class and the this class inherits the removeAll() from AbstractList() whose implementation throws UnsupportedOperationException.
Myclass la[] = getMyClass();
Collection c = Arrays.asList(la);
c.removeAll(thisAllreadyExistingMyClass);
Is there any way to remove the elements? please help
Arrays.asList returns a List wrapper around an array. This wrapper has a fixed size and is directly backed by the array, and as such calls to set will modify the array, and any other method that modifies the list will throw an UnsupportedOperationException.
To fix this, you have to create a new modifiable list by copying the wrapper list's contents. This is easy to do by using the ArrayList constructor that takes a Collection:
Collection c = new ArrayList(Arrays.asList(la));
Yup, the Arrays.asList(..) is collection that can't be expanded or shrunk (because it is backed by the original array, and it can't be resized).
If you want to remove elements either create a new ArrayList(Arrays.asList(..) or remove elements directly from the array (that will be less efficient and harder to write)
That is the way Array.asList() works, because it is directly backed by the array.
To get a fully modifiable list, you would have to clone the collection into a collection created by yourself.
Collection c = new ArrayList(Arrays.asList(la))

java - how to remove an object from a collection using an iterator [duplicate]

I have a collection c1<MyClass> and an array a<MyClass>. I am trying to convert the array to a collection c2 and do c1.removeAll(c2), But this throws UnsupportedOperationException. I found that the asList() of Arrays class returns Arrays.ArrayList class and the this class inherits the removeAll() from AbstractList() whose implementation throws UnsupportedOperationException.
Myclass la[] = getMyClass();
Collection c = Arrays.asList(la);
c.removeAll(thisAllreadyExistingMyClass);
Is there any way to remove the elements? please help
Arrays.asList returns a List wrapper around an array. This wrapper has a fixed size and is directly backed by the array, and as such calls to set will modify the array, and any other method that modifies the list will throw an UnsupportedOperationException.
To fix this, you have to create a new modifiable list by copying the wrapper list's contents. This is easy to do by using the ArrayList constructor that takes a Collection:
Collection c = new ArrayList(Arrays.asList(la));
Yup, the Arrays.asList(..) is collection that can't be expanded or shrunk (because it is backed by the original array, and it can't be resized).
If you want to remove elements either create a new ArrayList(Arrays.asList(..) or remove elements directly from the array (that will be less efficient and harder to write)
That is the way Array.asList() works, because it is directly backed by the array.
To get a fully modifiable list, you would have to clone the collection into a collection created by yourself.
Collection c = new ArrayList(Arrays.asList(la))

Copying an ArrayList

I have an ArrayList of generic object type, i.e. List queue. I want to write a function EnqueueModified, that takes an arraylist and a list object as input and returns another ArrayList that contains the elments of the old arraylist and the list object but without affecting the original arraylist passed. i.e. Enqueue operation should be performed on a new copy of the arraylist and returned.
This can be done as follows:
public List<E> EnqueueModified(E e, List<E> queue) {
List<E> clone = new ArrayList<E>(queue);
clone.add(e);
return clone;
}
but is there a better method to do this? instead of using a copy constructor, is there any faster way to create a copy of the list? I cannot use cloning as it does not support for generic List.
To copy a list, you have to create a new list and fill it with items from the old list.
The constructor you are using might not actually be the best option, though. If you check the source code (google arraylist source code) you notice that it creates an array that is exactly as big as there are elements in the old collection.
Then it adds an element to that array. Because the array is too small, it has to create another copy of the array, only a bit bigger, and move the elements there again.
You could get a better performance by using
clone = new ArrayList(queue.size() + 1);
clone.addAll(queue);
clone.add(e);
Also, method names should start with a lower case letter. So use: enqueueModified(...)

Java array declaration without hard coding the size

How can I initialize an array of objects of a class in another class without hardcoding its size?
Use a List. The size does not need to be declared on creation of the List. The toArray() method will return an array representation of the list. There are multiple implementations you can use but the most popular tends to be ArrayList (though it is best to map the implementation to your particular situation).
Arrays have a fixed size after creation. The size doesn't need to be known at compile-time, but it does need to be known at creation time. For example:
public String[] createArray(int size) {
// Not hard-coded, but array is not expandable
return new String[size];
}
If you want a collection which can grow an shrink over time, look at the various List<E> implementations, such as ArrayList<E>.
Arrays are fixed in length. I would recommend using a Collection.
Here is an article on collections:
http://en.wikipedia.org/wiki/Java_collections_framework
With these, you can add elements by using an Add() command or something similar.
As mentioned in the previous answers, an ArrayList or List are collections.
Object[] will always be fixed size. If you need a variable length collection, try ArrayList, LinkedList, or one of the many others.
Pick the collection carefully, since they all have different performance aspects.
For mutable arrays other container objects are used.
When using a set of objects, an ArrayList or Vector object is used.
You can also store objects with an object key e.g. "Name" = "Ben" instead of [0] = "Ben".
Vector v = new Vector();
for(int i = 0; i < 100; i++){
Object o = new Object();
// init object
v.addElement(o);
}
for(int i = 0; i < 100; i++){
Object o = v.elementAt(i);
// manipulate object
}
Now you have an arbritairy list of object of undefined length.
Size found by using vector.size() method.
java.util package is required and part of J2SE 1.3 and higher.
As noted elsewhere, an array object has a fixed size. If there's some reason you must use an array, you can use one or both of these techniques:
Make it the larger than you need, leaving the unused
entries null. You may want to keep a "slotsUsed" variable.
When the array gets too small, make a bigger one and copy the
contents into it.
These are both used inside ArrayList.
You can create a new array and initialize it like this.
String[] strArray = {"Initialize","Array","Like","This"};
If you want an array with a dynamic size I would recommend using an ArrayList.
If you want an array of primitive instead of objects, you can use Trove4j. Otherwise use an ArrayList, or CopyOnWriteArrayList to wrap an array. There are other List implementations but these do not act like arrays for access time.
Sometimes it is useful, in case you know an upper bound of the objects your application needs,
to declare the size of an array as
static final int ARRAY_SIZE = 1000;
This goes near the beginning of the class so it can be easily changed.
In the main code instantiate the array with
Object[] objects = new Object[ARRAY_SIZE];
Also in case the array you want to use has the same size as another array consider using
Object[] objects = new Object[other_objects.length];

Java List toArray(T[] a) implementation

I was just looking at the method defined in the List interface:
Returns an array containing all of the elements in this list in the correct order; the runtime type of the returned array is that of the specified array. If the list fits in the specified array, it is returned therein. Otherwise, a new array is allocated with the runtime type of the specified array and the size of this list.
If the list fits in the specified array with room to spare (i.e., the array has more elements than the list), the element in the array immediately following the end of the collection is set to null. This is useful in determining the length of the list only if the caller knows that the list does not contain any null elements.
<T> T[] toArray(T[] a);
And I was just wondering why is it implemented this way, basically if you pass it an array with a length < to the list.size(), it will simply create a new one and return it. Therefore the creation of the new Array Object in the method parameter is useless.
Additionally if you pass it an array long enough using the size of the list if returns that same object with the objects - really no point in returning it since it is the same object but ok for clarity.
The problem is that I think this promotes slightly inefficient code, in my opinion toArray should simply receive the class and just return the new array with the contents.
Is there any reason why it is not coded that way?.
357 public <T> T[] toArray(T[] a) {
358 if (a.length < size)
359 // Make a new array of a's runtime type, but my contents:
360 return (T[]) Arrays.copyOf(elementData, size, a.getClass());
361 System.arraycopy(elementData, 0, a, 0, size);
362 if (a.length > size)
363 a[size] = null;
364 return a;
365 }
Maybe so it has a runtime type?
From wiki:
Consequently, instantiating a Java
class of a parameterized type is
impossible because instantiation
requires a call to a constructor,
which is unavailable if the type is
unknown.
As mentioned by others, there are a couple different reasons:
You need to pass in the type somehow, and passing in an array of the specified type isn't an unreasonable way to do it. Admittedly, it might be nice if there was a version that you pass in the Class of the type you want too, for speed.
If you want to reuse your array, you can keep passing in the same one, rather than needing to create a new one each time. This can save time and memory, and GC issues if you need to do it many, many times
Most likely this is to allow you to reuse arrays, so you basically avoid (relatively costly) array allocation for some use cases. Another much smaller benefit is that caller can instantiate array slightly more efficiently, since toArray() must use 'java.lang.reflect.Array.newInstance' method.
This method is a holdover from pre-1.5 Java. Here is the link to javadoc
Back then it was the only way to convert a list to a reifiable array.
It is an obscure fact, but although you can store anything in the Object[] array, you cannot cast this array to more specific type, e.g.
Object[] generic_array = { "string" };
String[] strings_array = generic_array; // ClassCastException
Seemingly more efficient List.toArray() does just that, it creates a generic Object array.
Before Java generics, the only way to do a type-safe transfer was to have this cludge:
String[] stronglyTypedArrayFromList ( List strings )
{
return (String[]) strings.toArray( new String[] );
// or another variant
// return (String[]) strings.toArray( new String[ strings.size( ) ] );
}
Thankfully generics made these kind of machinations obsolete. This method was left there to provide backward compatibility with pre 1.5 code.
My guess is that if you already know the concrete type of T at the point you're calling toArray(T[]), it's more performant to just declare an array of whatever it is than make the List implementation call Arrays.newInstance() for you -- plus in many cases you can re-use the array.
But if it annoys you, it's easy enough to write a utility method:
public static <E> E[] ToArray(Collection<E> c, Class<E> componentType) {
E[] array = (E[]) Array.newInstance(componentType, c.size());
return c.toArray(array);
}
(Note that there's no way to write <E> E[] ToArray(Collection<E> c), because there's no way to create an array of E at runtime without a Class object, and no way to get a Class object for E at runtime, because the generics have been erased.)

Categories