How to resize ArrayList - java

I come from a C++ background and I want to have a matrix of
ArrayList<arrayList<E>> javamatrix
In C++ I would just do
std::vector<std::vector<T> > cppmatrix;
std::vector<T>vcol(cols);
cppmatrix.resize(rows,vcol);
I can't seem to find a built-in resize() function for ArrayLists for this task, so should I use another collection? Is no way to do this except using for loops with javamatrix.add()?
P.S I want it to be initialized in the constructor with its size as that size might be queried before I edit elements or add or remove.

There is no resize equivalent that automatically constructs and adds elements. You must do this yourself. However, ensureCapacity is equivalent to vector's reserve. It will ensure you have room, but not change the actual size.

You shouldn't need to resize arraylists. The size you initially pass in is just its starting size. If you attempt to add items beyond its current size, it will automatically resize.
From the documentation:
Each ArrayList instance has a capacity. The capacity is the size of the array used to store the elements in the list. It is always at least as large as the list size. As elements are added to an ArrayList, its capacity grows automatically. The details of the growth policy are not specified beyond the fact that adding an element has constant amortized time cost.

Mostly, a 'resize()' operation is not needed because (a) ArrayList's auto-resize as you add elements, and (b) it's unclear what values you would store in the ArrayList<>, e.g. 'null' is not very useful. E.g. in your case you'd probably need a loop anyway to create MatrixCell objects.
For those readers who want to know how to resize an ArrayList to make it smaller, it mystifies me why ArrayList was designed without a 'resize()' method. Perhaps it's because novice programmers are likely to see that method and then not realise that ArrayList<> auto-resizes.
In Java this idiom works to reduce the size of an ArrayList<>:
list.subList(n,list.size()).clear();
It works because the 'subList' returns a List backed by the original ArrayList<>, so therefore the 'clear()' operates on the original 'ArrayList<>'.

I know this question is very old already but this link may help java arraylist ensureCapacity not working , The code adds "Null" value in order to adjust the current size.
Instead of using purely ensureCapacity you can have ensureSize
public static void ensureSize(ArrayList<?> list, int size) {
list.ensureCapacity(size);
while (list.size() < size) {
list.add(null);
}
}

Related

initialCapacity in ArrayList

