Understanding Array Indexing in Java - java

I have a brief question about how Java handles arrays. Below is my code:
//import java.util.Arrays;
import static java.lang.System.out;
public class Arrays
{
public static void main(String[] args)
{
String [][] multiArray = new String[10][8];
int k = 1;
while (k <= 61) {out.print('-'); k++;}
out.println ();
for (int i = 0; i < multiArray.length; i++)
{
for (int j = 0; j < multiArray[i].length; j++)
{
multiArray[i][j] = i + "" + j;
out.print ("| " + multiArray[i][j] + " ");
}
out.println ("|");
}
k = 1;
while (k <= 61) {out.print('-'); k++;}
out.println();
}
}
I understand that you have to create a double "for" loop to print out values for both dimensions and that you have to have:
multiArray[i].length
so that it knows to reference the length of the second dimension. I just don't understand how it works.
What I'm confused about is this: At the very beginning of the program, directly after I declare my array, if I write a statement like:
system.out.println (multiArray.length);
It will print the value of 10, which is the length I declared in the first dimension. If I, however, create some random variable like "int a = 0" or "int idontgetthis = 0" and then I write:
system.out.println (multiArray[a].length);
it somehow knows to print the length of the second dimension, 8. So my question is, how does it know how to do this? It's killing me!! lol

Because multiArray is really an array of arrays. So multiArray[a] is a reference to an object. That object is itself an array. That array has a length (8), and a property called length which can be used to return that length.

