ensureCapacity() for inner ArrayList - java

I have a 2-dimensional ArrayList Object
private ArrayList<ArrayList<Short>> VOL_2D = new ArrayList<ArrayList<Short>>();
Now I want to call .ensureCapacity() on both the outer list and all the inner lists (The number of inner lists is know, but they are not initialized yet). For the outer list it is easy, I just define how many inner lists I want to fit inside.
Is there a nice way of calling this method on the inner lists? Or do I have to call it every time I initialize a new inner list?

There's no thing like "2-dimensional ArrayList Object". You have an ArrayList which stores ArrayList objects inside it. All of objects stored in the outer list may have different sizes, some of them may be null or subclasses of ArrayList. So you have to explicitly add enough ArrayList objects into the outer array list:
int n = // size of the outer list
int m = // size of the inner lists
private ArrayList<ArrayList<Short>> VOL_2D = new ArrayList<ArrayList<Short>>(n);
for(int i=0; i<n; i++)
VOL_2D.add(new ArrayList<>(m));
Please note that ensureCapacity does not actually add any elements to the list. It just resizes the internal array to fit the specified number of elements, so subsequent resizes will not be necessary. Creating an empty ArrayList and calling ensureCapacity right after this is meaningless: better to use the ArrayList(minCapacity) constructor which will do the same in more effective way. Anyways ensureCapacity is useful just to improve the performance. If you actually want to have elements inside these lists, you may use:
for(int i=0; i<n; i++) {
ArrayList<Short> inner = new ArrayList<>(m);
for(int j=0; j<m; j++)
inner.add(null); // or some other initial value
VOL_2D.add(inner);
}
Finally if you want to have two-dimensional ArrayList of fixed size, why not just create array like this?
private short[][] VOL_2D = new short[n][m];
It would be much more performant.

It seems that you don't understand what this construct really means. You see, those "inner" lists have no idea that they might be collected in some outer list. So there is no way to (easily) achieve what you are looking for.
One possibility though: you could extend ArrayList; and in your own class, you can overwrite all methods that would "add" an ArrayList ... you can do whatever you want; for example set the desired capcity.

You don't need to call ensureCapacity
It's just a method used for optimisation to avoid unnecessary reallocation of the underlying array data structure.
From the docs
An application can increase the capacity of an ArrayList instance
before adding a large number of elements using the ensureCapacity
operation. This may reduce the amount of incremental reallocation.

If the outer ArrayList size is known, and fixed then I would recommend you to use array instead of ArrayList, like below.
int size = 10;
ArrayList<Short>[] VOL_2D = new ArrayList<Short>[size];
Why do you need to call ensureCapacity(int minCapacity)? Could you elaborate your usecase? Because when you create instance you can specify the size of ArrayList. like below
VOL_2D[0] = new ArrayList<Short>(30);
This will invoke below constructor, and create an array size of 30
public ArrayList(int initialCapacity) {
super();
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
this.elementData = new Object[initialCapacity];
}
To answer your question, there is no single in-built method which will iterate all elements in list and call ensureCapacity.
You need to write code for this, like below
for(ArrayList<Short> vol : VOL_2D){
vol.ensureCapacity(30);
}
Remember this, before call ensureCapacity method, you need to initialize your ArrayList object (in your case all inner ArrayList object), otherwise you will end up with NullPointerException.

Related

Referencing the Objects of 2D array into an ArrayList

