Java: Concatenating not specified number of 2d Arrays dinamically - java

I know that there were other questions related to this topic.
But this is a little different.
Immagine that you have a program that gets every some amount of time an 2d Object (Object[][]) from the excel and it pass this to one method; this method needs to concatenate this 2d Object, so when it gets a flag that there is no more input, it passes this potentially big 2d object as a result to some other method...
1) You don't know how many excel documents will be sent , so how many 2d object will you get
2) every 2d object can have different num of columns and rows (ok this is not a big problem)
Is there a way in java to concatenate 2d objects into one? Wihout "killing" the memory.
Looking at this accepted anwer
How do you append two 2D array in java properly?
there is an append method, but each time it is called (and in this described case we don't know how many times could be called), it recreates an 2d array, and in my opition is not a best practice for this solution.
Looking at this accepted solution How to concatenate two-dimensional arrays in Java there is used an arraycopy solution, which how i understood is something similar to the previous solution... maybe a little better.
I know that would be possible to use some lists that could somehow rappresents this 2d object, or be parsed at the end in the 2d object, but:
is there any way in java (good practice) to concatenate dinamically unown number of 2d object into 1?
tnx

It look like you need ArrayList< ArrayList < Object > > instead of Object[][]. If you use ArrayList, the different num of columns and rows aren't problems at all, and you not "killing" the memory if you use addAll method. Moreover, you could use a core Java methods to concat ot ArrayLists without create your own manual methods.
For example, you can use something like this:
public List<ArrayList<Object>> concat (List<ArrayList<Object>> list1, List<ArrayList<Object>> list2) {
if(list1.size() > list2.size()) {
List<ArrayList<Object>> listBig = new ArrayList(list1); // or just list1 if we can change list1
List<ArrayList<Object>> listSmall = list2;
} else {
List<ArrayList<Object>> listBig = new ArrayList(list2); // or just list1 if we can change list1
List<ArrayList<Object>> listSmall = list1;
}
for(int i = 0; i < listSmall.size(); i++) {
listBig[i].addAll(listSmall[i]);
}
return listBig;
}

Related

How can I add (+) an integer to an element in a 2-dimensional ArrayList?

I'm trying to add 1 to an integer in a 2-dimensional ArrayList.
I'm using the set() method with the element + 1 as the second argument, but the "+ 1" isn't working. When I retrieve the element, it defines it as an object, not an integer. How do I get around this?
Code:
ArrayList<ArrayList> inventoryList = new ArrayList(
Arrays.asList(new ArrayList<String>(), new ArrayList<Integer>()));
...
(inventoryList.get(1)).set(i, ((inventoryList.get(1)).get(i) + 1));
Error:
Main.java:47: error: bad operand types for binary operator '+'
(inventoryList.get(1)).set(i, ((inventoryList.get(1)).get(i) + 1));
^
My code is at this ideone page. This code is translated from python and I'm currently debugging it so don't worry about the other errors.
ArrayList<ArrayList> inventoryList = ...
You are using the raw variant of ArrayList for your inner lists, such an ArrayList indeed contains Objects instead of Integers. You shouldn't use those raw ArrayLists and instead use generic ones:
What is a raw type and why shouldn't we use it?
Looking at your code a bit more, it seems that inventoryList is supposed to contain two lists, one that contains the items you have (as strings) and one that contains how many you have (as integers) where you can find how many you have of the item at index i in the first list by looking in the second list at that same index i.
If that is correct there are multiple ways to fix this, indeed, casting the Objects to Integers works, but then you are still using raw types, which you probably shouldn't. To fix this you should just not keep the ArrayList<String> and the ArrayList<Integer> in the same list. You could just have:
ArrayList<String> inventoryItems = ...
ArrayList<Integer> inventoryItemCounts = ...
separately (you don't need a list if it always contains exactly 2 items, a list of strings and a list of integers). However a cleaner solution would be, as was suggested in the comments by user2418306, to use a map
Map<String, Integer> inventory = ...
http://docs.oracle.com/javase/7/docs/api/java/util/Map.html, that way each string (item) in your inventory has exactly one corresponding integer (number you have of that item) and you don't have to get that by using the "at the same index" trick.
Looking at you code a bit though, I would say that more is going wrong with the inventory. You print your inventory using:
for (int i = 0; i < inventoryList.size(); i++){
System.out.println((inventoryList.get(1)).get(i) + " : " + (inventoryList.get(0)).get(i));
}
and you iterate through it in that way in other places as well. However, if i'm not misunderstanding anything, inventoryList.size() is always going to be 2 (the inventoryList contains 2 lists, one of strings and one of integer). To get the number of distinct items (strings) in your inventory you'd have to do inventoryList.get(0).size() (or inventoryList.get(1).size() because that is going to be the same). However, things will get easier if you chose a better datatype for your inventory. I would look into the mentioned Map. Using that, you easily get the correct number using inventory.size().
You can solve your problem by casting to Integer
inventoryList.get(1).set(i, (Integer) inventoryList.get(1).get(i)+1);
Of course first take a look on comments below your question to see how to properly init your list, so you wont need explicit cast.
The way it is declared, your lists are list of Object. You need to cast the result from second get() with (Integer), like:
inventoryList.get(1).set(i, (Integer)inventoryList.get(1).get(i)+1);
Note: There are unneeded ().

How to add an element at the end of an array?

I want to know how to add or append a new element to the end of an array. Is any simple way to add the element at the end? I know how to use a StringBuffer but I don't know how to use it to add an element in an array. I prefer it without an ArrayList or list. I wonder if the StringBuffer will work on integers.
You can not add an element to an array, since arrays, in Java, are fixed-length. However, you could build a new array from the existing one using Arrays.copyOf(array, size) :
public static void main(String[] args) {
int[] array = new int[] {1, 2, 3};
System.out.println(Arrays.toString(array));
array = Arrays.copyOf(array, array.length + 1); //create new array from old array and allocate one more element
array[array.length - 1] = 4;
System.out.println(Arrays.toString(array));
}
I would still recommend to drop working with an array and use a List.
Arrays in Java have a fixed length that cannot be changed. So Java provides classes that allow you to maintain lists of variable length.
Generally, there is the List<T> interface, which represents a list of instances of the class T. The easiest and most widely used implementation is the ArrayList. Here is an example:
List<String> words = new ArrayList<String>();
words.add("Hello");
words.add("World");
words.add("!");
List.add() simply appends an element to the list and you can get the size of a list using List.size().
To clarify the terminology right: arrays are fixed length structures (and the length of an existing cannot be altered) the expression add at the end is meaningless (by itself).
What you can do is create a new array one element larger and fill in the new element in the last slot:
public static int[] append(int[] array, int value) {
int[] result = Arrays.copyOf(array, array.length + 1);
result[result.length - 1] = value;
return result;
}
This quickly gets inefficient, as each time append is called a new array is created and the old array contents is copied over.
One way to drastically reduce the overhead is to create a larger array and keep track of up to which index it is actually filled. Adding an element becomes as simple a filling the next index and incrementing the index. If the array fills up completely, a new array is created with more free space.
And guess what ArrayList does: exactly that. So when a dynamically sized array is needed, ArrayList is a good choice. Don't reinvent the wheel.
The OP says, for unknown reasons, "I prefer it without an arraylist or list."
If the type you are referring to is a primitive (you mention integers, but you don't say if you mean int or Integer), then you can use one of the NIO Buffer classes like java.nio.IntBuffer. These act a lot like StringBuffer does - they act as buffers for a list of the primitive type (buffers exist for all the primitives but not for Objects), and you can wrap a buffer around an array and/or extract an array from a buffer.
Note that the javadocs say, "The capacity of a buffer is never negative and never changes." It's still just a wrapper around an array, but one that's nicer to work with. The only way to effectively expand a buffer is to allocate() a larger one and use put() to dump the old buffer into the new one.
If it's not a primitive, you should probably just use List, or come up with a compelling reason why you can't or won't, and maybe somebody will help you work around it.
As many others pointed out if you are trying to add a new element at the end of list then something like, array[array.length-1]=x; should do. But this will replace the existing element.
For something like continuous addition to the array. You can keep track of the index and go on adding elements till you reach end and have the function that does the addition return you the next index, which in turn will tell you how many more elements can fit in the array.
Of course in both the cases the size of array will be predefined. Vector can be your other option since you do not want arraylist, which will allow you all the same features and functions and additionally will take care of incrementing the size.
Coming to the part where you want StringBuffer to array. I believe what you are looking for is the getChars(int srcBegin, int srcEnd,char[] dst,int dstBegin) method. Look into it that might solve your doubts. Again I would like to point out that after managing to get an array out of it, you can still only replace the last existing element(character in this case).
one-liner with streams
Stream.concat(Arrays.stream( array ), Stream.of( newElement )).toArray();

Comparing equals between 1D and 2D array in java

I have two questions:
I am using JAVA programming language and I have found some difficulties using Arrays.
Here are some different arrays :
Object [] play1 = {0,3,6};
Object [] play2 = {0,3,6,4};
Object[][] pre = {{0,1,2},{0,3,6},{2,5,8},{6,7,8},{0,4,8},{2,4,6}};
Question 1 : Is it possible to check equals between play1 and pre using deepEquals? I also know that pre is 2D array and play1 is 1D array.
If I want to check whether play1 is equal to pre, then I might check like:
if(Arrays.deepEquals(pre, play1)){
System.out.print("true");
}else{System.out.print("false");}
Is the code correct? Even though is is possible to check equals between 1D and 2D arrays? Or do I have to use ArrayList? I am not that much familiar with ArrayList. Would appreciate if anyone explain with example.
Question 2 : However, if I want to check between play1 and play2, then also the output is false. I want to check between two arrays even though they don't have equal element but if both array consists the same element such as: {0,3,6} can be found in both play1 and play2, then the output must come true..
Thanks.
For Question2:
You can create List of objects and check as follows:
List<Object> play1List = Arrays.asList(play1);
List<Object> play2List = Arrays.asList(play2);
if(play1List.containsAll(play2List) || play2List.containsAll(play1List))
System.out.println("founD");
For Question1:
List<Object> play1List = Arrays.asList(play1);
for (int i =0 ; i< pre.length;i++){
List<Object> preList = Arrays.asList(pre[i]);
if(preList.equals(play1List)){
System.out.println("FounD"+preList);
break;
}
}
From the API docs:
Two array references are considered deeply equal if both are null, or
if they refer to arrays that contain the same number of elements and
all corresponding pairs of elements in the two arrays are deeply
equal.
From your question I understand that you are searching for a subgroup of the array.
I don't think that there's a function for that on the JDK, probably you have to develop your own function iterating the arrays.

Java: Sorting different types of arrays to one another

I need to sort an array based on the positions held in another array.
What I have works, but it is kinda slow, is there a faster/better way to implement this?
2 Parts:
Part1
int i = mArrayName.size();
int temp = 0;
for(int j=0;j<i;j++){
temp = mArrayPosition.get(j);
mArrayName.set(temp, mArrayNameOriginal.get(j));
}
In this part, mArrayPosition is the position I would like the mArrayName to be in.
Ex.
input:
mArrayName= (one, two, three)
mArrayPosition = (2,0,1)
output:
mArrayName= (three, one two)
Part 2
int k=0;
int j=0;
do{
if(mArrayName.get(k)!=mArrayNameOriginal.get(j)){
j++;
}else{
mArrayIdNewOrder.set(k, mArrayId.get(j));
k++;
j=0;
}
}while(k < mArrayName.size());
}
In this part, mArrayName is the reordered name array, mArrayNameOriginal is the original name array.
Ex.
mArrayName = (three, one, two)
mArrayNameOriginal = (one, two, three)
Now I want to compare these two arrays, find which entries are equal and relate that to a new array that has their rowId number in it.
Ex.
input:
mArrayId = (001,002,003)
output:
mArrayIdNewOrder = (003,001,002)
So then I will have mArrayIdNewOrder id's matching up with the correct names in mArrayName.
Like I said these methods work, but is there a faster/better way to do it? I tried looking at Arrays.sort and comparators but they only seem to sort alphabetically or numerically. I saw something like I can create my own rules inside the comparator but it would probably end up being similar to what I already have.
Sorry for the confusing question. I'll try to clear up any ambiguities if needed.
The best performance read I've found is Android's Designing For Performance doc. You are violating a couple of the "Android way" style of doing things that will help you.
You are using multiple internal getters inside each loop for what looks like a simple value. Redo this by accessing the fields directly.
For extra credit, post your performance comparison results! I'd love to see em!
You could use some form of tuple, some class to hold both id and name. You'll just to have a java.util.Comparator that compares it accordingly, both elements will move together and your code will be cleaner.
This data structure might be convenient for the rest of your program... if not, just take things off it again and you're done.
If your order indexes are compact, i.e. from index 0 to size - 1, then just use an array and create the updated list afterwards? About something like
MyArray[] array = new MyArray[size];
for(int j=0;j< size;j++) {
array[ mArrayPosition.get(j) ] = mArrayName.get(j);
}
// create ArrayList from array

Starting Size for an ArrayList

I want to use an ArrayList (or some other collection) like how I would use a standard array.
Specifically, I want it to start with an intial size (say, SIZE), and be able to set elements explicitly right off the bat,
e.g.
array[4] = "stuff";
could be written
array.set(4, "stuff");
However, the following code throws an IndexOutOfBoundsException:
ArrayList<Object> array = new ArrayList<Object>(SIZE);
array.set(4, "stuff"); //wah wahhh
I know there are a couple of ways to do this, but I was wondering if there was one that people like, or perhaps a better collection to use. Currently, I'm using code like the following:
ArrayList<Object> array = new ArrayList<Object>(SIZE);
for(int i = 0; i < SIZE; i++) {
array.add(null);
}
array.set(4, "stuff"); //hooray...
The only reason I even ask is because I am doing this in a loop that could potentially run a bunch of times (tens of thousands). Given that the ArrayList resizing behavior is "not specified," I'd rather it not waste any time resizing itself, or memory on extra, unused spots in the Array that backs it. This may be a moot point, though, since I will be filling the array (almost always every cell in the array) entirely with calls to array.set(), and will never exceed the capacity?
I'd rather just use a normal array, but my specs are requiring me to use a Collection.
The initial capacity means how big the array is. It does not mean there are elements there. So size != capacity.
In fact, you can use an array, and then use Arrays.asList(array) to get a collection.
I recomend a HashMap
HashMap hash = new HasMap();
hash.put(4,"Hi");
Considering that your main point is memory. Then you could manually do what the Java arraylist do, but it doesn't allow you to resize as much you want. So you can do the following:
1) Create a vector.
2) If the vector is full, create a vector with the old vector size + as much you want.
3) Copy all items from the old vector to your new vector.
This way, you will not waste memory.
Or you can implement a List (not vector) struct. I think Java already has one.
Yes, hashmap would be a great ideia.
Other way, you could just start the array with a big capacity for you purpose.

Categories