I'm fairly new to ArrayLists anyway but I need them for this project I'm doing so if you guys could help me I would be more than grateful!
Basically, I need to create a multidemensional ArrayList to hold String values. I know how to do this with a standard array, like so public static String[][] array = {{}}
but this is no good because I don't know the size of my array, all I know is how many demensions it will have.
So, if you guys know how to make a 'dynamically resizable array with 2/+ demensions', please could you tell me.
Thanks In advance,
Andy
Edit/Update
Maybe it would be easier to resize or define a standard array using a varible? But I don't know?
It's probably easier to use my original idea of an ArrayList though... All I need is a complete example code to create a 2D ArrayList and add so example values to both dimensions without knowing the index.
This question is related to
java
multidimensional-array
arraylist
ArrayList<ArrayList<String>> array = new ArrayList<ArrayList<String>>();
Depending on your requirements, you might use a Generic class like the one below to make access easier:
import java.util.ArrayList;
class TwoDimentionalArrayList<T> extends ArrayList<ArrayList<T>> {
public void addToInnerArray(int index, T element) {
while (index >= this.size()) {
this.add(new ArrayList<T>());
}
this.get(index).add(element);
}
public void addToInnerArray(int index, int index2, T element) {
while (index >= this.size()) {
this.add(new ArrayList<T>());
}
ArrayList<T> inner = this.get(index);
while (index2 >= inner.size()) {
inner.add(null);
}
inner.set(index2, element);
}
}
Wouldn't List<ArrayList<String>> 2dlist = new ArrayList<ArrayList<String>>();
be a better (more efficient) implementation?
ArrayList<ArrayList<String>>
http://download.oracle.com/javase/6/docs/api/java/util/ArrayList.html
Once I required 2-D arrayList and I created using List and ArrayList and the code is as follows:
import java.util.*;
public class ArrayListMatrix {
public static void main(String args[]){
List<ArrayList<Integer>> a = new ArrayList<>();
ArrayList<Integer> a1 = new ArrayList<Integer>();
ArrayList<Integer> a2 = new ArrayList<Integer>();
ArrayList<Integer> a3 = new ArrayList<Integer>();
a1.add(1);
a1.add(2);
a1.add(3);
a2.add(4);
a2.add(5);
a2.add(6);
a3.add(7);
a3.add(8);
a3.add(9);
a.add(a1);
a.add(a2);
a.add(a3);
for(ArrayList obj:a){
ArrayList<Integer> temp = obj;
for(Integer job : temp){
System.out.print(job+" ");
}
System.out.println();
}
}
}
Output:
1 2 3
4 5 6
7 8 9
Source : https://www.codepuran.com/java/2d-matrix-arraylist-collection-class-java/
What would you think of this for 3D ArrayList - can be used similarly to arrays - see the comments in the code:
import java.util.ArrayList;
import java.util.List;
/**
* ArrayList3D simulates a 3 dimensional array,<br>
* e.g: myValue = arrayList3D.get(x, y, z) is the same as: <br>
* myValue = array[x][y][z] <br>
* and<br>
* arrayList3D.set(x, y, z, myValue) is the same as:<br>
* array[x][y][z] = myValue; <br>
* but keeps its full ArrayList functionality, thus its
* benefits of ArrayLists over arrays.<br>
* <br>
* @param <T> data type
*/
public class ArrayList3D <T> {
private final List<List<List<T>>> arrayList3D;
public ArrayList3D() {
arrayList3D = newArrayDim1();
}
/**
* Get value of the given array element.<br>
* E.g: get(2, 5, 3);<br>
* For 3 dim array this would equal to:<br>
* nyValue = array[2][5][3];<br>
* <br>
* Throws: IndexOutOfBoundsException
* - if any index is out of range
* (index < 0 || index >= size())<br>
* <br>
* @param dim1 index of the first dimension of the array list
* @param dim2 index of the second dimension of the array list
* @param dim3 index of the third dimension of the array list
* @return value of the given array element (of type T)
*/
public T get(int dim1, int dim2, int dim3) {
List<List<T>> ar2 = arrayList3D.get(dim1);
List<T> ar3 = ar2.get(dim2);
return ar3.get(dim3);
}
/**
* Set value of the given array.<br>
* E.g: set(2, 5, 3, "my value");<br>
* For 3 dim array this would equal to:<br>
* array[2][5][3]="my value";<br>
* <br>
* Throws: IndexOutOfBoundsException
* - if any index is out of range
* (index < 0 || index >= size())<br>
* <br>
* @param dim1 index of the first dimension of the array list
* @param dim2 index of the second dimension of the array list
* @param dim3 index of the third dimension of the array list
* @param value value to assign to the given array
* <br>
*/
public void set(int dim1, int dim2, int dim3, T value) {
arrayList3D.get(dim1).get(dim2).set(dim3, value);
}
/**
* Set value of the given array element.<br>
* E.g: set(2, 5, 3, "my value");<br>
* For 3 dim array this would equal to:<br>
* array[2][5][3]="my value";<br>
* <br>
* Throws: IndexOutOfBoundsException
* - if any index is less then 0
* (index < 0)<br>
* <br>
* @param indexDim1 index of the first dimension of the array list
* @param indexDim2 index of the second dimension of the array list
* If you set indexDim1 or indexDim2 to value higher
* then the current max index,
* the method will add entries for the
* difference. The added lists will be empty.
* @param indexDim3 index of the third dimension of the array list
* If you set indexDim3 to value higher
* then the current max index,
* the method will add entries for the
* difference and fill in the values
* of param. 'value'.
* @param value value to assign to the given array index
*/
public void setOrAddValue(int indexDim1,
int indexDim2,
int indexDim3,
T value) {
List<T> ar3 = setOrAddDim3(indexDim1, indexDim2);
int max = ar3.size();
if (indexDim3 < 0)
indexDim3 = 0;
if (indexDim3 < max)
ar3.set(indexDim3, value);
for (int ix = max-1; ix < indexDim3; ix++ ) {
ar3.add(value);
}
}
private List<List<List<T>>> newArrayDim1() {
List<T> ar3 = new ArrayList<>();
List<List<T>> ar2 = new ArrayList<>();
List<List<List<T>>> ar1 = new ArrayList<>();
ar2.add(ar3);
ar1.add(ar2);
return ar1;
}
private List<List<T>> newArrayDim2() {
List<T> ar3 = new ArrayList<>();
List<List<T>> ar2 = new ArrayList<>();
ar2.add(ar3);
return ar2;
}
private List<T> newArrayDim3() {
List<T> ar3 = new ArrayList<>();
return ar3;
}
private List<List<T>> setOrAddDim2(int indexDim1) {
List<List<T>> ar2 = null;
int max = arrayList3D.size();
if (indexDim1 < 0)
indexDim1 = 0;
if (indexDim1 < max)
return arrayList3D.get(indexDim1);
for (int ix = max-1; ix < indexDim1; ix++ ) {
ar2 = newArrayDim2();
arrayList3D.add(ar2);
}
return ar2;
}
private List<T> setOrAddDim3(int indexDim1, int indexDim2) {
List<List<T>> ar2 = setOrAddDim2(indexDim1);
List<T> ar3 = null;
int max = ar2.size();
if (indexDim2 < 0)
indexDim2 = 0;
if (indexDim2 < max)
return ar2.get(indexDim2);
for (int ix = max-1; ix < indexDim2; ix++ ) {
ar3 = newArrayDim3();
ar2.add(ar3);
}
return ar3;
}
public List<List<List<T>>> getArrayList3D() {
return arrayList3D;
}
}
And here is a test code:
ArrayList3D<Integer> ar = new ArrayList3D<>();
int max = 3;
for (int i1 = 0; i1 < max; i1++) {
for (int i2 = 0; i2 < max; i2++) {
for (int i3 = 0; i3 < max; i3++) {
ar.setOrAddValue(i1, i2, i3, (i3 + 1) + (i2*max) + (i1*max*max));
int x = ar.get(i1, i2, i3);
System.out.println(" - " + i1 + ", " + i2 + ", " + i3 + " = " + x);
}
}
}
Result output:
If you're allowed to use predefined Java classes, you could do something like:
private static ArrayList<ArrayList<String>> biDemArrList = new ArrayList<ArrayList<String>>();
Then you can add new elements, something like:
ArrayList<String> temp = new ArrayList<String>(); // added ()
temp.add("Hello world.");
biDemArrList.add(temp);
Hope you can understand what I mean and what's going on. Also, you'll need to import java.util.ArrayList; for this, if you're making use of the Java class.
Credit goes for JAcob Tomao for the code. I only added some comments to help beginners like me understand it. I hope it helps.
// read about Generic Types In Java & the use of class<T,...> syntax
// This class will Allow me to create 2D Arrays that do not have fixed sizes
class TwoDimArrayList<T> extends ArrayList<ArrayList<T>> {
public void addToInnerArray(int index, T element) {
while (index >= this.size()) {
// Create enough Arrays to get to position = index
this.add(new ArrayList<T>()); // (as if going along Vertical axis)
}
// this.get(index) returns the Arraylist instance at the "index" position
this.get(index).add(element); // (as if going along Horizontal axis)
}
public void addToInnerArray(int index, int index2, T element) {
while (index >= this.size()) {
this.add(new ArrayList<T>());// (as if going along Vertical
}
//access the inner ArrayList at the "index" position.
ArrayList<T> inner = this.get(index);
while (index2 >= inner.size()) {
//add enough positions containing "null" to get to the position index 2 ..
//.. within the inner array. (if the requested position is too far)
inner.add(null); // (as if going along Horizontal axis)
}
//Overwrite "null" or "old_element" with the new "element" at the "index 2" ..
//.. position of the chosen(index) inner ArrayList
inner.set(index2, element); // (as if going along Horizontal axis)
}
}
You can also do something like this ...
First create and Initialize the matrix or multidimensional arraylist
ArrayList<ArrayList<Integer>> list;
MultidimentionalArrayList(int x,int y)
{
list = new ArrayList<>();
for(int i=0;i<=x;i++)
{
ArrayList<Integer> temp = new ArrayList<>(Collections.nCopies(y+1,0));
list.add(temp);
}
}
void add(int row,int column,int val)
{
list.get(row).set(column,val); // list[row][column]=val
}
This static matrix can be change into dynamic if check that row and column are out of bound. just insert extra temp arraylist for row
int remove(int row, int column)
{
return list.get(row).remove(column);// del list[row][column]
}
Here an answer for those who'd like to have preinitialized lists of lists. Needs Java 8+.
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
class Scratch {
public static void main(String[] args) {
int M = 4;
int N = 3;
// preinitialized array (== list of lists) of strings, sizes not fixed
List<List<String>> listOfListsOfString = initializeListOfListsOfT(M, N, "-");
System.out.println(listOfListsOfString);
// preinitialized array (== list of lists) of int (primitive type), sizes not fixed
List<List<Integer>> listOfListsOfInt = initializeListOfListsOfInt(M, N, 7);
System.out.println(listOfListsOfInt);
}
public static <T> List<List<T>> initializeListOfListsOfT(int m, int n, T initValue) {
return IntStream
.range(0, m)
.boxed()
.map(i -> new ArrayList<T>(IntStream
.range(0, n)
.boxed()
.map(j -> initValue)
.collect(Collectors.toList()))
)
.collect(Collectors.toList());
}
public static List<List<Integer>> initializeListOfListsOfInt(int m, int n, int initValue) {
return IntStream
.range(0, m)
.boxed()
.map(i -> new ArrayList<>(IntStream
.range(0, n)
.map(j -> initValue)
.boxed()
.collect(Collectors.toList()))
)
.collect(Collectors.toList());
}
}
Output:
[[-, -, -], [-, -, -], [-, -, -], [-, -, -]]
[[7, 7, 7], [7, 7, 7], [7, 7, 7], [7, 7, 7]]
Side note for those wondering about IntStream
:
IntStream
.range(0, m)
.boxed()
is equivalent to
Stream
.iterate(0, j -> j + 1)
.limit(n)
You can have ArrayList with elements which would be ArrayLists itself.
I can think of An Array inside an Array or a Guava's MultiMap?
e.g.
ArrayList<ArrayList<String>> matrix = new ArrayList<ArrayList<String>>();
Source: Stackoverflow.com