I need to create an ArrayList and I know upfront that the max size for this array won't exceed more than 5 elements.
I wanted to know from the community whether initailCapacity specifying size as 5 will have any performance benefits.
List<String> list = new ArrayList<>(5);
or
List<String> list = new ArrayList<>();
Which one is better?
If you do expect that the list will usually be populated with at least some elements (but no more than 5), then yes, setting an initial capacity of 5 will likely be the most efficient way to go.
Lazy instantiation of backing array
However, if the most common / expected case is that not even a single item gets added to the list, then the constructor without any specified initial capacity may be more efficient. This is because (assuming a somewhat recent JDK version is used) the ArrayList will not yet allocate any backing array at all, but just use a reference shared among all empty, default-constructed ArrayLists. It will only actually allocate memory once you start adding items to it.
When you add your first element to the ArrayList, a new backing array is created. That new array defaults to a size of ten.
To see that a shared reference to a backing array is initially used, you can look at OpenJDK's github for example, and you can find the implementation of the no-args constructor here. It looks as follows:
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
That reference that the backing array (elementData) is assigned to is declared higher up in the file as follows:
/**
* Shared empty array instance used for default sized empty instances. We
* distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when
* first element is added.
*/
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
This does not only happen in OpenJDK, but also in Oracle's JDK. At least, it does in the version I have on my computer right here. I don't know if there are any easy-to-find links to Oracle's source code though, OpenJDK source code is easier to find online.
From ArrayList.java
/**
* Default initial capacity.
*/
private static final int DEFAULT_CAPACITY = 10;
The default capacity (used when you don't provide one) is ten. So specifying the size of five will mean less memory gets used.
If you know that you'll only ever have a certain number, perhaps an Array will be a more lightweight choice.
It depends on the use case. Suppose if you already know that a specific number of objects(in this case string objects) are going to be stored for sure, then if you would specify the size of the ArrayList while creating it would allocate the memory at that step.
List<String> list = new ArrayList<>(5);
Then once the elements are filled the size of the ArrayList will expand dynamically as you add more objects. Suppose if you are going to add 50 elements to the ArrayList for sure, then specify the initial capacity as 50 which would result in allocating that much space. This would be a more efficient approach as you wont be dynamically allocating the memory up to 50 elements after initialization. Allocating memory as the ArrayList expands will affect the performance. At the same time if you specify a large initial size then you are wasting valuable memory space.
yeah, it will improvethe performance, as not much memory default of 10 will be occupied
Yes it will improve performance but only by a tiny amount.
Good practice would be to set the list to a specific length if you know it will always be that long, but such uses tend to be rare so shouldn't be a common issue.
Furthermore, if it is a 5 member list then you will probably be better off just making a new object with 5 fields. This will make handling this data easier and faster as won't need to search the list.

ArrayList.trimToSize() method

Can I use ArrayList.trimToSize() method in dynamic arrayList ?
If I use it , what will be happened ?
Can I get any benefits on using this method on dynamic ArrayList.
In which case, I should use this method.
Thanks in advance.
From the docs you link yourself:
Trims the capacity of this ArrayList instance to be the list's current size. An application can use this operation to minimize the storage of an ArrayList instance.
Internally an ArrayList stores an array that holds all the items. At certain moments the ArrayList will "expand" this array by copying all values into a larger array. This happens whenever an item is being added and the required capacity is bigger than the current one. What happens at this point is the following line of code:
int newCapacity = oldCapacity + (oldCapacity >> 1);
elementData = Arrays.copyOf(elementData, newCapacity);
In essence this will create a new array that is 1.5 times the size of the current one. What this method does is resize the internal array so that it has no empty space left.
Nothing will happen that's visible to you. You won't lose any data, it's just smaller backing array. Adding data to the arraylist will again expand the array normally.
I assume you mean a "normal" ArrayList. If you use this, you will reduce the memory used but it will also be futile if you will still add data after that AND it is pretty useless for small lists. If you have an ArrayList of many, many items and you're sure you don't want to add anymore then you can call this method to reduce some memory footprint.
See above. I don't think it's very likely you'll ever use this.
trimToSize() from the source:
public void trimToSize() {
modCount++;
int oldCapacity = elementData.length;
if (size < oldCapacity) {
elementData = Arrays.copyOf(elementData, size);
}
}
Well, that's simple:
The ArrayList will be trimmed to its current size
Yes, you can minimize the storage of an ArrayList instance
When you want to trim the ArrayList and minimize its storage
But seriously: There are few occasions where this method should be called (I personally have never used it). It's related to how an ArrayList is implemented: As the name suggests, the ArrayList internally uses an array to store the data. When you add new elements to the ArrayList, the size of the array is increased as needed. When you add 1000000 elements to the ArrayList, then the internal Array will have a .length of at least (!) 1000000. When you afterwards remove 999999 elements from the ArrayList, then the internal array will still have a .length of at least 1000000. The call to trimToSize will then make sure that the internal array only has the required size (1, in this case). But again: This is hardly ever necessary or beneficial. You should usually not work on ArrayList instances anyhow, but on the (more general) List interface.

How do I create an array of strings without specifying its length in the beginning?

I want to create an array of strings, but I do not know the length of it in the beginning. It's like the array length depends on many factors and it's only decided when I fill strings/words into it. however, processing does not allow me to do that, it asks me to specify the length in the beginning. How can I get rid of this?..Thanks for all help. Any suggestion will be appreciated.
Amrita
List<String> strs = new ArrayList<String>();
strs.add("String 1");
strs.add("String 2");
strs.add("String 3");
System.out.println(strs.size()); //3
System.out.println(strs.get(1)); //String 2
Something like that is all you need! You don't need to worry about resizing, copying stuff in memory or whatever - the list will just expand as it needs to. All of the performance details are taken care of and unless you're really interested in how it works, you don't need to read about those details to use it.
You can use ArrayList: http://processing.org/reference/ArrayList.html
I would start by using ArrayList and resizing it when necessary. Java pre-allocates memory for ArrayList so that not every resize means that the contents are copied in memory. Access to ArrayList is faster than to LinkedList (it's O(1) instead of O(n)). Only if you find that the resizing of the ArrayList takes too much time, would I think of switching to LinkedList.
Use the typed ArrayList as #berry120 suggests (otherwise, you'll need to cast from Object to String all the time).
Also, if it helps, Processing has some functions for handling Arrays (like append() and expand()). Look under Array Functions in the Processing reference.
Behind the scenes the above mentioned Array Functions use System.arraycopy(), if that's of any use.
You need to use a LinkedList structure: this gives you an easily expanded container array and takes an initial capacity in the constructor, rather than a set limit. This will also be more efficient than an ArrayList, which will copy it's contents every time you exceed the current capacity, rather than simply add to it.

What are the differences between ArrayList and Vector?

What are the differences between the two data structures ArrayList and Vector, and where should you use each of them?
Differences
Vectors are synchronized, ArrayLists
are not.
Data Growth Methods
Use ArrayLists if there is no specific requirement to use Vectors.
Synchronization
If multiple threads access an ArrayList concurrently then we must externally synchronize the block of code which modifies the list either structurally or simply modifies an element. Structural modification means addition or deletion of element(s) from the list. Setting the value of an existing element is not a structural modification.
Collections.synchronizedList is normally used at the time of creation of the list to avoid any accidental unsynchronized access to the list.
Data growth
Internally, both the ArrayList and Vector hold onto their contents using an Array. When an element is inserted into an ArrayList or a Vector, the object will need to expand its internal array if it runs out of room. A Vector defaults to doubling the size of its array, while the ArrayList increases its array size by 50 percent.
As the documentation says, a Vector and an ArrayList are almost equivalent. The difference is that access to a Vector is synchronized, whereas access to an ArrayList is not. What this means is that only one thread can call methods on a Vector at a time, and there's a slight overhead in acquiring the lock; if you use an ArrayList, this isn't the case. Generally, you'll want to use an ArrayList; in the single-threaded case it's a better choice, and in the multi-threaded case, you get better control over locking. Want to allow concurrent reads? Fine. Want to perform one synchronization for a batch of ten writes? Also fine. It does require a little more care on your end, but it's likely what you want. Also note that if you have an ArrayList, you can use the Collections.synchronizedList function to create a synchronized list, thus getting you the equivalent of a Vector.
Vector is a broken class that is not threadsafe, despite it being "synchronized" and is only used by students and other inexperienced programmers.
ArrayList is the go-to List implementation used by professionals and experienced programmers.
Professionals wanting a threadsafe List implementation use a CopyOnWriteArrayList.
ArrayList is newer and 20-30% faster.
If you don't need something explitly apparent in Vector, use ArrayList
There are 2 major differentiation's between Vector and ArrayList.
Vector is synchronized by default, and ArrayList is not.
Note : you can make ArrayList also synchronized by passing arraylist object to Collections.synchronizedList() method.
Synchronized means : it can be used with multiple threads with out any side effect.
ArrayLists grow by 50% of the previous size when space is not sufficient for new element, where as Vector will grow by 100% of the previous size when there is no space for new incoming element.
Other than this, there are some practical differences between them, in terms of programming effort:
To get the element at a particular location from Vector we use elementAt(int index) function. This function name is very lengthy.
In place of this in ArrayList we have get(int index) which is very
easy to remember and to use.
Similarly to replace an existing element with a new element in Vector we use setElementAt() method, which is again very lengthy and may irritate the programmer to use repeatedly. In place of this ArrayList has add(int index, object) method which is easy to use and remember.
Like this they have more programmer friendly and easy to use function names in ArrayList.
When to use which one?
Try to avoid using Vectors completely. ArrayLists can do everything what a Vector can do. More over ArrayLists are by default not synchronized. If you want, you can synchronize it when ever you need by using Collections util class.
ArrayList has easy to remember and use function names.
Note : even though arraylist grows by 100%, you can avoid this by ensurecapacity() method to make sure that you are allocating sufficient memory at the initial stages itself.
Hope it helps.
ArrayList and Vector both implements List interface and maintains insertion order.But there are many differences between ArrayList and Vector classes...
ArrayList -
ArrayList is not synchronized.
ArrayList increments 50% of current array size if number of element exceeds from its capacity.
ArrayList is not a legacy class, it is introduced in JDK 1.2.
ArrayList is fast because it is non-synchronized.
ArrayList uses Iterator interface to traverse the elements.
Vector -
Vector is synchronized.
Vector increments 100% means doubles the array size if total number of element exceeds than its capacity.
Vector is a legacy class.
Vector is slow because it is synchronized i.e. in multithreading environment, it will hold the other threads in runnable or non-runnable state until current thread releases the lock of object.
Vector uses Enumeration interface to traverse the elements. But it can use Iterator also.
See Also : https://www.javatpoint.com/difference-between-arraylist-and-vector
Basically both ArrayList and Vector both uses internal Object Array.
ArrayList: The ArrayList class extends AbstractList and implements the List interface and RandomAccess (marker interface). ArrayList supports dynamic arrays that can grow as needed. It gives us first iteration over elements.
ArrayList uses internal Object Array; they are created with an default initial size of 10. When this size is exceeded, the collection is automatically increases to half of the default size that is 15.
Vector: Vector is similar to ArrayList but the differences are, it is synchronized and its default initial size is 10 and when the size exceeds its size increases to double of the original size that means the new size will be 20. Vector is the only class other than ArrayList to implement RandomAccess. Vector is having four constructors out of that one takes two parameters Vector(int initialCapacity, int capacityIncrement) capacityIncrement is the amount by which the capacity is increased when the vector overflows, so it have more control over the load factor.
Some other differences are:

Java ArrayList<Double> IndexOutOfBoundsException Problem

I've got a Problem with ArrayList. I need it to store a result. Because I want to start with element n I tried to give the ArrayList a capacity with ensureCapacity(n+1) to use set(n,x) but I get an IndexOutOfBoundsException.
I tried to store n add(x) before the use of set and this works.
So I'd like to know why it doesn't work on my way and how to solve this because put n times a add(x) isn't a good style ;-)
When you change the capacity of an ArrayList it doesn't create any elements, it just reserves memory where there could be elements. You can check the size before and after adjusting the capacity and you will see that it does not change.
The purpose of changing the capacity is if you know in advance how many elements you will have, then you can avoid unnecessary repeated resizing as you add new elements, and you can avoid memory wastage from excess unused capacity.
If you don't like using your own loop and the list add method directly then there is another way. Create your ArrayList with the number of elements you want it directly like this:
final int MAX_ELEMENTS = 1000;
List<Integer> myList = new ArrayList<Integer>(
Collections.<Integer>nCopies(MAX_ELEMENTS, null));
Or, if you already have a list that you want to expand the size by n elements:
myList.addAll(Collections.<Integer>nCopies(n, null));
(Note, I assumed here that the list would be holding Integer objects, but you can change this to your custom type. If you are working with raw/pre-Java 5 types then just drop the generic declarations.)
As for your actual question: capacity != contents. An ArrayList internally has both a physical array and a count of what is actually in it. Increasing the capacity, changes the internal array so it can hold that many elements, however, the count does not change. You need to add elements to increase that count.
On the other hand, if you are just trying to set specific elements and know the maximum that you want to use, why not use an array directly? If you then need to pass this array to an API that takes Lists, then use Arrays.asList. The other classes could still change contents of your backing array but it would not be able to increase the size or capacity of it.
As others have answered, ensureCapacity() is just related to performance, is not frequently used by the common user.
From Bruce Eckel's Thinking in Java book:
In a private message, Joshua Bloch
wrote: "... I believe that we erred by
allowing implementation details (such
as hash table size and load factor)
into our APIs. The client should
perhaps tell us the maximum expected
size of a collection, and we should
take it from there. Clients can easily
do more harm than good by choosing
values for these parameters. As an
extreme example, consider Vector's
capacityIncrement. No one should ever
set this, and we shouldn't have
provided it. If you set it to any
non-zero value, the asymptotic cost of
a sequence of appends goes from linear
to quadratic. In other words, it
destroys your performance. Over time,
we're beginning to wise up about this
sort of thing. If you look at
IdentityHashMap, you'll see that it
has no low-level tuning parameters"
You are getting this exception because ensureCapacity() only makes sure that there is enough memory allocated for adding objects to an ArrayList, I believe this is in case you want to add multiple objects at once, without having to relocate memory.
To do what you want you would have to initiate the ArrayList with null elements first...
int n = 10; //capacity required
ArrayList foo = new ArrayList();
for( int i=0; i<=n; i++ ) {
foo.add(null);
}
Then you have objects in the List that you can reference via index and you wont receive the exception.
Perhaps you should rethink the choice of using List<Double>. It might be that a Map<Integer,Double> would be more appropriate if elements are to be added in an odd order.
Whether this is appropriate depends on knowledge about your usage that I don't have at the moment though.
Is the data structure eventually going to be completely filled, or is the data sparse?
what other people said about ensureCapacity() ...
you should write a class like DynamicArrayList extends ArrayList. then just overrride add(n,x) to do with for loop add(null) logic specified about.
ensureCapacity() has another purpose. It should be used in cases when you get to know the required size of the List after it has been constructed. If you know the size before it is constructor, just pass it as a an argument to the constructor.
In the former case use ensureCapacity() to save multiple copying of the backing array on each addition. However, using that method leaves the structure in a seemingly inconsistent state
the size of the backing array is increased
the size field on the ArrayList isn't.
This, however, is normal, since the capacity != size
Use the add(..) method, which is the only one that is increasing the size field:
ArrayList list = new ArrayList();
list.ensureCapacity(5); // this can be done with constructing new ArrayList(5)
for (int i = 0; i < list.size - 1; i ++) {
list.add(null);
}
list.add(yourObject);

Categories