Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

java streams operate on all values

edit - second class does not have indexed based access, instead it implements iterable

Suppose a class structure like this:

public class Values
{
    public int getValue(int i)
    {
        return values_[i];
    }

    private int[] values_;
}

and a second class like this

public class ValuesCollection implements Iterable
{
    private Values[] valuesCollection_;
}

Is there a way using java8 streams API to operate statistics along each dimension for instance: sum, mean, min, max, range, variance, std, etc. For example [[2,4,8],[1,5,7],[3,9,6]], for getting min it would return [1,4,6]

The closest I can come up with is something like this:

public int[] getMin(ValuesCollection valuesCollection)
{

    IntStream.range(0, valuesCollection.size()).boxed().collect(Collectors.toList())
            .forEach(i -> {

                List<Integer> vals = valuesCollection.stream()
                        .map(values -> values.getValue(i))
                        .collect(Collectors.toList());

                // operate statistics on vals
                // no way to return the statistics
            });

}
like image 833
rossb83 Avatar asked May 16 '26 21:05

rossb83


1 Answers

You can do it. I've used arrays rather than your wrapper classes. Also, I should probably have included some validation that the array is rectangular, and used orElseThrow rather than getAsInt, but you get the idea.

int[][] vals = {{2, 4, 8}, {1, 5, 7}, {3, 9, 6}};

int[] min = IntStream
               .range(0, vals[0].length)
               .map(j -> IntStream.range(0, vals.length).map(i -> vals[i][j]).min().getAsInt())
               .toArray();

System.out.println(Arrays.toString(min));       // Prints [1, 4, 6] as expected

(Since I used arrays, I could have used this line instead

.map(j -> Arrays.stream(vals).mapToInt(arr -> arr[j]).min().getAsInt())

but I wrote it like I did to closely model your situation where your objects are not arrays but do have indexed based access.)

Doing it for standard deviation is obviously harder, but you can do it by combining my answer with this one.

Edit

If your outer class does not have indexed based access, but instead implements Iterable you can do it by converting the Iterable to a Stream.

Iterable<int[]> vals = Arrays.asList(new int[][] {{2, 4, 8}, {1, 5, 7}, {3, 9, 6}});

int[] min = IntStream
               .range(0, vals.iterator().next().length)
               .map(j -> StreamSupport.stream(vals.spliterator(), false).mapToInt(a -> a[j]).min().getAsInt())
               .toArray();

System.out.println(Arrays.toString(min));       // Prints [1, 4, 6] as expected
like image 54
Paul Boddington Avatar answered May 19 '26 11:05

Paul Boddington



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!