I'd like to know, in detail, how the Enhanced For Loop works in Java (assuming i do get how the basic usage of this loop is and how it works in general).
Given the following code:
String[] a = {"dog", "cat", "turtle"};
for (String s : a) {
out.println("String: " + s);
s = in.readLine("New String? ");
}
It doesn't actually modify the original list 'a'.
Why not? How memory Management works? Isn't 's' a reference to the same memory cell of 'a[i]'?
I read on the oracle documentation that enhanced for loops can't be used to remove elements from the original array, it makes sense. Is it the same for modifying values?
Thanks in advance
Isn't 's' a reference to the same memory cell of 'a[i]'?
Originally, yes. But then in.readLine produces a reference to a new String object, which you then use to overwrite s. But only s is overwritten, not the underlying string, nor the reference in the array.
s is a local variable that points to the String instance. It is not associated with a[i], they just happen to have the same value initially.
You can only write
for (int i = 0; i < a.length; i++) {
out.println("String: " + a[i]);
a[i] = in.readLine("New String? ");
}
You can't use for-each loops to modify the original collection or array.
Think in s like an address to an object. The thing here is that s is pointing out to a certain value of the array when using the for loop. When you reassing s inside the loop is just happen that s points out to another value but the original value of the array is not modified as you are only changing the address s is pointing to.
String[] a = {"dog", "cat", "turtle"};
for (String s : a) {
//s --> "dog"
out.println("String: " + s);
s = in.readLine("New String? ");
//s --> the new string the user inputs
}
For every iteration String s initially references to corresponding String object in String a[]. But it is then referenced to another String object that is returned by in.readLine().
Related
I've read in other posts, that instead of writing just System.out.println(finalPressedKey);
you should write System.out.println(Arrays.toString((finalPressedKey)); because otherwise it will just return the location where the String is saved (as far as I understood it).
public static String PressedKey[] = new String[2000];
public static String[][] finalPressedKey = {{ "", "", "", "", "", "", "", "", "", "", "", "" }}; // 12
public static String FPK3;
public static void upcounter(KeyEvent e) {
for (int x = 0; x < PressedKey.length; x++) {
if (PressedKey[x] != null && PressedKey[x + counter] != null) {
//FPK counter is supposed to be a line, and counter is where the words are supposed to be saved
finalPressedKey[FPKcounter][counter] =
finalPressedKey[FPKcounter] + PressedKey[x + counter];
System.out.println(Arrays.toString(finalPressedKey));
}
}
Whenever I Press a Button, it should be saved in my PressedKey Array, and finalPressedKey is supposed to contain itself, and PressedKey (also , only the last element of the array is supposed to be printed), but instead it just prints [[Ljava.lang.String;#76f42c4b]
I also tried using Arrays.deepToString(); but it gives me the same output as with Arrays.toString();
Thanks for your help!
A String[][] is not a 2-d array. It is an array of String[]. The difference is subtle but important.
The method Arrays.toString() takes an array, iterates through its elements, calls toString() on all of them, and adds a prefix, suffix, and delimiters. Since you give it a String[][] (an array of String[]), it will do the following:
Iterate through the elements (each of them a String[])
call toString() on each element - giving the default toString() value of an array - i.e. its memory address (not really but for this purpose it doesn't matter)
concatenate
Luckily for you, there is an easier way - just use Arrays.deepToString(). This behaves as you would expect.
I did not understand the whole code, but following statement is very suspicious:
finalPressedKey[FPKcounter][counter] =
finalPressedKey[FPKcounter] + PressedKey[x + counter];
since it is adding an array (finalPressedKey[...]) to a string (PressedKey[...]), which will result in that strange text - the standard textual representation of an array (returned by toString). (from a mathematical point of view, it's strange to have 2 indexes )2D_ before the assignment and only one on the right side (1D) for same matrix)
I'm not sure, since we cannot see what counteris, but I believe you wanted something like:
finalPressedKey[FPKcounter][counter] =
finalPressedKey[FPKcounter][counter] + PressedKey[x + counter];
that is, an additional [counter] on second line.
This can also be written as
finalPressedKey[FPKcounter][counter] += PressedKey[x + counter];
If you only want to store lines of strings, a normal String[] is good for you
finalPressedKey[FPKcounter] += PressedKey[x + counter];
even though I wouldn't recomment doing this, no matter what you're trying to accomplish, since this will create a new String object each time a key is pressed.
Maybe ask the question differently and tell us what you're trying to do. I guess String arrays might not be the way to go.
You have to print the elements of your array with
for(int i = 0; i<finalPressedKey[0].length; i++){
for(int j=0; j<finalPressedKey[1].length; j++){
System.out.println(finalPressedKey[i][j]);
}
}
if I understand it correctly.
The program is supposed to print out the amount of times each name has been selected (this is indicated by number of asterisks (*). I have most of the code working but for some reason the output contains two null values for each name and I am not sure how to fix the problem. Also if you have the time, I'm also struggling to find out which name has the most amount of asterisks. Here's an example output:
1: nullnull************************ Conner
2: nullnull********************************** John
etc...
(it does this for all 10 names)
public class RandomStudentsLab {
public static void main(String[] args){
//create an array with 10 students
String [] StudentList = new String[10];
String [] StarString = new String[10];
String [] FinalString = new String[10];
//add 10 names to the student list
StudentList[0] = "Conner";
StudentList[1] = "John";
StudentList[2] = "Alex";
StudentList[3] = "Robert";
StudentList[4] = "James";
StudentList[5] = "Carl";
StudentList[6] = "Sarah";
StudentList[7] = "Bob";
StudentList[8] = "Ethan";
StudentList[9] = "Chris";
//loop 250 times selecting each student randomly
for(int i=0; i<250; i++){
int randomNum = (int)((Math.random()*10));
for(int x=0; x<10; x++){
if(randomNum == x){
StarString[x] += "*";
}
}
}
for(int z=0; z<10; z++){
System.out.println((z+1)+": "+(FinalString[z] += StarString[z] + " "+StudentList[z]));
}
}
}
Elements in FinalString and StarString arrays are still not initialized. So with += operator its calling toString on the null element and prefix "null" to each string.
As mentioned by Karthik in his answer you never initialized (as in you never assigned values) the FinalString array. That is what is causing your error.
You can easily tell since your System.out.println() is printing:
Number : nullnull Stars Name
So clearly your issue is with FinalString, it is the only variable not printing correctly.
System.out.println((z+1)+": "+(FinalString[z] += StarString[z] + " "+StudentList[z]));
You are making the same mistake with the StarString array. You are lucky enough to get away with it in this case since you end up adding variables to StarString in your loop.
However, NOT initialising ANY variable is >>horrible<< practice. You never know what was previously stored in memory, this could lead to your variables being assigned some 'alien' data that was leftover on the memory by some other program. Secondly, and this is the issue in your question, if you forget to initialise you can run into null errors and such.
So as a matter of good coding practice always initialise your variables to something. Even if you are using the variable two lines later - it doesn't matter. When you create your variable assign it a value:
If it's an integer then 0 or -1. It's better if it's a value that won't occur in your program, so if you have an error in your code you can spot it easily because your integer will be -1 instead of x y z.
If it's a string then name it 'banana' or 'peanuts' or whatever.
If it's an object make sure you initialise all of the attributes
And so on...
P.S. Not sure if I came accross as harsh, but it's absolutely not my intention. Good coding practices are simply important and will be extremely helpful in the future.
Best of luck!
EDIT:
Little update to reflect your comment on another answer.
When you create FinalString here String [] FinalString = new String[10]; your are not assigning any values to it, unlike what you did with the names.
So when your code gets to the final for loop here:
for(int z=0; z<10; z++){
System.out.println((z+1)+": "+(FinalString[z] += StarString[z] + " "+StudentList[z]));
}
}
}
And you try to do a System.out.println() for FinalString[z], well FinalString[z] still does not have a value. At no point in your code did you write
FinalString[0] = "Banana";
So obviously it will print null instead.
I am currently seeking for a bit of help with the use of arrays. Quite a newbie on the Java language, so excuse the poor etiquette towards the programming format and I forwardly thank for any answers provided.
My current quarrel with the Array is how to fetch data from any array element. Currently I use the method System.out.println(Arrays.toString(listarray)) but the problem with this method is that it's not necessarily User friendly and it can't be formatted (to my little knowledge). So I'd like to ask help on how to fetch data from an element of an array and put it in a way so its readable by any given user.
Here is the code I'm utilizing:
import java.util.Arrays;
import java.util.Scanner;
public class principal {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("Array Example");
String[] listarray = new String[10];
int i = 0;
byte op;
do {
System.out.println("Select your option:");
System.out.println("1-Add");
System.out.println("2-Check");
System.out.println("3-Change");
op = input.nextByte();
switch (op) {
case 1:
input.nextLine();
System.out.println("First String:");
String a1 = input.nextLine();
System.out.println("Second String:");
String a2 = input.nextLine();
System.out.println("Third String:");
String a3 = input.nextLine();
System.out.println("(" + (i + 1) + "/10)");
listarray[i] = a1 + a2 + a3;
i++;
break;
case 2:
System.out.println(Arrays.toString(listarray));
break;
}
}while(op != 9);
}
}
While the code does work, I'd like to know how to format the data, and from a single element, not every element. Or even if I can. Thanks and I appreciate the time spent reading this question.
You have two questions:
How do you reference an array element?
How do you format output?
When you declare an array like
String[10] names;
You have an array that can hold 10 strings, numbered 0 to 9. To reference the fifth element (remembering that array indices start at 0), you would use
names[4]
You can do various things with a reference. If you put it on the right side of an equals sign, then you are assigning the value at that element to something else.
currentName = names[4];
If you put it on the left side, you are assigning something to that element.
names[4] = "Michael";
And if you put it in a println statement, it will output the value to wherever the println statement is putting things at that time, usually the console:
System.out.println(names[4]);
So much for references. And, incidentally, that's what it is called -- you are referencing the 5th element of the array, or you are referencing the indicated element of the array. You can also put the number in a variable:
var i = 4;
System.out.println[i];
Note that most of these uses of the reference assume there is something IN that element of the array. Until something is assigned there, the element is a null.
To format, I recommend looking (carefully) into the Format / Formatter classes and choosing some simple things to do what you want. As an example, you could have:
String formatString = "The name is currently %s.";
String outputString = String.format(formatString, names[i]);
and String's format method will substitute whatever is in names[i] for the %s in the format. There are also formats for ints, doubles, and dates.
For more info, see the Oracle Tutorial on arrays and on manipulating Strings.
Hope that helps
If you want to traverse the Array that is how you can do it:-
for(int i = 0; i < listArray.length; i++) {
System.out.println(listArray[i]);
}
or
for (String s : listArray) {
System.out.println(s);
}
So I initialized an array lets say
`string example = new string [5];
When I called the split method on a line of
string x = "abc, def, g";
example = x.split(",");
example[0] = abc
example[1] = def
example[2] = g
I can no longer access example[3] and example[4] as I am getting null pointer
shouldn't these still be accessible with values of null?
Even though you created a array with some initial length for example
String [] sample = new String[5];
after assigning new Array to the variable It will create a new array with new array size. for example.
String s = "Hi how are you";
sample = s.split(" ");
so you can not access old array elements.
It doesnt preserve the values. "example" is assigned with a completely new and different array.
If you want to preserve the number of elements previously present in the array, you can do something like:
int num = example.length;
example = x.split(",");
example = Arrays.copyOf(example, num);
// initialize the new array elements here.
Of course doing so is not very efficent and should be avoided. I suggest you take a look at array lists instead.
Your initial example array (of length 5 with null values) gets overwritten by the new array returned by the call to the split() method, in this case an array of length 3. The initial array referenced by the example reference is not accessible anymore, it will be garbage collected.
If you want to keep both arrays you can assign the result of the split to another variable
String[] example2 = x.split(",");
String s;
/*code*/
s = "foo";
Is a whole new object being created, since the empty string can't change?
This:
String s;
doesn't create an "empty string", it's simply an uninitialised variable.
This:
s = "foo";
sets that variable to refer to a String object. It's the object that's immutable, not the variable.
You need to understand the difference between variables and objects.
Consider this code:
String x = "hello";
for (int i = 0; i < 10; i++) {
x = x + i;
}
This will end up creating 11 string objects, but there are only two variables involved (x and i). At any point, the value of i is an integer (0-10) and the value of x is a reference to a String. (It could be null too, but it happens not to be in this example.)
It's important to understand that x is not an object, nor is the value of x an object.
If it helps to think of it in physical terms, consider a piece of paper with my home address on it:
The piece of paper is like the variable - it's "somewhere a value can be stored".
The address written on the piece of paper is like the reference - it's a way of finding an object
The house itself is like the object.
Neither the piece of paper nor the address is the house itself. If you rub the address out on the paper and write a different address instead, that doesn't make any changes to my house - just like changing the value of x doesn't make any changes to the string objects themselves in my sample code.
s isn't currently assigned to anything at all.
But if you had -- if you had defined String s = ""; and then s = "foo";, then the empty string isn't changed, but the variable s is changed to refer to the string "foo" instead of the empty string.