Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Elegant min/max absolute values in java

Tags:

java

I need to get the minimum and maximum values in a collection of floating point values, after applying an absolute value conversion. In python I would do this

min(map(abs, [-5, -7, 10, 2]))

how can I perform the same operation in java in the most elegant way?

like image 525
Stefano Borini Avatar asked Mar 06 '26 23:03

Stefano Borini


2 Answers

You might be able to do something crazy, but the most straightforward solution is this:

List<Integer> x = new ArrayList<Integer>(Arrays.asList( {-5,-7,10,2} } );
for( int i = 0; i < x.size(); i++ ){
   x.set( i, Math.abs(x.get(i)) );
}

return Collections.max( x );

Collections and Arrays are infinitely useful.

like image 183
Stefan Kendall Avatar answered Mar 09 '26 13:03

Stefan Kendall


Here is another way to do it. This approach does not require creating a second copy of the array, since Arrays.asList merely produces an array-backed view of the given array. Another potential advantage is the fact that the signs of the minimum and maximum are preserved. In the example below, the minimum is displayed as 1.333 and the maximum as -9.43.

It is more complex than Stefan's solution, but depending on the situation, it might be right for you.

    Float numbers[] = {-9.43f, 2.3f, -8.2f, 1.333f};

    // Calculate the minimum
    Float min = Collections.min(Arrays.asList(numbers), 
            new Comparator<Float>() {
                public int compare(Float o1, Float o2) {
                    Float result = Math.abs(o1) - Math.abs(o2);
                    return result > 0 ? 1 : result < 0 ? -1 : 0;
                }
            }
    );

    // Calculate the maximum
    Float max = Collections.min(Arrays.asList(numbers), 
            new Comparator<Float>() {
                public int compare(Float o1, Float o2) {
                    Float result = Math.abs(o2) - Math.abs(o1);
                    return result > 0 ? 1 : result < 0 ? -1 : 0;
                }
            }
    );

    System.out.println("Min = " + min);
    System.out.println("Max = " + max);

Output:

Min = 1.333
Max = -9.43

Edit: In response to "hatchetman82" in the comments, I decided to run a simple benchmark to see how my solution performs compared to Stefan Kendall's. For small arrays of less than ten thousand elements, the two solutions perform almost identically. However, for larger arrays, my solution will usually perform better.

Stefan's approach is perfectly valid, but it uses about twice as much memory as mine, because it must create a copy of the original array in order to store each element's absolute value. As for time complexity, I found that my approach performed anywhere between 4X and 7X faster, mostly due to the time Stefan's approach requires to copy the array. Keep in mind that these benchmarks were performed on a single machine (a MacBook Pro, 4GB, Core2 Duo @ 2.53) and results will vary depending on your computer's and JVM's configurations.

Stefan's approach is certainly more straight forward, and mine can perform better under certain situations. So basically each solution is valid, though one or the other might be preferable depending on the situation.

like image 32
William Brendel Avatar answered Mar 09 '26 13:03

William Brendel



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!