2

In the method normalize I input an array say, {1, 2, 3, 4}, and the return is a normalized array, {0.1, 0.2, 0.3, 0.4}. I know I should introduce a new array in the method (b in the following), but why actually?

public static double[] normalize(double[] a) {
    double[] b = new double[a.length];
    double sum = 0;
        for (int i = 0; i < b.length; i++) {
            sum += a[i];
        }
        for (int i = 0; i < b.length; i++) {
            b[i] = a[i]/sum;
        }
    return b;
}
Input: 1 2 3 4 
Output: 0.1 0.2 0.3 0.4

Why is the following wrong:

public static double[] normalize(double[] a) {
    double sum = 0;
        for (int i = 0; i < a.length; i++) {
            sum += a[i];
        }
        for (int i = 0; i < a.length; i++) {
            a[i] = a[i]/sum;
        }
    return a;
}
Input: 1 2 3 4
Output: 0.1 0.2 0.3 0.4
JDoeDoe
  • 361
  • 1
  • 2
  • 7
  • 3
    Maybe you don't want the array you passed in to be modified. Maybe you need it for something else. – khelwood Feb 18 '20 at 14:00
  • There are times where an array passed in should be changed. However, that should be documented in 100 point bold type! – NomadMaker Feb 18 '20 at 14:02
  • 1
    It's not "wrong", it depends on the situation you're in - Do you want to keep the original values for further calculations (Then use version A) or do you want to override them with the normalized values (Then use version B)? Generally speaking, version A is probably "better" / more versatile, since you can use it in both cases, while B is only useful if you don't need the original values. – Nightara Feb 18 '20 at 14:03
  • BTW second case can be misinterpreted: it is returning an array, so I would assume it is a new array - IMO `void` would be more appropriate **if** the original is to be changed - but that does not mean it is "wrong" - why do **you** call it wrong? – user85421 Feb 18 '20 at 14:08

4 Answers4

4

In the first case, the original array will stay unmodified when the method returns.

In the second case, the original array will be modified (even when it returns to where it was called), irregardless to whatever array you set the return value to afterward.

Both options can be viable, but it depends on the case and what is expected to happen. However, typically I would expect when you pass a parameter to a method, the parameter will not be modified when the method returns.

Documentation can make it clear that the original array will be modified or if it will not be.

Side Note:

This will not work the same way if you modify a directly, instead of modifying the values contained within:

public static void normalize(double[] a) {
    a = new double[5];
}

a will remain unchanged in this case when the method returns.

Nexevis
  • 4,647
  • 3
  • 13
  • 22
  • 1
    Well to be fair, setting 'a' in the code presented to a new value also wouldn't modify the original array - it's when modifying an attribute/internal field of the passed object rather than changing the reference that it becomes an issue – josh.trow Feb 18 '20 at 14:23
  • 1
    @josh.trow I modified the side note instead to what you mentioned, thanks for your input. – Nexevis Feb 18 '20 at 14:31
4

The difference is that one method updates the input array in place, whereas the other one keeps the array intact and returns a copy.

Neither is wrong(*), both ways have their place, you just need to make sure to the caller knows what is happening.

If you update in-place, you can make that clearer by making the method void instead of returning a (redundant) reference to the same array.


(*) In modern practice, prefer immutable data structures. So unless performance is a real issue, go with the "safer" variant.

Thilo
  • 257,207
  • 101
  • 511
  • 656
0

In my opinion, you are creating a new variable with new values. The method receives one var and returns another var.

It's more reader-friendly.

guren
  • 122
  • 2
  • 9
0

Explaining the byte code behavior, and the difference of creating a new array or reusing the same input is not what you are asking for I think. Because it is really easy to see the difference.

What I think you are looking for, is a conceptual analysis of the difference. From my perspective, "functions" in any language should be treated as math functions. You give X and Y, and the function returns Z. Imagine you have a rectangle which height = a and width = b. If you want the area of it, you pass a and b and you get A . If you want the perimeter, you pass a and b and you get P.

This makes your code more readable, reusable, more cohesive, more testable.

Perimosh
  • 2,304
  • 3
  • 20
  • 38