Do you know some neat Java libaries that allow you to make cartesian product of two (or more) sets?
For example: I have three sets. One with objects of class Person, second with objects of class Gift and third with objects of class GiftExtension.
I want to generate one set containing all possible triples Person-Gift-GiftExtension.
The number of sets might vary so I cannot do this in nested foreach loop.
Under some conditions my application needs to make a product of Person-Gift pair, sometimes it is triple Person-Gift-GiftExtension, sometimes there might even be sets Person-Gift-GiftExtension-GiftSecondExtension-GiftThirdExtension, etc.
Edit: Previous solutions for two sets removed. See edit history for details.
Here is a way to do it recursively for an arbitrary number of sets:
public static Set<Set<Object>> cartesianProduct(Set<?>... sets) {
if (sets.length < 2)
throw new IllegalArgumentException(
"Can't have a product of fewer than two sets (got " +
sets.length + ")");
return _cartesianProduct(0, sets);
}
private static Set<Set<Object>> _cartesianProduct(int index, Set<?>... sets) {
Set<Set<Object>> ret = new HashSet<Set<Object>>();
if (index == sets.length) {
ret.add(new HashSet<Object>());
} else {
for (Object obj : sets[index]) {
for (Set<Object> set : _cartesianProduct(index+1, sets)) {
set.add(obj);
ret.add(set);
}
}
}
return ret;
}
Note that it is impossible to keep any generic type information with the returned sets. If you knew in advance how many sets you wanted to take the product of, you could define a generic tuple to hold that many elements (for instance Triple<A, B, C>), but there is no way to have an arbitrary number of generic parameters in Java.
This is a pretty old question, but why not use Guava's cartesianProduct?
The method below creates the cartesian product of a list of list of strings:
protected <T> List<List<T>> cartesianProduct(List<List<T>> lists) {
List<List<T>> resultLists = new ArrayList<List<T>>();
if (lists.size() == 0) {
resultLists.add(new ArrayList<T>());
return resultLists;
} else {
List<T> firstList = lists.get(0);
List<List<T>> remainingLists = cartesianProduct(lists.subList(1, lists.size()));
for (T condition : firstList) {
for (List<T> remainingList : remainingLists) {
ArrayList<T> resultList = new ArrayList<T>();
resultList.add(condition);
resultList.addAll(remainingList);
resultLists.add(resultList);
}
}
}
return resultLists;
}
Example:
System.out.println(cartesianProduct(Arrays.asList(Arrays.asList("Apple", "Banana"), Arrays.asList("Red", "Green", "Blue"))));
would yield this:
[[Apple, Red], [Apple, Green], [Apple, Blue], [Banana, Red], [Banana, Green], [Banana, Blue]]
The number of sets might vary so I
cannot do this in nested foreach loop.
Two hints:
A x B x C = A x (B x C)
Recursion
Index-based solution
Working with the indices is an alternative that is fast and memory-efficient and can handle any number of sets. Implementing Iterable allows easy use in a for-each loop. See the #main method for a usage example.
public class CartesianProduct implements Iterable<int[]>, Iterator<int[]> {
private final int[] _lengths;
private final int[] _indices;
private boolean _hasNext = true;
public CartesianProduct(int[] lengths) {
_lengths = lengths;
_indices = new int[lengths.length];
}
public boolean hasNext() {
return _hasNext;
}
public int[] next() {
int[] result = Arrays.copyOf(_indices, _indices.length);
for (int i = _indices.length - 1; i >= 0; i--) {
if (_indices[i] == _lengths[i] - 1) {
_indices[i] = 0;
if (i == 0) {
_hasNext = false;
}
} else {
_indices[i]++;
break;
}
}
return result;
}
public Iterator<int[]> iterator() {
return this;
}
public void remove() {
throw new UnsupportedOperationException();
}
/**
* Usage example. Prints out
*
* <pre>
* [0, 0, 0] a, NANOSECONDS, 1
* [0, 0, 1] a, NANOSECONDS, 2
* [0, 0, 2] a, NANOSECONDS, 3
* [0, 0, 3] a, NANOSECONDS, 4
* [0, 1, 0] a, MICROSECONDS, 1
* [0, 1, 1] a, MICROSECONDS, 2
* [0, 1, 2] a, MICROSECONDS, 3
* [0, 1, 3] a, MICROSECONDS, 4
* [0, 2, 0] a, MILLISECONDS, 1
* [0, 2, 1] a, MILLISECONDS, 2
* [0, 2, 2] a, MILLISECONDS, 3
* [0, 2, 3] a, MILLISECONDS, 4
* [0, 3, 0] a, SECONDS, 1
* [0, 3, 1] a, SECONDS, 2
* [0, 3, 2] a, SECONDS, 3
* [0, 3, 3] a, SECONDS, 4
* [0, 4, 0] a, MINUTES, 1
* [0, 4, 1] a, MINUTES, 2
* ...
* </pre>
*/
public static void main(String[] args) {
String[] list1 = { "a", "b", "c", };
TimeUnit[] list2 = TimeUnit.values();
int[] list3 = new int[] { 1, 2, 3, 4 };
int[] lengths = new int[] { list1.length, list2.length, list3.length };
for (int[] indices : new CartesianProduct(lengths)) {
System.out.println(Arrays.toString(indices) //
+ " " + list1[indices[0]] //
+ ", " + list2[indices[1]] //
+ ", " + list3[indices[2]]);
}
}
}
Here is an Iterable, which allows you to use a simplified for-loop:
import java.util.*;
// let's begin with the demo. Instead of Person and Gift,
// I use the well known char and int.
class CartesianIteratorTest {
public static void main (String[] args) {
List <Object> lc = Arrays.asList (new Object [] {'A', 'B', 'C', 'D'});
List <Object> lC = Arrays.asList (new Object [] {'a', 'b', 'c'});
List <Object> li = Arrays.asList (new Object [] {1, 2, 3, 4});
// sometimes, a generic solution like List <List <String>>
// might be possible to use - typically, a mixture of types is
// the common nominator
List <List <Object>> llo = new ArrayList <List <Object>> ();
llo.add (lc);
llo.add (lC);
llo.add (li);
// Preparing the List of Lists is some work, but then ...
CartesianIterable <Object> ci = new CartesianIterable <Object> (llo);
for (List <Object> lo: ci)
show (lo);
}
public static void show (List <Object> lo) {
System.out.print ("(");
for (Object o: lo)
System.out.print (o + ", ");
System.out.println (")");
}
}
How is it done? We need an Iterable, to use the simplified for-loop, and an Iterator has to be returned from the Iterable.
We return a List of Objects - this could be a Set instead of List, but Set has no indexed access, so it would be a bit more complicated, to implement it with Set instead of List. Instead of a generic solution, Object would have been fine for many purposes, but generics allow for more restrictions.
class CartesianIterator <T> implements Iterator <List <T>> {
private final List <List <T>> lilio;
private int current = 0;
private final long last;
public CartesianIterator (final List <List <T>> llo) {
lilio = llo;
long product = 1L;
for (List <T> lio: lilio)
product *= lio.size ();
last = product;
}
public boolean hasNext () {
return current != last;
}
public List <T> next () {
++current;
return get (current - 1, lilio);
}
public void remove () {
++current;
}
private List<T> get (final int n, final List <List <T>> lili) {
switch (lili.size ())
{
case 0: return new ArrayList <T> (); // no break past return;
default: {
List <T> inner = lili.get (0);
List <T> lo = new ArrayList <T> ();
lo.add (inner.get (n % inner.size ()));
lo.addAll (get (n / inner.size (), lili.subList (1, lili.size ())));
return lo;
}
}
}
}
The mathematical work is done in the 'get'-method. Think about 2 sets of 10 elements. You have a total of 100 combinations, enumerated from 00, 01, 02, ... 10, ... to 99. For 5 X 10 elements 50, for 2 X 3 elements 6 combinations. The modulo of the sublist size helps to pick one element for each iteration.
Iterable i the least interesting thing here:
class CartesianIterable <T> implements Iterable <List <T>> {
private List <List <T>> lilio;
public CartesianIterable (List <List <T>> llo) {
lilio = llo;
}
public Iterator <List <T>> iterator () {
return new CartesianIterator <T> (lilio);
}
}
To implement Iterable, which allows the for-each kind of loop, we have to implement iterator (), and for Iterator we have to implement hasNext (), next () and remove ().
Result:
(A, a, 1, )
(B, a, 1, )
(C, a, 1, )
(D, a, 1, )
(A, b, 1, )
(B, b, 1, )
(C, b, 1, )
(D, b, 1, )
...
(A, a, 2, )
...
(C, c, 4, )
(D, c, 4, )
Here is an Iterator that gives the cartesian product of a two-dimensional array, where the arrays components represent the sets from the question (one can always convert actual Sets to arrays):
public class CartesianIterator<T> implements Iterator<T[]> {
private final T[][] sets;
private final IntFunction<T[]> arrayConstructor;
private int count = 0;
private T[] next = null;
public CartesianIterator(T[][] sets, IntFunction<T[]> arrayConstructor) {
Objects.requireNonNull(sets);
Objects.requireNonNull(arrayConstructor);
this.sets = copySets(sets);
this.arrayConstructor = arrayConstructor;
}
private static <T> T[][] copySets(T[][] sets) {
// If any of the arrays are empty, then the entire iterator is empty.
// This prevents division by zero in `hasNext`.
for (T[] set : sets) {
if (set.length == 0) {
return Arrays.copyOf(sets, 0);
}
}
return sets.clone();
}
#Override
public boolean hasNext() {
if (next != null) {
return true;
}
int tmp = count;
T[] value = arrayConstructor.apply(sets.length);
for (int i = 0; i < value.length; i++) {
T[] set = sets[i];
int radix = set.length;
int index = tmp % radix;
value[i] = set[index];
tmp /= radix;
}
if (tmp != 0) {
// Overflow.
return false;
}
next = value;
count++;
return true;
}
#Override
public T[] next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
T[] tmp = next;
next = null;
return tmp;
}
}
The basic idea is to treat count as a multi-radix number (digit i has its own radix which equals the length of the i'th "set"). Whenever we have to resolve next (that is, when hasNext() is called and next is null), we decompose the number into its digits in this multi-radix. These digits are now used as the indices from which we draw elements from the different sets.
Example use:
String[] a = { "a", "b", "c"};
String[] b = { "X" };
String[] c = { "r", "s" };
String[][] abc = { a, b, c };
Iterable<String[]> it = () -> new CartesianIterator<>(abc, String[]::new);
for (String[] s : it) {
System.out.println(Arrays.toString(s));
}
Output:
[a, X, r]
[b, X, r]
[c, X, r]
[a, X, s]
[b, X, s]
[c, X, s]
If one doesn't like arrays, the code is trivially convertible into using collections.
I guess this is more or less similar to the answer given by "user unknown", only without recursion and collections.
You can get the Cartesian product of an arbitrary number of sets of different types and store it into a set of sets of objects Set<Set<Object>> using Java 9 Streams as follows:
Try it online!
public static Set<Set<Object>> cartesianProduct(Set<?>... sets) {
// incorrect incoming data
if (sets == null) return Collections.emptySet();
return Arrays.stream(sets)
// non-null and non-empty sets
.filter(set -> set != null && set.size() > 0)
// represent each set element as Set<Object>
.map(set -> set.stream().map(Set::<Object>of)
// Stream<Set<Set<Object>>>
.collect(Collectors.toSet()))
// summation of pairs of inner sets
.reduce((set1, set2) -> set1.stream()
// combinations of inner sets
.flatMap(inner1 -> set2.stream()
// merge two inner sets into one
.map(inner2 -> Stream.of(inner1, inner2)
.flatMap(Set::stream)
.collect(Collectors.toCollection(
LinkedHashSet::new))))
// set of combinations
.collect(Collectors.toCollection(LinkedHashSet::new)))
// returns Set<Set<Object>>, otherwise an empty set
.orElse(Collections.emptySet());
}
public static void main(String[] args) {
Set<Integer> set1 = Set.of(1, 2, 3);
Set<String> set2 = Set.of("A", "B", "C");
Set<Object> set3 = Set.of(new Time(0));
Set<Set<Object>> sets = cartesianProduct(set1, set2, set3);
// output
sets.forEach(System.out::println);
}
Output:
[1, A, 03:00:00]
[1, B, 03:00:00]
[1, C, 03:00:00]
[2, A, 03:00:00]
[2, B, 03:00:00]
[2, C, 03:00:00]
[3, A, 03:00:00]
[3, B, 03:00:00]
[3, C, 03:00:00]
See also: How to create a data structure similar to the cartesian product of three lists of different types?
Yes, there is Functional Java.
For a set s:
s.bind(P.p2(), s);
a simple solution, for example, for Integer set should be as follows:
void printCombination(List<Set<Integer>> listSet, Set<Integer> combination) {
if (listSet.isEmpty()) {
System.out.println("a combination :" + combination);
return;
}
Set<Integer> intSet = listSet.get(0);
for (Integer it : intSet) {
Set<Integer> combination1 = new HashSet<Integer>();
combination1.addAll(combination);
combination1.add(it);
List<Set<Integer>> listSet1 = new ArrayList<Set<Integer>>();
listSet1.addAll(listSet);
listSet1.remove(0);
this.printCombination(listSet1, combination1);
}
}
You can apply a simple generator interferace named Seq via this library. Unlike Guava's cartesianProduct, the sets/lists/iterables do not need to be within the same generic type bound B, all types are welcome. And all you need to do is writing the product as normal nested for-loops.
public static void main(String[] args) {
List<String> ls1 = Arrays.asList("a", "b");
List<Integer> ls2 = Arrays.asList(1, 2);
List<Character> ls3 = Arrays.asList('x', 'y');
Seq<String> seq = c -> {
for (String s : ls1) {
for (Integer i : ls2) {
for (Character d : ls3) {
c.accept(s + i + d);
}
}
}
};
System.out.println(seq.toSet());
}
The result would be
[a2x, a1y, b1x, b2y, a1x, a2y, b2x, b1y]
Related
I have this method to merge 2 sorted arrays into one sorted array:
public void merge(T[] a, int l1, int r1, T[] b, int l2, int r2, T[] c, int l3) {
while (l1 < r1 && l2 < r2) {
if (a[l1].compareTo(b[l2]) < 0) {
c[l3++] = a[l1++];
} else
c[l3++] = b[l2++];
}
while (l1 < r1)
c[l3++] = a[l1++];
while (l2 < r2)
c[l3++] = b[l2++];
}
But now I want to do it with 4 arrays at once.
I tried really long to come up with a solution, but wasn’t really successful. Does somebody have an idea how to do it?
There is a much simpler way using Java8 streams than doing this by hand:
combine all arrays into one stream (i've used 2 but you can use as many as you want to):
int[] arr1 = {1, 7, 10};
int[] arr2 = {1, 2, 4, 9};
Stream<int[]> ints = Stream.of(arr1, arr2);
then flatMap and sort them in a stream:
IntStream intStream = ints.flatMapToInt(Arrays::stream).sorted();
and when you print them you will see all the numbers sorted:
intStream.forEach(System.out::println);
1
1
2
4
7
9
10
combined in a function, it could look something like this:
public int[] merge(int[]... arrays) {
return Stream.of(arrays)
.flatMapToInt(Arrays::stream)
.sorted()
.toArray();
}
EDIT: The advantage of streams is, that you can further modify the values as you like. e.g. by leveraging the distinct function you can easily remove duplicates:
intStream = intStream.distinct();
intStream.forEach(System.out::println);
1
2
4
7
9
10
I've generalized the problem to "merging N sorted arrays into a single sorted array".
The code provided in the question utilizes generics. But it introduces a problem because arrays are not type-safe. In short, there's a substantial difference in their behavior: arrays are covariant and, on the other hand, generics are invariant. Due to that, compiler will not be abler to identify a problem when generics and arrays are mixed. It's a good practice to avoid usage of generic arrays.
Also, I've taken into account that it is clearly an algorithmic problem (therefore its audience broader than readers who have a deep insight in Java, which is required to grasp generic-based implementation) I've decided to create two flavors of solution one using arrays exclusively, another with generics and Collections framework.
Non-generic version
Below is the description of how to merge an arbitrary number of sorted arrays of primitives:
find the total number of elements and create a resulting array based on it;
define an array that will maintain a current position in each of the source arrays;
using a nested for loop for each position in the resulting array, pick the lowest value of all currently accessible values.
The time complexity of this algorithm is O(n * m) (where n - is the total number of elements in all arrays and m is the number of arrays).
The implementation might look like this:
public static int[] mergeNSorted(int[]... arrays) {
int[] result = new int[getTotalLength(arrays)];
int[] positions = new int[arrays.length]; // position for each array
for (int pos = 0; pos < result.length; pos++) {
int minCurVal = Integer.MAX_VALUE;
int curArr = 0;
for (int i = 0; i < arrays.length; i++) {
if (positions[i] < arrays[i].length && arrays[i][positions[i]] < minCurVal) {
minCurVal = arrays[i][positions[i]];
curArr = i;
}
}
result[pos] = minCurVal;
positions[curArr]++;
}
return result;
}
public static int getTotalLength(int[][] arrays) {
long totalLen = 0;
for (int[] arr : arrays) totalLen += arr.length;
if (totalLen > Integer.MAX_VALUE) throw new IllegalArgumentException("total length exceeded Integer.MAX_VALUE");
return (int) totalLen;
}
main() - demo
public static void main(String[] args) {
int[][] input =
{{1, 3}, {}, {2, 6, 7}, {10}, {4, 5, 8, 9}};
System.out.println(Arrays.toString(mergeNSorted(input)));
}
Output
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Generic version
In this version, input considered to be a list containing multiple lists of generic type T which expected to implement Comparable interface.
This solution enhances the array-based implementation provided above, reducing the overall time complexity to O(n * log m) (where n - is the total number of elements in all arrays and m is the number of arrays).
Instead of performing m iteration for each resulting element it maintains a PriorityQueue, which in this case represents a Min-Heap (i.e. when a head element is being retrieved from it, it'll have the lowest value of all the elements that are present in the queue).
Every element in queue wraps the value of a particular element retrieved from one of the given lists, as well the data regarding the source of this value (i.e. an index of the list and a position inside this list).
This wrapper over the element of the nested list can be represented by the class shown below.
public class ElementWrapper<V extends Comparable<V>> implements Comparable<ElementWrapper<V>> {
private V value;
private int listIndex;
private int position;
public ElementWrapper(V value, int listIndex, int position) {
this.value = value;
this.listIndex = listIndex;
this.position = position;
}
// getters
#Override
public int compareTo(ElementWrapper<V> o) {
return value.compareTo(o.getValue());
}
}
Note, that this class implements the of Comparable interface based on the value of wrapped list element.
The queue is being prepopulated with the first element of each non-empty list. And then until the queue is not empty, its lowest element is being removed and gets added to the resulting list. Also, if a list to which the latest element retrieved from the queue points, has more elements, the next of them will be added into the queue.
Note that both operations of adding a new element into the priority queue add() and removing its head element remove() according to the documentation has a cost of O(n) time (where n is the number of elements in the queue).
The same time complexity can be achieved by utilizing a TreeSet instead, but in practice PriorityQueue will perform better because a heap is easier to maintain than a red-black tree.
The code might look like this:
public static <T extends Comparable<T>> List<T> mergeNSorted(List<List<T>> lists) {
List<T> result = new ArrayList<>();
Queue<ElementWrapper<T>> queue = getInitializedQueue(lists);
while (!queue.isEmpty()) {
ElementWrapper<T> next = queue.remove();
result.add(next.getValue());
if (next.getPosition() + 1 < lists.get(next.getListIndex()).size()) {
queue.add(new ElementWrapper<>(lists.get(next.getListIndex()).get(next.getPosition() + 1),
next.getListIndex(),
next.getPosition() + 1));
}
}
return result;
}
public static <T extends Comparable<T>> Queue<ElementWrapper<T>> getInitializedQueue(List<List<T>> lists) {
Queue<ElementWrapper<T>> queue = new PriorityQueue<>();
for (int i = 0; i < lists.size(); i++) {
if (lists.get(i).isEmpty()) continue;
queue.add(new ElementWrapper<>(lists.get(i).get(0), i, 0));
}
return queue;
}
main() - demo
public static void main(String[] args) {
List<List<Integer>> genericInput =
List.of(List.of(1, 3), List.of(), List.of(2, 6, 7), List.of(10), List.of(4, 5, 8, 9));
System.out.println(mergeNSorted(genericInput));
}
Output
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
I'm not a Java programmer so I'll just give Pythonesque pseudo-code.
First turn each non-emptyarray into a triplet:
(next_value, index, array)
Now put those into a priority queue sorted by next value.
while 0 < queue.size():
(next_value, index, array) = queue.poll()
answer.append(next_value)
if index+1 < array.length:
queue.add((array[index+1], index+1, array))
If you have k arrays, this will take O(log(k)) comparisons per element produced.
Sadly, Java does not seem to have anything corresponding to the swaptop method. I practice if one array has a run of values, using .peek() to get the top element then .swaptop(...) if you can will let you go through those runs with O(1) work per element.
This could also be an good example using List<String> in addition to int[]
import org.testng.annotations.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class TestClass {
public static List<String> list(String... elems) {
return new ArrayList<>(Arrays.asList(elems));
}
public static List<String> mergedListSorted(List<String>... listsVarArgs) {
return Stream.of(listsVarArgs).flatMap(List::stream).sorted().collect(Collectors.toList());
}
#Test
public void sortedListsTest() {
// Sorted sub lists
List<String> AGMS = list("A", "G", "M", "S");
List<String> BHNT = list("B", "H", "N", "T");
List<String> CIOU = list("C", "I", "O", "U");
List<String> DJPV = list("D", "J", "P", "V");
List<String> EKQW = list("E", "K", "Q", "W");
List<String> FLRX = list("F", "L", "R", "X");
System.out.println(mergedListSorted(AGMS, BHNT, CIOU, DJPV, EKQW, FLRX));
System.out.println(mergedListSorted(BHNT, BHNT, CIOU, BHNT));
}
}
The according output of two examples:
[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X]
[B, B, B, C, H, H, H, I, N, N, N, O, T, T, T, U]
I have created an Iterable in Java that sort keys by their occurrence in decending order. For example if I have this array: [3, 3, 3, 2, 2, 1] I will get the output 3 2 1. Though there is one problem with my code. Whenever the occurrence of a key appears twice it overwrites the old one. For example if i have this array: [3, 3, 3, 2, 2, 1, 1, 0] I will get the output 3 1 0 when I want ot get 3 2 1 0. Here is what my Iterable looks like:
Iterable<Key> keys()
{
ArrayList<Key> keyList = new ArrayList<>();
ArrayList<Integer> occurrenceList = new ArrayList<>();
Map<Integer, Key> sortedMap = new TreeMap<Integer, Key>();
ArrayList <Key> temp = new ArrayList<>();
int j = 0;
//puts keys in one arraylist and occurrences in another arraylist
for (int i = 1; i < size; i++)
{
if (keys[i] != null)
{
keyList.add((Key) keys[i].getKey());
occurrenceList.add(keys[i].counter);
}
}
//puts each key and occurrence in a treemap so that they are "linked"
//This is where the overwriting is happening
for(Integer num : occurrenceList)
{
sortedMap.put(occurrenceList.get(j), keyList.get(j));
j++;
}
//puts the key values in another arraylist in the sorted order from the sortedMap
for(Key s : sortedMap.values())
{
temp.add(s);
}
//flips it to decending order
Collections.reverse(temp);
return temp;
}
This is where the problem happens:
for(Integer num : occurrenceList)
{
sortedMap.put(occurrenceList.get(j), keyList.get(j));
j++;
}
And this is how i test my code:
public static void main(String[] args) {
LinearProbingHashSet<Integer> list = new LinearProbingHashSet<>(30);
list.insert(3);
list.insert(3);
list.insert(3);
list.insert(2);
list.insert(2);
list.insert(1);
for(int i : list.keys())
{
System.out.println(i);
}
}
It is also worth noting that I am not using a Key array but rather a HashElement array. Hashelement is my own class that looks like this:
public class HashElement<Key> implements Comparable<HashElement<Key>> {
Key key;
int counter;
HashElement(Key key)
{
this.key = key;
this.counter = 1;
}
HashElement(Key key, int counter)
{
this.key = key;
this.counter = counter;
}
int getFrequency()
{
return this.counter;
}
Key getKey()
{
return this.key;
}
public int compareTo(HashElement that) {
if(this.counter > that.counter)
{
return 1;
}
else if(this.counter < that.counter)
{
return -1;
}
else
{
return 0;
}
}
}
I know my code is probably not optimised but right now I want to focus on getting it to work. Also I am not 100% sure what I am doing. How would you go about fixing the overwrite problem?
The problem of your code lies in this statement:
sortedMap.put(occurrenceList.get(j), keyList.get(j));
Consider the array = [3,3,3,2,2,1,1,0], when this part executes
for (int i = 1; i < size; i++)
{
if (keys[i] != null)
{
keyList.add((Key) keys[i].getKey());
occurrenceList.add(keys[i].counter);
}
}
The keyList is [3, 2, 1, 0], and occurrenceList is [3, 2, 2, 1].
Now, when you try to put the elements of occurrenceList in a map, like this:
for(Integer num : occurrenceList)
{
sortedMap.put(occurrenceList.get(j), keyList.get(j));
j++;
}
The 2 at index-2 in occurrenceList, overrides in the map, the 2 at index-1, because Maps in Java, inserting a key twice will override its previous value, it will not store duplicate. You can do something like this:
for(Integer num : occurrenceList)
{
if(sortedMap.containsKey(num)){
sortedMap.get(num).add(keyList.get(j));
}else{
sortedMap.put(num, Arrays.asList(keyList.get(j)));
}
j++;
}
//puts the key values in another arraylist in the sorted order from the sortedMap
for(List<Key> s : sortedMap.values())
{
Collections.sort(s, new Comparator<Key>(){
public int compare(Key k1, Key k2){
return k1.getKey() - k2.getKey();
}
});
temp.addAll(s);
}
And declare sortedMap like this:
Map<Integer, List<Key>> sortedMap = new TreeMap<Integer, List<Key>>();
Here is one approach to demonstrate some concepts. I suggest you use it as a guide to understanding how the various capabilities work. Those can then be applied to your own solution. It is especially important to use the Java API Documentation to research the various Java API features and classes (streams, interfaces, comparators, etc) to understand how they are being used.
List<Integer> list1 =
List.of(3, 2, 5, 3, 3, 1, 0, 2, 5, 5, 5, 5, 0, 0, 2);
MySpecialSet<Integer> list = new MySpecialSet<>(list1);
// the enhanced for loop may be used because of the Iterable interface
for (int v : list) {
System.out.printf("%s ", v);
}
System.out.println();
// Using an array of Objects
Integer[] ints = { 1, 3, 3, 3, 2, 2, 4, 4, 4, 4, 6, 6, 6, 6,
6, 6, 5, 5, 5, 5, 5 };
MySpecialSet<Integer> list2 = new MySpecialSet<>(ints);
// This time using an explicit iterator.
Iterator<Integer> it = list2.iterator();
while (it.hasNext()) {
System.out.printf("%s ", it.next());
}
System.out.println();
prints
5 3 2 0 1
6 5 4 3 2 1
Here is the explanation of the class. This class will accept either an Array or a List of elements that implement the Comparable interface which is required for sorting of the elements.
this class implements the Iterable interface to return an Iterator. This allows the enhanced for loop to operate over the list.
when the iterator is obtained, either directly or implicitly, it converts the supplied list to meet the requirements.
first stream the keys and collect them in a map using a frequency count.
then stream the entryset of that map and sort based first on the frequency and if the frequencies are equal, then the key itself. And do these in reverse order.
then, the keys are returned in an internal list to be used by the iterator.
class MySpecialSet<T extends Comparable<T>> implements Iterable<T> {
private ArrayList<T> list;
public MySpecialSet(T[] v) {
list = new ArrayList<>(Arrays.asList(v));
}
public MySpecialSet(Collection<T> coll) {
this.list = new ArrayList<>(coll);
}
public Iterator<T> iterator() {
return new MyIterator();
}
private class MyIterator implements Iterator<T> {
private Iterator<T> it;
// comparator to direct the sort for comparing the may entries. First compare
// on the value (count) then if the count is equal, compare on the key
Comparator<Entry<T, Long>> comp = Entry
.<T, Long>comparingByValue()
.thenComparing(Entry.comparingByKey()).reversed();
public MyIterator() {
// This will essentially be a set since no duplicate
// entries will be present
List<T> result = list.stream()
// frequency count and collect into map
.collect(Collectors.groupingBy(k -> k,
Collectors.counting()))
// then stream the entries and sort as explained
// above using comparator.
.entrySet().stream().sorted(comp)
// then collect the keys into a list
.map(Entry::getKey).collect(Collectors.toList());
it = result.iterator();
}
// simply use the iterator of the newly created list.
public boolean hasNext() {
return it.hasNext();
}
public T next() {
return it.next();
}
}
}
Given a Java List with 21 elements.
What is the best way to create three new lists with:
A = 0, 3, 6, ... indexed elements from source
B = 1, 4, 7, ...
C = 2 ,5, 8, 11, 14, 17, 20
Is it possible without looping?
Well you could write a wrapper class which is able to provide a read-only "view" onto a list given a multiple (3 in this case) and an offset (0, 1 and 2). When asked for the item at a particular index, it would have to multiply by the "multiple" and add the offset, then look into the original list. (Likewise for the other operations.)
It would be simpler to loop though... what's the context here? What are you really trying to achieve?
Here's an example of what Jon mentioned (if of course you really don't want to just loop). The name isn't great... I'm not sure what a good name for such a thing would be.
public class OffsetList<E> extends AbstractList<E> {
private final List<E> delegate;
private final int offset;
private final int multiple;
public static <E> OffsetList<E> create(List<E> delegate, int offset, int multiple) {
return new OffsetList<E>(delegate, offset, multiple);
}
private OffsetList(List<E> delegate, int offset, int multiple) {
this.delegate = delegate;
this.offset = offset;
this.multiple= multiple;
}
#Override public E get(int index) {
return delegate.get(offset + (index * multiple));
}
#Override public int size() {
int offsetToEnd = delegate.size() - offset;
return (int) Math.ceil(offsetToEnd / (double) multiple);
}
}
Example use:
List<Integer> numbers = // the numbers 0 to 21 in order
List<Integer> first = OffsetList.create(numbers, 0, 3);
List<Integer> second = OffsetList.create(numbers, 1, 3);
List<Integer> third = OffsetList.create(numbers, 2, 3);
System.out.println(first); // [0, 3, 6, 9, 12, 15, 18, 21]
System.out.println(second); // [1, 4, 7, 10, 13, 16, 19]
System.out.println(third); // [2, 5, 8, 11, 14, 17, 20]
Creating each list is O(1) since they're views. Iterating each list is O(n) where n is the size of the actual view list, not the size of the full list it's based on. This assumes the original list is a random access list... this approach, like index-based iteration, would be very inefficient with a linked list.
Given you saying you're used to functional programming, I'm going to assume you want to split up the lists because you want to do something different to each. If that's the case I would put the filtering logic at the Iterator level.
You could have a wrapping Iterator instead of a wrapping List. It might look something like this:
public <T> Iterable<T> filter(final Iterable<T> allElements, final int offset, final int multiple) {
return new Iterable<T> {
public Iterator<T> iterator() {
return new Iterator<T> {
int index = 0;
Iterator<T> allElementsIt = allElements.iterator();
public boolean hasNext() {
while (allElementsIt.hasNext()) {
if ( isDesiredIndex(index) ) {
return true;
} else {
allElementsIt.next();
index++;
}
}
return false;
}
private boolean isDesiredIndex(int index) {
return (index - offset) % multiple == 0;
}
public T next() {
if ( hasNext() ) {
return allElementsIt.next();
} else {
throw NoSuchElementException();
}
}
public void remove() {...}
}
}
}
}
Then to use it:
for ( ElementType element : filter(elements, 2, 3) ) {
//do something to every third starting with third element
}
Next try :)
class Mod3Comparator implements Comparator<Integer> {
public int compare(Integer a, Integer b) {
if (a % 3 < b % 3 || (a % 3 == b % 3 && a < b)) {
return -1;
}
if (a % 3 > b % 3 || (a % 3 == b % 3 && a > b)) {
return 1;
}
return 0;
}
}
First sort the list taking into consideration the modulo rule, then use the Arrays.copyOfRange method.
Collections.sort(list, new Mod3Comparator());
Integer[] array = new Integer[list.size()];
list.toArray(array);
List<Integer> A = Arrays.asList(Arrays.copyOfRange(array, 0, 7));
List<Integer> B = Arrays.asList(Arrays.copyOfRange(array, 7, 14));
...
Also see this example.
Unfortunately, I can't think of a way of doing so without pretending the arrays are lists are doing the following.
String[] twentyOne = new String[21];
String[] first = new String[3];
first[0] = twentyOne[0];
first[1] = twentyOne[3];
first[2] = twentyOne[6];
// And so on
String[] second = new String[3];
second[0] = twentyOne[1];
second[1] = twentyOne[4];
second[2] = twentyOne[7];
String[] third = new String[15];
third[0] = twentyOne[2];
// You get the picture
I only used arrays in the example because I'm more confident with them, and know them without needing to look at something.
May I ask why you want to avoid looping?
The following Java code:
public static void main(String args[]) {
int[] x = new int[] {1, 2, 3};
int[] y = new int[] {1, 2, 3};
LinkedList<int[]> list = new LinkedList<int[]>();
list.add(x);
System.out.println("List contains y: " + list.contains(y));
}
gives the output
List contains y: false
which makes sense as x and y are references to different memory locations, however there is also a sense in which they are equal (they have the the same elements in the same order).
Is there a data structure which would return true to the query list.contains(y) in this example?
I don't believe there is a Java data structure that would return true for contains() as you have described.
The issue, as you probably know, is that for Java arrays, equals() only tests for Object identity and not "equality" as most would define it.
Since contains() relies on equals() in this case (and most of the time), you're stuck with the given behaviour.
You would have to implement a List that specifically overrode contains() to provide your desired behaviour for Java arrays, probably using Arrays.equals().
My suggestion is to instead use a List instead of an array; you'd then have a List<List<Integer>>. contains() should work in this scenario as it'll use equals() on the underyling List implementation.
You need to define a comparator for your arrays. Then when the list looks up the elements, it will use your comparator to see if they're the same:
public static void main(String args[]) {
int[] x = new int[] {1, 2, 3};
int[] y = new int[] {1, 2, 3};
LinkedList<int[]> list = new LinkedList<int[]>(new Comparator<int[]>() {
#Override
public int compare(int[] a1, int[] a2) {
if(a1 == a2) return 0;
if(a1 == null && a2 != null) return -1;
if(a1 != null && a2 == null) return 1;
if(a1.size() < a2.size()) return -1;
if(a1.size() > a2.size()) return 1;
for(int i = 0; i < a1.size(); i++) {
int comp = a1[i] - a2[i];
if(comp < 0) return -1;
if(comp > 0) return 1;
}
return 0;
}
});
list.add(x);
System.out.println("List contains y: " + list.contains(y));
}
It looks like you're really looking for a Set implementation.
A collection that contains no duplicate elements. More formally, sets contain no pair of elements e1 and e2 such that e1.equals(e2), and at most one null element. As implied
by its name, this interface models the mathematical set abstraction.
If you want to store sets of int values, you can use this Tuple class I wrote a while ago for another question on SO.
Set<Tuple> myTuples = new HashSet<Tuple>();
Tuple<Integer> x = Tuple.create(1, 2, 3);
Tuple<Integer> y = Tuple.create(1, 2, 3);
myTuples.add(x);
System.out.println("Set contains y: " + myTuples.contains(y)); // prints true
If order matters, you can use a SortedSet.
LinkedList uses equals to implement contains, so this should work:
public static void main(String args[]) {
static class Ints {
int[] array;
public Ints(int[] array) {
this.array = array;
}
public boolean equals(Object other) {
if (other instanceof Ints) {
return arraysEqual((Ints) other);
}
}
public boolean arraysEqual(Ints other) {
// check that this.array and other.array are same length and
// have same values. Do a null check somewhere too. :)
}
}
Ints x = new Ints(new int[] {1, 2, 3});
Ints y = new Ints(new int[] {1, 2, 3});
LinkedList<Ints> list = new LinkedList<int[]>();
list.add(x);
System.out.println("List contains y: " + list.contains(y));
}
You would probably want to extend LinkedList into your own custom data structure and define a custom equality method if you wanted anything outside of the standard checking that is in place.
If you could use a Set instead of an array it might be easier. Have a look here or here
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 dimensions it will have.
How can I make a 'dynamically resizable array with 2/+ demensions'?
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.
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);
}
}
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.
ArrayList<ArrayList<String>>
http://download.oracle.com/javase/6/docs/api/java/util/ArrayList.html
http://en.wikipedia.org/wiki/Generics_in_Java
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/
I can think of An Array inside an Array or a Guava's MultiMap?
e.g.
ArrayList<ArrayList<String>> matrix = new ArrayList<ArrayList<String>>();
You can have ArrayList with elements which would be ArrayLists itself.
Wouldn't List<ArrayList<String>> 2dlist = new ArrayList<ArrayList<String>>(); be a better (more efficient) implementation?
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)
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)
}
}
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:
0, 0, 0 = 1
0, 0, 1 = 2
0, 0, 2 = 3
0, 1, 0 = 4
0, 1, 1 = 5
0, 1, 2 = 6
0, 2, 0 = 7
0, 2, 1 = 8
0, 2, 2 = 9
1, 0, 0 = 10
1, 0, 1 = 11
1, 0, 2 = 12
1, 1, 0 = 13
1, 1, 1 = 14
1, 1, 2 = 15
1, 2, 0 = 16
1, 2, 1 = 17
1, 2, 2 = 18
2, 0, 0 = 19
2, 0, 1 = 20
2, 0, 2 = 21
2, 1, 0 = 22
2, 1, 1 = 23
2, 1, 2 = 24
2, 2, 0 = 25
2, 2, 1 = 26
2, 2, 2 = 27
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);
}
}
Add element at specific position
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
remove element
int remove(int row, int column)
{
return list.get(row).remove(column);// del list[row][column]
}
ArrayList<ArrayList<Integer>> C = new ArrayList<ArrayList<Integer>>();
ArrayList<Integer> a = new ArrayList<Integer>();
a.addAll(Arrays.asList(7, 3));
ArrayList<Integer> b = new ArrayList<Integer>();
b.addAll(Arrays.asList(2, 1));
ArrayList<Integer> c = new ArrayList<Integer>();
c.addAll(Arrays.asList(4, 9));
C.addAll(Arrays.asList(a, b, c));
C.forEach(System.out::print);
You can simply use:
ArrayList<ArrayList<T>> multiDimentionalArray = new ArrayList<ArrayList<T>>();
You can change T to whatever data type you need