Basically, it is a concept confusion, by doing:
String[] array;
you are declaring that you will have an array of Strings with an unknown lenght.
A call to: System.out.println(array.length) at this moment will fail with a compilation error because array is not yet initialized (so the compiler can't know how long it is).
By doing:
String[] array = new String[8]
you declare that you will have and array of String and initialize it, specifying it will have space for 8 Strings, the compiler then allocates space for this 8 Strings.
Something important to notice is that even when the compiler now knows that you will store 8 Strings in your array, it will fill it with 8 nulls.
So a call to System.out.println(array.length) at this point will return 8 (Compiler knows the size) but a call to System.out.println(array[1]) will return a Null Pointer Exception (You have 8 nulls in it).
Now, in the example you presented, you are declaring a bidimensional array, this is, an array that will contain other arrays.
Bidimensional arrays are initialized as String[][] multiarray = new String[10][8]; and the logic is the same as in simple arrays, the new String[10][8]; indicates the lenght of the array that contains the other arrays, and the new String[10][8]; indicates the length of the contained arrays.
So doing system.out.println(multiArray[x].length); after initializing multiarray is translated as "What is the length of the Xth contained array?", which the compiler, thanks to your initialization, now knows is 8 for all the contained arrays, even when they are full of nulls at the moment.
Hope it helps to add a bit more understanding!

You could try looking at it like this.
public class Arrays{
public static class EightStrings {
public String[] strings = new String[8];
}
EightStrings[] tenOfThem = new EightStrings[10];
}

Related

Is it possible to pass input.next - after verification - directly to a method as parameters in a variable length argument list? <in java>

package compute.greatest.common.denominator;
import java.util.Scanner;
public class computeGreatestCommonDenominator{
private static Scanner input;
public static void main(String[] args) {
input = new Scanner(System.in);
final int MAX = 20;
final int MIN = 2;
System.out.println("Enter between " + MIN + " and " + MAX + " numbers ( inclusive ) to find the GCD of: ");
for(int i = 0; input.nextInt() != '\n'; i++) { // Normally I would use a for loop to populate input into
if(input.nextInt() < MIN) { // an array and pass the array to method gcd().
System.out.println("ERROR! That number is not within the given constraints! Exiting.......");
System.exit(1); // Any non-zero value, is considered an abnormal exit.
}
}
public static int gcd(int... numbers) {
int greatestCommonDenominator = 0;
}
}
Normally I would use a for loop to populate input into an array and pass that to method gcd(int... numbers). However, that seems to be a case of redundancy to me - passing an array to a variable length argument list, which is treated as an array.
First let me say that I'm still in the learning phase of java and, while understanding variable length argument lists, it's not a confident understanding.
Is there a way to verify the input data and pass it, one by one, in the loop,
directly to the variable length argument list - without using an array?
With an array seems redundant to me and without seems illogical :/
I think you are misunderstanding the use of variable length parameters (varargs) here.
Varargs are nice syntactic sugar because it makes this code:
int[] ints = {1, 2, 3};
gcd(ints);
more elegant:
gcd(1, 2, 3);
That is the purpose of varargs.
If you don't have or expect code like this:
int[] ints = {1, 2, 3};
gcd(ints);
then varargs is not so useful, and certainly don't force your code fit into this varargs thing.
My suggestion is that you keep your code the way it is, or you can change the varargs into a normal array parameter if you don't need to use the varargs feature anywhere else in your code.

Having trouble returning truncated copy of array

I have created a method that is supposed to create a copy of an array of length up to the number of values stored in the original array. So if my original array is of length 10, and I only have 4 values contained in it, then my copy of that array should be of length 3. Here is my code:
public int[] getArray(){
int[] temp = new int[size];
for(int i = 0; i<size; i++){
temp[i] = a[i];
//System.out.print(temp[i] + " ");
}
return temp;
}
I used the print statement to make sure it copies the array and it does. It prints it out when I call this method in my main method. But when I comment out the print statement and use "return temp" it returns the memory location. How would I print the values in the copied array WITHOUT using the JCF or any built in methods? I must use a return statement and the name of the method must remain exactly the same for the specifications our teacher provided. Any help would be appreciated.
To output a whole array, not just its address, use java.util.Arrays.toString().
System.out.println(java.util.Arrays.toString(getArray()));

Read and print sequences and print merged sequence

I suppose to write a Java program using array and method follows: It reads a sequence of strings, each on a separate line, and stores them in an array, let call it input1, with one string per cell, in the order they were read. The sequence ends with an empty line: one with a String of length 0. Same thing with 2nd sequence.Then prints the 1st sequence and 2nd sequence. And then create an array that contains all of the elements of the above two arrays. Merging is done by alternating between the arrays: that is, the first cell of input1 is copied followed by the first cell of input2. Then the second cell of input1 is copied followed by the second cell of input2. Of course, in general, the two sequences may have different lengths, so after the shorter sequence is finished, all elements of the longer sequence are simply appended to the output array. Finally, prints the merged array with 1 string each line.
import java.util.Scanner;
public class A4 {
public static void readInput(Scanner myScanner, String[] input) {
boolean streamEnded = false;
int index = 0;
while (!streamEnded && myScanner.hasNext()) {
String value = myScanner.nextLine();
if (value.length() == 0) {
streamEnded = true;
input[index] = value;
} else {
input[index] = value;
index++;
}
}
}
public static void main(String[] args) {
int size = 5;
String[] input1 = new String[size];
String[] input2 = new String[size];
String[] store = new String[size*2];
Scanner aScanner = new Scanner(System.in);
readInput(aScanner, input1);
for (int i = 0; i < input1.length; i++) {
System.out.println("input[" + i +"]" + input1[i]);
}
readInput (aScanner, input2);
for (int i = 0; i < input2.length; i++) {
System.out.println("input[" + i +"]" + input2[i]);
}
}
}
i still dont know how to merge those 2 inputs together.Can anyone show me how to do it? Thanks
Declare three arrays for sequence 1, sequence 2 and merged-sequence.
Use a variable whichToUse to store which array to be used and assign array1 to it before the while loop, then store values into array1 on the place of System.out.print, then when first reach value.length()==0 ('=' is not designed for comparing, it's a mistake in your code.), you change the whichToUse point to array2. When the second reach value.length()==0, end the reading loop. One place to be marked, declare streamEnded as a int to count how many times we reach the value.length()==0. Only exit loop while streamEnded==2.
Now you have two arrays which contains the values from file. Next step is to merge them. Use a for loop to iterate items in merged-sequence, and use loop-counter%2 to determine which array to read when assign value to merged-sequence items. after any of the array1 and array2 reaches the end, read the other array in the rest of loop.
As looks like you are new to Java, I think write code by yourself is much better than I provide the code to you. If you've any other question, just comment here.

How to get 2D array possible combinations

I have the following 2D array:
String[M][]
String[0]
"1","2","3"
String[1]
"A", "B"
.
.
.
String[M-1]
"!"
All the possible combinations should be in store in a resulting array
String[] combinations. So for example:
combinations[0] == {"1A....!")
combinations[1] == {"2A....!")
combinations[2] == {"3A....!")
combinations[3] == {"1B....!")
Notice that that the arrays are of variable length. Order of the elements in the output String doesn't matter. I also don't care if there are duplicates.
If the arrays were the same length, nested loops would do the trick, but they are not, and I really don't know how to approach the problem.
You can iterate through the combinations one at a time like clockwork by using an array to record the size of each inner array, and a counter array which keeps track of which member to use from each inner array. Something like this method:
/**
* Produce a List<String> which contains every combination which can be
* made by taking one String from each inner String array within the
* provided two-dimensional String array.
* #param twoDimStringArray a two-dimensional String array which contains
* String arrays of variable length.
* #return a List which contains every String which can be formed by taking
* one String from each String array within the specified two-dimensional
* array.
*/
public static List<String> combinations(String[][] twoDimStringArray) {
// keep track of the size of each inner String array
int sizeArray[] = new int[twoDimStringArray.length];
// keep track of the index of each inner String array which will be used
// to make the next combination
int counterArray[] = new int[twoDimStringArray.length];
// Discover the size of each inner array and populate sizeArray.
// Also calculate the total number of combinations possible using the
// inner String array sizes.
int totalCombinationCount = 1;
for(int i = 0; i < twoDimStringArray.length; ++i) {
sizeArray[i] = twoDimStringArray[i].length;
totalCombinationCount *= twoDimStringArray[i].length;
}
// Store the combinations in a List of String objects
List<String> combinationList = new ArrayList<String>(totalCombinationCount);
StringBuilder sb; // more efficient than String for concatenation
for (int countdown = totalCombinationCount; countdown > 0; --countdown) {
// Run through the inner arrays, grabbing the member from the index
// specified by the counterArray for each inner array, and build a
// combination string.
sb = new StringBuilder();
for(int i = 0; i < twoDimStringArray.length; ++i) {
sb.append(twoDimStringArray[i][counterArray[i]]);
}
combinationList.add(sb.toString()); // add new combination to list
// Now we need to increment the counterArray so that the next
// combination is taken on the next iteration of this loop.
for(int incIndex = twoDimStringArray.length - 1; incIndex >= 0; --incIndex) {
if(counterArray[incIndex] + 1 < sizeArray[incIndex]) {
++counterArray[incIndex];
// None of the indices of higher significance need to be
// incremented, so jump out of this for loop at this point.
break;
}
// The index at this position is at its max value, so zero it
// and continue this loop to increment the index which is more
// significant than this one.
counterArray[incIndex] = 0;
}
}
return combinationList;
}
How the method works
If you imagine the counter array being like a digital clock reading then the first String combination sees the counter array at all zeroes, so that the first String is made by taken the zero element (first member) of each inner array.
To get the next combination the counter array is incremented by one. So the least-significant counter index is increased by one. If this causes its value to become equal to the length of the inner array it represents then the index is zeroed, and the next index of greater significance is increased. A separate size array stores the length of each inner array, so that the counter array loop knows when an index has reached its maximum.
For example, if the size array was:
[3][3][2][1]
and the counter array was at:
[0][2][1][0]
then the increment would make the least significant (right-most) index equal to 1, which is its maximum value. So that index gets zeroed and the next index of greater significance (the second-from-right) gets increased to 2. But that is also the maximum of that index, so it gets zeroed and we move to the next index of greater significance. That gets increased to three, which is its maximum value so it gets zeroed and we move to the most significant (left-most) index. That gets increased to 1, which is less than its maximum so the incremented counter array becomes:
[1][0][0][0]
Which means the next String combination is made by taking the second member of the first inner array, and the first member of the next three inner arrays.
Dire warnings and notes
I wrote this just now in about forty minutes, and it's half-one in the morning, which means that even though it seems to do exactly what is needed, there are very likely bugs or bits of code which could be optimised. So be sure to unit test it thoroughly if its performance is critical.
Note that it returns a List rather than a String array because I think that Java Collections are vastly preferable to using arrays in most cases. Also, if you need a result set with no duplicates, you can simply change the List to a Set which will automatically drop duplicates and leave you with a unique set.
If you really need the result as a String array, don't forget you can use the List<String>.toArray(String[]) method to simply convert the returned List to what you need.
This problem has a very nice recursive structure to it (which also means it could explode in memory, the correct way should be using iterators such as the other answer, but this solution looks nicer imo and we can prove correctness inductively because of the recursive nature). A combination consists of an element from the first list attached to all possible combinations formed from the remaining (n-1) lists. The recursive work is done in AllCombinationsHelper, but you invoke AllCombinations. Note to test for empty lists and more extensively.
public static List<String> AllCombinations(List<List<Character>> aList) {
if(aList.size() == 0) { return new ArrayList<String>(); }
List<Character> myFirstSubList = aList.remove(0);
List<String> myStrings = new ArrayList<String>();
for(Character c : myFirstSubList) {
myStrings.add(c.toString());
}
return AllCombinationsHelper(aList, myStrings);
}
public static List<String> AllCombinationsHelper(List<List<Character>> aList,
List<String> aCollection) {
if(aList.size() == 0) { return aCollection; }
List<Character> myFirstList = aList.remove(0);
List<String> myReturnSet = new ArrayList<String>();
for(String s : aCollection) {
for(Character c : myFirstList) {
myReturnSet.add(c + s);
}
}
return AllCombinationsHelper(aList, myReturnSet);
}
Should be straight forward to do with recursion.
Let me rephrase a bit, so the terminology is less confusing.
We will call String[] as Token List, which is a list of Tokens
Now you have a List of Token List, you want to get one Token from each Token List available, and find out all combination.
What you need to do is, given a list of TokenList
If the List is having only one TokenList, the content of the Token List itself is all combinations
Else, make a sub-list by excluding the first Token List, and find out all combinations of that sub list. When you have the combinations, the answer is simply loop through your first token list, and generate all combinations using each token in the token list, and the result combinations.
I am only giving a psuedo code:
List<String> allCombinations(List<TokenList> listOfTokenList) {
if (length of strings == 1) {
return strings[0];
}
List<String> subListCombinations
= allCombination(listOfTokenList.subList(1)); // sublist from index 1 to the end
List<String> result;
for each (token in listOfTokenList[0]) {
for each (s in subListCombination) {
result.add(token + s);
}
}
return result;
}
I have been struggling with this problem for some time. But I finally solved it. My main obstacle was the SCOPE I used for declaring each variable. If you do not declare your variables in the correct scope, then the variable will retain changes made in the previous iteration.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class RecursiveAlgorithmTest {
private static int recursiveCallsCounter = 0;
public static ArrayList<ArrayList<String>> testCases = new ArrayList<ArrayList<String>>();
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
//set values for ArrayOfArrays
ArrayList<String> VariableA = new ArrayList<String>(Arrays.asList("red", "green"));
ArrayList<String> VariableB = new ArrayList<String>(Arrays.asList("A", "B", "C"));
ArrayList<String> VariableC = new ArrayList<String>(Arrays.asList("1", "2", "3", "4"));
ArrayList<ArrayList<String>> AofA = new ArrayList<ArrayList<String>>();
AofA.add(VariableA); AofA.add(VariableB); AofA.add(VariableC);
System.out.println("Array of Arrays: ToString(): " +AofA.toString());
ArrayList<String> optionsList = new ArrayList<String>();
//recursive call
recurse(optionsList, AofA, 0);
for (int i = 0 ; i < testCases.size() ; i++) {
System.out.println("Test Case " + (i+1) + ": " + testCases.get(i));
}
}//end main(String args[])
private static void recurse(ArrayList<String> newOptionsList,
ArrayList<ArrayList<String>> newAofA, int placeHolder){
recursiveCallsCounter++;
System.out.println("\n\tStart of Recursive Call: " + recursiveCallsCounter);
System.out.println("\tOptionsList: " + newOptionsList.toString());
System.out.println("\tAofA: " + newAofA.toString());
System.out.println("\tPlaceHolder: "+ placeHolder);
//check to see if we are at the end of all TestAspects
if(placeHolder < newAofA.size()){
//remove the first item in the ArrayOfArrays
ArrayList<String> currentAspectsOptions = newAofA.get(placeHolder);
//iterate through the popped off options
for (int i=0 ; i<currentAspectsOptions.size();i++){
ArrayList<String> newOptions = new ArrayList<String>();
//add all the passed in options to the new object to pass on
for (int j=0 ; j < newOptionsList.size();j++) {
newOptions.add(newOptionsList.get(j));
}
newOptions.add(currentAspectsOptions.get(i));
int newPlaceHolder = placeHolder + 1;
recurse(newOptions,newAofA, newPlaceHolder);
}
} else { // no more arrays to pop off
ArrayList<String> newTestCase = new ArrayList<String>();
for (int i=0; i < newOptionsList.size();i++){
newTestCase.add(newOptionsList.get(i));
}
System.out.println("\t### Adding: "+newTestCase.toString());
testCases.add(newTestCase);
}
}//end recursive helper
}// end of test class
In Python one uses itertools.product and argument unpacking (apply)
>>> import itertools
>>> S=[['1','2','3'],['A','B'],['!']]
>>> ["".join(x) for x in itertools.product(*S)]
['1A!', '1B!', '2A!', '2B!', '3A!', '3B!']

java android string and integer functions dont work

Hi I'm not sure if this is a problem with Eclipse or Java but recently my code has stopped working. I only changed things like assigning new variables to store things. My program takes a multi-dimensional string array and should return a new array trimmed of nulls.
public void makebuttons(final int n, String equals) {
//does lots of widget functions and id assignments
String[] items=getArray(Integer.parseInt(data.equnits.substring(n*3, n*3+1)));
unitvalues[n]=Integer.parseInt(data.equnits.substring(n*3, n*3+1));
ArrayAdapter aa = new ArrayAdapter(this,android.R.layout.simple_spinner_item, items);
//does more code
}
public static String[] getArray(int selection) {
String[] result;//stores the new array
int x=0,j=0 ,ulength = data.units[0].length;//ints used
String temp="";
while(j < ulength && temp!=null) {
temp= data.units[selection][j][0]; //find the actual array length
j++;
}
if(j==ulength)j--;
result = new String[j+1];//initalise array from check
for(x=0; x<=j; x++) { //add data to array
result[x]=data.units[selection][x][0];
}
return result;//return corrected array
}
Integer.parseInt and Integer.valueOf give value of 0 each time for a string like "01,02,03,04" data.equnits stores the string to be converted to integer by checking 2 digits only to select from a large 3 dimensional array. Since its a 3 dimensional array some nulls are present
Null check for the String doesnt seem to work since the while loop doesnt seem to detect it and it ends up being in the array that gets passed into the array adapter for spinner causing NullPointerException while scrolling.
Restarting eclipse doesn't help.
I can't help with your first problem without more information, but this seems to be the issue with your second:
The function substring is inclusive of the first parameter and exclusive of the second. Since you are only adding 1 to the n*3, you only get one character.
Try using:
substring(n*3, n*3+2)
Edit:
Adding the updated code from my comment above:
while(j < ulength && temp != null && !temp.isEmpty())
{
temp = data.units[selection][j];
j++;
}

Categories