0

I have the following ArrayList List<DataSt> list1 where list1 has the following values (floats):

<25.89,   21.23>
< 5.89,    1.23>
< 3.69,   20.23>
< 2.89,  121.23>
<125.89, 231.23>
.
.
.
< 28.89,  41.23>

And DataSt has the following structure:

public class DataSt {
    private float a;
    private float b;

    public DataSt(float a , float b){
        this.a=a;
        this.b=b;
    }
}

Now I need to find the minimum from the first column i.e., from <25.89, 5.89, 3.69, 2.89, 125.89 ... 28.89> it must return 2.89

Then find max from <25.89, 5.89, 3.69, 2.89, 125.89 ... 28.89> it must return 125.89

Now repeat the same for second column and store them with 4 different variables say min_col1,max_col1,min_col2 and max_col2 respectively.

min_col1 = 2.89
max_col1 = 125.89
min_col2 = 1.23
max_col2 = 231.23

I have been looking through various solutions that suggest using two for loops with is really time consuming also some threads suggested using stream() which was finding for the whole list (i.e., not for every column).

Is there an efficient way to do this? I am also looking at Apache Commons as well.

4
  • What have you tried so far? Where do you get performance problems? Commented Jul 31, 2017 at 9:17
  • 2
    Would be good if you could share the code you already have. It shows you made an effort yourself and are not just looking for someone to write code for you. Also makes it a lot easier to see if you made any mistakes in the code and/or whether improvements are possible Commented Jul 31, 2017 at 9:20
  • Please show us you effort by using these nested loops. Then we can show you how to improve it. But if your code does the actual job and there is no performance concern why changing a working solution? Commented Jul 31, 2017 at 9:20
  • 1
    you do not have a 2D array. You have a 1D array of objects, and your objects contain 2 floats each. Commented Jul 31, 2017 at 9:30

3 Answers 3

1

If all you need is to find those values, it's enough to loop through the list one time. I suggest to study a little bit about Big O notation, to understand performance of algorithms.

You can do something like this:

float min_col1 = Float.MAX_VALUE;
float max_col1 = Float.MIN_VALUE;
float min_col2 = Float.MAX_VALUE;
float max_col2 = Float.MIN_VALUE;

for (DataSt data : list1) {

    if (data.getA() < min_col1) {
        min_col1 = data.getA();
    }

    if (data.getA() > max_col1) {
        max_col1 = data.getA();
    }

    if (data.getB() < min_col2) {
        min_col2 = data.getB();
    }

    if (data.getB() > max_col2) {
        max_col2 = data.getB();
    }
}
Sign up to request clarification or add additional context in comments.

5 Comments

If the list is empty you're stuck with having to check for a load of sentinel values.
The question is not about handling edge cases, is it? This is just a general approach to do it in one go.
Well either mention that in your answer or improve the code, otherwise its a bad answer.
Oh c'mon, in this case the values just remain set at a default value. Your answer will crash on empty list, lol. Nothing to do here... bye.
That's not a bad thing. Trying to get the min/max of nothing should result in an exception. Fail-safe solutions just become impossible to debug.
0

I worked out some sample for you.

    float Fmin = 0f;
    float Fmax = 0f;
    float Smin = 0f;
    float Smax = 0f;
    for (int i = 0; i < dataSts.size(); i++)
    {
        DataSt dataSt = dataSts.get(i);
        float a = dataSt.getA();
        float b = dataSt.getB();
        if(i == 0)
        {
            Fmin = a;
            Fmax = a;
            Smin = b;
            Smax = b;
            continue;
        }

        if(a < Fmin )
            Fmin = a;

        if(b < Smin )
            Smin = b;

        if(a > Fmax)
            Fmax = a;

        if(b > Smax)
            Smax = b;

    }
    System.out.println(Fmin +": "+Fmax+" : "+Smin+" : "+Smax);

Comments

0

It's a shame there's no FloatStream, but you can widen the values to doubles then narrow them back safely.

I've assumed you have getters for A and B that you've elided.

if (list1.isEmpty())
{
   throw /*something*/;
}
min_col1 = (float) list1.stream().mapToDouble(DataSt::getA).min().getAsDouble();
max_col1 = (float) list1.stream().mapToDouble(DataSt::getA).max().getAsDouble();
min_col2 = (float) list1.stream().mapToDouble(DataSt::getB).min().getAsDouble();
max_col2 = (float) list1.stream().mapToDouble(DataSt::getB).max().getAsDouble();

3 Comments

Is this more efficient than using Comparator.naturalOrder() in the min(),max() with a .map() instead of .mapToDouble ?
How come is this more efficient? This way you'll end up looping through the list 4 times .
I completely ignored the efficiency aspect. Without having measured that something is a problem, or having defined an efficiency goal, it's a completely meaningless requirement. In practice, this probably has negligibly worse performance than a for-loop-based solution and is significantly more clear and maintainable.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.