When declaring and assigning primitives before loop everything works fine and could be different from each other later on
//example
double sum1, sum2, sum3, sum4;
sum1 = sum2 = sum3 = sum4 = 0;
//later each gets own value correctly
Is it possible to make oneliner for an array?
//example
double[][] compare, updated; // works as intended
compare = updated = new double[SIZE][]; // makes compare=updated
Problem with second line is that it ignores all following calculations for updated and takes values from compare.
If by "one-liner" you mean a single statement and writing new double[] once, yes you can do this:
double[] arr1, arr2;
arr1 = (arr2 = new double[10]).clone(); // this is the line
arr1[0] = 10;
System.out.println(arr2[0]); // 0.0
But it's not very readable. It gets even worse when you do this with more arrays:
arr1 = (arr2 = (arr3 = new double[10]).clone()).clone();
I suggest you still use multiple lines to do this.
As an alternative to #Sweeper's answer, consider using the Arrays.copyOf() method, as suggested in this answer. Note that the copyOf() method is type-safe whereas the clone() method isn't.
double[] a, b, c;
c = Arrays.copyOf((b = Arrays.copyOf((a = new double[10]), a.length)), b.length);
But again, I'll reiterate as #Sweeper does, that this code really smells and you should consider doing it in multiple lines. As Steve McConnell says in Code Complete 2nd Ed., the Primary Technical Imperative of software is to manage complexity (i.e. make your code simple). This doesn't necessarily mean reducing the lines of code, but more to do with enabling people who read your code to understand what it does at a glance.
Related
I'm fairly new to coding and am struggling with an assignment for my class. The program takes a user input for the size of an Array and prompts the user to enter each value 1 at a time. The array size starts at 3 and if the array needs to be bigger when the array has filled a new array that's 2x size is created and all info is copied into it. I was able to figure out this part but I just can't see what I'm doing wrong in the downsizing part. After the info is copied I have to remove the trailing zeroes. I think I have the downsize method right but I don't know if I'm calling it right
import java.util.Scanner;
public class Lab6 {
public static void main(String args[]) {
int[] myarray = new int[3];
int count = 0;
int limit, limitcount = 1;
Scanner kbd = new Scanner(System.in);
System.out.print("How many values would you like to enter? ");
limit = kbd.nextInt();
while (limitcount <= limit) {
System.out.println("Enter an integer value ");
int input = kbd.nextInt();
limitcount++;
if (count < myarray.length) {
myarray[count] = input;
}
else {
myarray = upsize(myarray);
myarray[count] = input;
}
count++;
}
myarray = downsize(myarray, count)
printArray(myarray);
System.out.println("The amount of values in the arrays that we care about is: " + count);
}
static int[] upsize(int[] array) {
int[] bigger = new int[array.length * 2];
for (int i =0;i<array.length; i++) {
bigger[i] = array[i];
}
return bigger;
}
static void printArray( int[] array ) {
for ( int number : array ) {
System.out.print( number + " ");
}
System.out.println();
}
static int[] downsize(int[] array,int count) {
int[] smaller = new int[count];
for (int i =0; i<count; i++) {
smaller[i] = array[i];
}
return array;
}
}
Giving you a full response rather than a comment since you're new here and I don't want to discourage you with brevity which could be misunderstood.
Not sure what happened to your code when you pasted it in here, you've provided everything but the format is weird (the 'code' bit is missing out a few lines at the top and bottom). Might be one to double-check before posting. After posting, I see that someone else has already edited your code to fix this one.
You're missing a semi-colon. I'm not a fan of handing out answers, so I'll leave you to find it :) If you're running your code in an IDE, it should already be flagging that one up for you. If you're not, why on earth not??? IntelliJ is free, easy to get going with, and incredibly helpful. There are others out there as well which different folk prefer :) An IDE will help you spot all sorts of useful things quickly.
I have now run your code, and you do have a problem! It's in your final method, downsize(). Look very, very carefully at the return statement ;) Your questions suggests you aren't actually sure whether or not this method is right, which makes me wonder: have you actually run this code with different inputs to see what results you get? Please do that.
Style-wise: blank lines between methods would make the code easier to look at, by providing a visual gap between components. Please be consistent with putting your opening { on the same line as the method signature, and with having spaces between items, e.g. for (int i = 0; i < count; i++) rather than for (int i =0; i<count; i++). The compiler couldn't care less, but it is easier for humans to look at and just makes it look like you did care. Always a good thing!
I think it is awesome that you are separating some of the work into smaller methods. Seriously. For extra brownie points, think about how you could move that while() block into its own method, e.g. private int[] getUserData(int numberOfItems, Scanner scanner). Your code is great without this, but the more you learn to write tiny units, the more favours you will be doing your future self.
Has your class looked at unit testing yet? Trust me, if not, when you get to this you will realise just how important point 5 can be. Unit tests will also help a lot with issues such as the one in point 3 above.
Overall, it looks pretty good to me. Keep going!!!
Simple mistake in your downsize method. If you have an IDE like Eclipse, Intellij, etc. you would have seen it flagged right away.
return array; // should return smaller
I have a few suggestions since you mentioned being new to coding.
The "limitcount" variable can be removed and substituted with "count" at every instance. I'll leave it to you to figure that out.
Try using more descriptive and understandable variable names. Other people will read your code (like now) and appreciate it.
Try to use consistent spacing/indentation throughout your code.
Your upsize method can be simplified using a System.arraycopy() call which generally performs better and avoids the need for writing out a for loop. You can rewrite downsize in a similar manner.
static int[] upsize(int[] array) {
int[] bigger = new int[array.length * 2];
System.arraycopy(array, 0, bigger, 0, array.length);
return bigger;
}
Edit: All good points by sunrise above - especially that you've done well given your experience. You should set up an IDE when you have the time, they're simple to use and invaluable. When you do so you should learn to step through a debugger to explore the state of your program over time. In this case you would have noticed that the myarray variable was never reassigned after the downsize() call, quickly leading you to a solution (if you had missed the warning about an unused "smaller" array).
This question already has answers here:
Assigning variables with dynamic names in Java
(7 answers)
Closed 5 years ago.
Okay so for what I am doing i need to increment my variables name, so for example
int Taco1 = 23432.....
int Taco2 = 234235656.....
int Taco3 = 11111.......
But instead i need it to be a variable like
int X = 0;
some method with loop or recursion()
int Taco(X) = bla bla bla
x++
Trying to get my variable names to auto name themselves incremented by 1 every time, so they don't overwrite themselves. If this is impossible then my apologies.
You can't do this in Java and more importantly, you don't want to do this as this isn't how Java works. In fact variable names aren't nearly as important as you think and hardly even exist in compiled code. What is much more important is that you are able to get a reference to your objects in as easy and reliable a way as possible. This can involve an array, an ArrayList (likely what you want here), a LinkedList, a Map such as a HashMap, a Set, and other types of collections.
For example:
List<Taco> tacoList = new ArrayList<Taco>();
for (int i = 0; i < MAX_TACOS; i++) {
tacoList.add(new Taco(i));
}
Indeed it is impossible to generate identifier names based on a variable. Perhaps what you want is an array:
int[] Taco = new int[ 15 /*some appropiate upper limit*/ ];
Taco[X] = bla bla bla;
Search the web for basic information on what arrays are and how they work.
Use an int[] or a List<Integer>:
int[] tacos = new int[numberOfTacos];
// in some loop or whatever
tacos[x] = someValue;
use array of int. say int taco[50]; and you can reference each location as taco[0],taco[1] etc
I TacoX is going to be an integer, I would create an array of X ints. If the max number is 10, we have:
int[] taco = new int[10];
Then to modify/read tacoX, you just look at taco[X]
Let's say I want to generate 20 random numbers on a 8 by 6 grid.(8 columns, 6 rows) . Based on the answer from here:Creating random numbers with no duplicates, I wrote my code like this:
Random randomNumGenerator = new Random();
Set<Integer[][]> generated = new LinkedHashSet<Integer[][]>();
while (generated.size() < 20) {
int randomRows = randomNumGenerator.nextInt(6);
int randomColumns = randomNumGenerator.nextInt(8);
generated.add(new Integer[][]{{randomRows,randomColumns}});
}
In reality what happens is the Set see Integer[][]{{5,5}}; and Integer[][]{{5,5}};as NOT duplicate.Why? Even tho my purpose is to get 20 non-duplicate pair of numbers, this does not work. How do I fix this?
The Set checks for duplicates using the equals method (and also the hashCode method) of its inner type, but the Integer[][]'s equals method compares the memory addresses and not the contents.
Why do you use a Set of Integer[][] if you just want to store pairs?
Unfortunately, in Java there is no Pair class, but if you do not want to create your own, you can use the Map.Entry for that.
Random randomNumGenerator = new Random();
Set<Map.Entry<Integer, Integer>> generated = new LinkedHashSet<>();
while (generated.size() < 20) {
int randomRows = randomNumGenerator.nextInt(6);
int randomColumns = randomNumGenerator.nextInt(8);
generated.add(new AbstractMap.SimpleEntry<>(randomRows,randomColumns));
}
System.out.println(generated);
Array equals is == in Java, so an array is only equal to itself. Normaly you use Arrays.equals(array1, array2) to compare them by content, but in this case, arrays are simply the wrong choice. You can either create a bean, as rafalopez79 suggested of use an array of Collections (List in your case), as a List will compare the content on equals, see the documentation. Choice is pretty much yours, a bean would probably be a bit cleaner.
How about this code. I ran it through the debugger, it works nicely and yes, the contains() method checks the value of the Integer, not the reference. You can change the range of the random number as needed, I used 5 to facilitate testing. Yes I know it's not very robust, as written this will be an endless loop (because of the limited range of 5) but it's a simple example to make the point.
UPDATE: Actually this has a bug in that it won't check for uniqueness across all the rows, but that's easily fixed as well. I just re-read the original question and looking at the original code I'm not sure I know what you want exactly. If you just want a grid with 48 unique Intergers arranged 8 by 6 this will do it, but there are several ways to do this.
final int rows = 6;
final int cols = 8;
Random randomGenerator = new Random();
ArrayList[] grid = new ArrayList[rows];
for(int i=0; i<rows; i++)
{
grid[i] = new ArrayList<Integer>();
for(int j=0; j<cols; j++)
{
for(;;)
{
Integer newInt = new Integer(randomGenerator.nextInt(5));
if(!grid[i].contains(newInt))
{
grid[i].add(newInt);
break;
}
}
}
}
if I have a for loop like...
for (int i = 0; i < myArray.length; i++) { ... }
...does myArray.lengthget evaluated every iteration? So would something like...
int len = myArray.length;
for (int i = 0; i < len; i++) { ... }
... be a small performance increase?
regardless myArray.length is just a field so there is nothing to evaluate
Java array has length as public final int so it gets initialized once and when you refer to it there is no code execution like a method call
The public final field length, which contains the number of components of the array. length may be positive or zero.
The first form will probably incur some performance penalty, since evaluating it will require, before the iflt, an aload, an arraylength and an iload; whereas the second is only two iloads.
#ajp rightly mentions that myArray may change; so it is highly unlikely that the compiler will optimize the first form into the second for you (unless, maybe, myArray is final).
However, the JIT, when it kicks in, is probably smart enough so that, if myArray doesn't change, it will turn the first form into the second.
Just in case, anyway, use the second form (this is what I always do, but that's just out of habit). Note that you can always javap the generated class file to see the generated byte code and compare.
By the way, Wikipedia has a very handy page listing all of a JVM's bytecodes. As you may see, quite a lot of them are dedicated to arrays!
Yes, the termination expression gets evaluated every time. So you're right that storing the length once could be a small performance increase. But more importantly, it changes the logic, which could make a difference if myArray gets reassigned.
for (int i = 0; i < myArray.length; i++) {
if (something-something-something) {
myArray = appendToMyArray(myArray, value); // sets myArray to a new, larger array
}
}
Now it makes a big difference whether you store the array length in a variable first.
You wouldn't normally see code like this with an array. But with an arrayList or other collection, whose size could increase (or decrease) in the body of the loop, it makes a big difference whether you compute the size once or every time. This idiom shows up in algorithms where you keep a "To-Do list". For example, here's a partial algorithm to find everyone who's connected directly or indirectly to some person:
ArrayList<Person> listToCheck = new ArrayList<>(KevinBacon);
for (int i = 0; i < listToCheck.size(); i++) {
List<Person> connections = allConnections(listToCheck.get(i));
for (Person p : connections) {
if ([p has not already been checked]) {
listToCheck.add(p); // increases listToCheck.size()!!!
}
}
}
Not really. Both cases are comparing the value at two memory addresses with every iteration, except you are doing unnecessary assigning when you use a len variable. The performance difference is probably very small, and the first line is more readable, so I would use the first way as it is more readable. If you want to be even more readable and efficient, use a for-each loop if you are just going to do a linear iteration through your array. For-each loops look work like this:
int [] myArray = {1,2,3};
for(int i:myArray){
System.out.print(i);
}
will print:
1
2
3
as i is set to each element of the array. The for each loop can be used for many objects, and is a nice feature to learn.
Here is a guide explaining it.
https://www.udemy.com/blog/for-each-loop-java/
Is there a way to do the following at the same time?
static final int UN = 0; // uninitialized nodes
int[] arr;
// ... code ...
arr = new int[size];
for (int i = 0; i < 5; i++) {
arr[i] = UN;
}
Basically, I want to declare arr once I know what its size will be and initialize it to UN without having to loop. So something like this:
int[] arr = new int[size] = UN;
Is this possible?
Thanks.
Arrays.fill(arr, UN);
You don't need to initialize them with 0. An int defaults to 0 already.
Just
int[] array = new int[size];
is enough. It gives you an array of zeroes of the given length. If it were an Integer[], it would have been an array of nulls.
Well, in the case of objects (or primitives with autoboxing) you can do the following:
int count = 20;
final int UN = 0;
Integer[] values = Collections.nCopies(count, UN).toArray(new Integer[count]);
The downsides are that you have to use the object forms of the primitives (since the Collections must be of objects) and a separate List will be constructed and then thrown away. This would allow you to create the array as one statement however.
No, not with the standard libraries. If you write your own functions, though, you can easily do so in a single statement (not instruction; those are different). Mine looks like String[][] strings = Arrayu.fill(new String[x][y], "");
Here's a link. There's some junk in there too, though; I just posted a copy of the current source directly without cleaning it up.
No.
Next question?
int arr[] = { 0, 0, 0, 0, 0 };
Oops, read your question better:
You can init an array like so
int[] arr = new int[] {UN, UN, UN, UN, UN};
But ofcourse, if you don't know the size at compile time, then you have to do the for loop. The second technique is not possible.