I need to create an ArrayList from a 2D Array where the ArrayList works as a linear "view" of the array. The thing thats bothering me is that when I change the value of some element of the original Array, it doesnt change in the List. While debugging, I observed that the reference to the object in the array changes, but it stays the same in the list. This is how I initialize the List:
public class ColeccionArray2D<E> extends AbstractCollection<E> {
private ArrayList<E> data = new ArrayList<E>();
private int size = 0;
public ColeccionArray2D(E[][] contenido) {
data = twoDArrayToList(contenido);
this.size = data.size();
}
public ArrayList<E> twoDArrayToList(E[][] twoDArray) {
int index = 0;
ArrayList<E> list = new ArrayList<E>();
for (int i = 0; i < twoDArray.length; i++) {
for (int j = 0; j < twoDArray[i].length; j++) {
list.add(index, twoDArray[i][j]);
index++;
}
}
return list;
}
But if I change the original array:
arrayInteger[0][0] = -1;
The reference on the array changes, but it stays the same in the list, as in the Integer object doesn't change.
My best guess is that I need to "update" the view as operations happen, but it defeats the purpose of referencing the elements of the original array.
Is there a way to add the reference of the index (for example [0][0]) to the list? So when the object inside changes, it changes as well in the list?
I need to create an ArrayList from a 2D Array where the ArrayList works as a linear "view" of the array.
The code presented in the question indeed does not implement a view of the array. Instead, it just copies the contents of the array (shallowly) at one point in time, and is subsequently independent.
It is possible to create a custom List implementation that uses your 2D array as the backing element store. This could be implemented such that the List.set() method replaces the corresponding reference in the backing store with the one specified as an argument. This would be facilitated by extending AbstractList and overriding (only) get(), set(), and size().
But other than by doing similar with ArrayList as a base class, you cannot accomplish your aim with specifically an ArrayList. And using ArrayList as a base would be problematic, because some of the things one can do with an ArrayList, such as lengthening it with add() or shrinking it with remove(), do not make sense for a view of a fixed-size object such as an array.

Why are ArrayList created with empty elements array but HashSet with null table?

Maybe a bit of a philosophical question.
Looking at java's ArrayList implementation I noticed that when creating a new instance, the internal "elementData" array (that holds the items) is created as new empty array:
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
However, a HashSet (that is based on a HashMap) is created with the table and entreySet are just left null;
transient Node<K,V>[] table;
transient Set<Map.Entry<K,V>> entrySet;
public HashMap() {
this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted
}
This got me thinking so I went and looked up C#'s List and HashSet:
https://referencesource.microsoft.com/#mscorlib/system/collections/generic/list.cs,61f6a8d9f0c40f6e
https://referencesource.microsoft.com/#System.Core/System/Collections/Generic/HashSet.cs,2d265edc718b158b
List:
static readonly T[] _emptyArray = new T[0];
public List() {
_items = _emptyArray;
}
HashSet:
private int[] m_buckets;
public HashSet()
: this(EqualityComparer<T>.Default) { }
public HashSet(IEqualityComparer<T> comparer) {
if (comparer == null) {
comparer = EqualityComparer<T>.Default;
}
this.m_comparer = comparer;
m_lastIndex = 0;
m_count = 0;
m_freeList = -1;
m_version = 0;
}
So, is there a good reason why both languages picked empty for list and null for set/map?
They both used the "single instance" for the empty array trick, which is nice, but why not just have a null array?
Answering from a C# perspective.
For an empty ArrayList, you'll find that all the logic (get, add, grow, ...) works "as-is" if you have an empty array as backing store. No need for additional code to handle the uninitialized case, this makes the whole implementation neater. And since the empty array is cached, this does not result in an additional heap allocation, so you get the cleaner code at no extra cost.
For HashSet this is not possible, as accessing a bucket is done through the formula hashCode % m_buckets.Length. Trying to compute % 0 is considered as a division by 0, and therefore invalid. This means you need to handle specifically the "not initialized" case, so you gain nothing from pre-assigning the field with an empty array.
Initializing elementData to an empty array in ArrayList allows to avoid a null check in the grow(int minCapacity) method, which calls:
elementData = Arrays.copyOf(elementData, newCapacity);
to increase the capacity of the backing array. When that method is first called, that statement will "copy" the empty array to the start of the new array (actually it will copy nothing).
In HashMap a similar strategy wouldn't be useful, since when you re-size the array of buckets, you don't copy the original array to the start of the new array, you have to go over all the entries and find the new bucket of each entry. Therefore initialing the buckets array to an empty array instead of keeping it null will require you to check if the array's length == 0 instead of checking whether it's null. Replacing one condition with another wouldn't be useful.

How to list elements maintaining order and reverse iteration?

What is the best list/set/array in Java that combines the following aspects:
maintain order of added elements
make if possible to both iterate forwards and backwards
of course good performance
I thought about a LinkedList, I then could insert elements by add(0, element) which would simulate a reverse order. Most of the time I will be using backwards iteration, so using this I can just iterate trough.
And if not, I can list.listIterator().hasPrevious().
But are there better approaches?
ArrayList will probably be your best bet. You can iterate through it in the following manner:
for (ListIterator it = list.listIterator(list.size()); it.hasPrevious();) {
Object value = it.previous();
}
A LinkedList will work but it will have more object creation overhead since you need to instantiate a Link for each element you store.
If you can get by index and wish to iterate over the collection then you can use a List and get(index) allow you to get the object in that place in the list. Arrays allow you to do this, you can just reference the index as normal, however if your array might grow then a Collection is going to be easier to use.
You can use List.size() and element through the object using a for loop rather than using an Iterator object, this will allow you to iterator over the list both forwards and backwards. For example:
List<AnObject> myList = new ArrayList<AnObject>;
// Add things to the list
for (int i = 0 ; i < myList.size; i++) {
AnObject myObject = myList.get(i);
}
for (int i = myList.size()-1 ; i <= 0 ; i--) {
AnObject myObject = myList.get(i);
}
Set is not applicable as a Set does not maintain ordering.

adding in ArrayList without iterating

I want to create an ArrayList<Float> of length 350. I did this:
x = new ArrayList<Float>(350);
No i want this array to have 'zero' float value at each point. i can do this:
for (int i = 0; i< 350 ; i++){
x.add((float) 0.0);
}
So my question is if there is another way to do the same thing without iterating. I want minimum iterating to increase efficiency.
If you want efficiency I wouldn't use ArrayList or Float here. I wouldn't recommend using float even as it's precision is so poor, unless you really know what you are doing.
I suggest you use an array of double.
double[] x = new double[350]; // all 0.0
java's Collections class has a nice utility for this: nCopies. Note that this creates an immutable list, but it does exactly what you want :)
From java documentation:
ArrayList(int initialCapacity)
Constructs an empty list with the specified initial capacity.
Note the list is still empty so you have to add the elements one by one. Only capacity is changed.
I would advice you to construct another collection for instance an array and then initialize the list using that constructor:
ArrayList(Collection<? extends E> c)
Constructs a list containing the elements of the specified collection, in the order they are returned by the collection's iterator.
As Peter says use an array. If you want this in an array list you can use the code below. This creates an arraylist of 100 integers each with a value of 42
Integer[] a = new Integer[100];
Arrays.fill(a, 42);
List<Integer> l = new ArrayList<Integer>(Arrays.asList(a));
for (Integer integer : l) {
System.out.println(integer);
}
You can modify it easily to be of type Float and assign any initial value you want.

How can I make a resizable array in Java?

What is the best way to do a resizable array in Java? I tried using Vector, but that shifts all elements over by when when you do an insert, and I need an array that can grow but the elements stay in place. I'm sure there's a simple answer for this, but I still not quite sure.
As an alternative, you could use an ArrayList. It is a resizable-array implementation of the List interface.
Usage (using String):
List<String> myList = new ArrayList<String>();
myList.add("a");
myList.add("c");
myList.add("b");
The order will be just like you put them in: a, c, b.
You can also get an individual item like this:
String myString = myList.get(0);
Which will give you the 0th element: "a".
Like Sanjo pointed out: "An array is a static datastructure, so they can't grow". The list interface can by backed by an array(for example ArrayList like Kevin pointed out in his post). When the list structure is full and a new item has to be added to the list. Then the structure first creates a new array which can contain the old elements plus the new element which has to be added to the list.
The list interface has a different implementations which all have there pros/cons and you should pick the one best solving your problem-set. Below I will try to give a short summary when to use which implementation:
Not thread-safe implementations:
ArrayList: Resizable-array implementation of the List interface. You should use this implementation when you are doing a lot of size, isEmpty, get, set, iterator, and listIterator operations run in constant time. The add operation runs in amortized constant time, that is, adding n elements requires O(n) time. I think you should use this implementation when doing more lookups(get()) then adding items to list(add()).
LinkedList: This implementation is not backup by an array but "links" the nodes together. In my opinion you should use this implementation when you are doing more add() then get().
Thread-safe implementations:
Be aware that these list implementations aren't thread-safe which means it is possible to get race conditions when accesing them from multiple threads. If you want to use List implementations from multiple threads I would advise you to study the java.util.concurrent package and use implementation from that class.
You probably should use ArrayList instead of Vector for reasons explained in other answers.
However ...
I tried using Vector, but that shifts all elements over by when when you do an insert, and I need an array that can grow but the elements stay in place.
When you do an insertElementAt(pos, elem), you have specifically asked for the element shifting. If you don't want the elements to be shifted, you should use set(pos, elem) instead. Or if you want to add the element at the end of the vector, you can also use add(elem).
Incidentally, the previous paragraph applies to all implementations of List, not just Vector, though the implementation details and performance vary across the different kinds of List.
I tried using Vector, but that shifts all elements over by when when you do an insert, and I need an array that can grow but the elements stay in place.
You probably want to use ArrayList instead of Vector.
They both provide about the same interface, and you can replace elements with both of them by calling set(idx, element). That does not do any shifting around. It also does not allow you to grow the array, though: You can only insert at already occupied positions (not beyond the current size of the array), to add new elements at the end you have to use add(element).
The difference between ArrayList and Vector is that Vector has synchronization code which you most likely do not need, which makes ArrayList a little faster.
If you want to operate array data after all element had already inserted or deleted, there is a way that try to create a LinkedList or ArrayList, its simply resize, after the data input is finished, you can transfer the ArrayList to an Array, then do all the things you normally to Array.
ArrayList and LinkedList
Space Complexity:
a) ArrayList:
Allocates a chunk of memory when you initialize and doubles everytime it reaches it max size whenever you add an element dynamically.
b) LinkedList:
It allocates memory only everytime you add an item to the list.
Runtime Complexity:
a) ArrayList:
Search is faster, insertion and deletion is slower compared to linked list
b) LinkedList:
Insertion and deletion is faster, search is slower compared to array list
An array cannot be resized dynamically in Java. The solution to this is using ArrayList or creating another temporary array and then assign it.
You can find tutorials about ArrayList, but if you just want custom ResizableArray in Java. Here's it is. But it's NOT recommend to use! It's just a FAKE resizable array and heap memory will be increased when you create too many objects. This is just to show you the idea.
The Interface
public interface Resizable<T> {
void add(T data);
int delete(int index);
int size();
void print();
}
Implementation Class
public class ResizeableImpl<T> implements Resizable<T> {
private Object[] temp = null;
private Object[] originals = new Object[0];
#Override
public void add(T data) {
Object[] temp = new Object[originals.length+1];
for (int i=0; i<originals.length; i++) {
temp[i]=originals[i];
}
temp[originals.length]=data;
originals=temp;
}
#Override
public int delete(int index) {
int success=0;
switch (originals.length) {
case 0: //No Data to delete
success=0;
break;
case 1: //One Data is delete and so no data, too!
originals = new Object[0];
success = 1;
break;
default: //>=2
int count=0;
originals[index]=null;
temp = new Object[originals.length-1];
for (int i=0; i<originals.length; i++) {
if (originals[i]!=null)
temp[count++]=originals[i];
}
originals = temp;
success = 1;
}
return success;
}
#Override
public int size() {
return originals.length;
}
#Override
public void print() {
StringBuilder sb = null;
if (originals.length==0) {
System.out.println("No data available!");
return;
}
for (int i=0; i<originals.length; i++) {
if (sb==null) {
sb = new StringBuilder();
sb.append(originals[i]);
}
else {
sb.append(", "+originals[i]);
}
}
sb.append(".");
System.out.println(sb.toString());
}
}
Main method
public class App {
public static void main(String[] args) {
//Program to interfaces, not implementations
Resizable<Integer> obj = new ResizeableImpl<>();
obj.add(13);
obj.add(20);
obj.add(17);
obj.add(25);
obj.add(100);
obj.add(12);
obj.print();
int result = obj.delete(2); //This will delete 17.
if (result==1) {
System.out.println("Deletion is successful!");
}
obj.print();
obj.delete(3); //This will delete 100.
obj.print();
}
}
Output
13, 20, 17, 25, 100, 12.
Deletion is successful!
13, 20, 25, 100, 12.
13, 20, 25, 12.
Use either ArrayList or LinkedList.
Using wonderful classes in Collections framework is the better than using arrays.
But in case your question is from a "quizzing" perspective, here is what you should do.
Create your own resize method such as:
int[] oldArray = {1,2,3};
int oldSize = java.lang.reflect.Array.getLength(oldArray);
Class elementType = oldArray.getClass().getComponentType();
Object newArray = java.lang.reflect.Array.newInstance(
elementType,newSize);
int preserveLength = Math.min(oldSize,newSize);
if (preserveLength > 0)
System.arraycopy (oldArray,0,newArray,0,preserveLength);
oldArray = newArray;

Categories

Resources