nt fury
nt fury

Reputation: 11

Efficient way to find the min/max of each field in an ArrayList of objects

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.

Upvotes: 0

Views: 130

Answers (3)

Michael
Michael

Reputation: 44230

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();

Upvotes: 0

Prasath
Prasath

Reputation: 1284

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);

Upvotes: 0

Andrej Jurkin
Andrej Jurkin

Reputation: 2266

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();
    }
}

Upvotes: 1

Related Questions