javajava-stream

Average difference between elements


I need to transform list (time, channel) which is sorted by time ascending:

[15, A], [16, B], [17, C], [20, A], [22, C], [24, B], [26, C], [27, B], [28, A]

to this one:

[6.5, A], // ((20-15)+(28-20))/2 - average difference between elements (channel A) 
[5.5, B], // ((24-16)+(27-24))/2
[4.5, C]   // ((22-17)+(26-22))/2

using java streams.


Solution

  • Well, supposing that there is something like ChannelInfo class:

        class ChannelInfo {
           private final int time;
           private final String channel; 
           // constructor, getters, setters 
    

    it could be achieved like this:

     List<ChannelInfo> pairs = Arrays.asList(
                new ChannelInfo(15, "A"), new ChannelInfo(16, "B"), 
                new ChannelInfo(17, "C"), new ChannelInfo(20, "A"), 
                new ChannelInfo(22, "C"), new ChannelInfo(24, "B"), 
                new ChannelInfo(26, "C"), new ChannelInfo(27, "B"), 
                new ChannelInfo(28, "A"));
    
        Map<String, Double> map = pairs.stream()
                .collect(Collectors.groupingBy(ChannelInfo::getChannel, 
                           Collectors.collectingAndThen(Collectors.toList(),
                             list -> {
                                int size = list.size();
                                return IntStream.range(1, size)
                                    .map(x -> (list.get(size - x).getTime() - list.get(size - x - 1).getTime()))
                                    .average()
                                    .orElse(0d);
    
                        })));
    
        System.out.println(map); // {A=6.5, B=5.5, C=4.5}