Java 8. Group a list of values into a list of ranges using Collectors

Arturo González

I need your help,

In Java 8 using Collectors groupingBy I need to group a list like this

ValueObject {id=1, value=2.0}
ValueObject {id=2, value=2.0}
ValueObject {id=3, value=2.0}
ValueObject {id=4, value=3.0}
ValueObject {id=5, value=3.0}
ValueObject {id=6, value=4.0}
ValueObject {id=7, value=4.0}
ValueObject {id=8, value=4.0}
ValueObject {id=9, value=4.0}
ValueObject {id=10, value=4.0}

in another one like this

GroupedObject {from=1, to=3, value=2.0}
GroupedObject {from=4, to=5, value=3.0}
GroupedObject {from=6, to=10, value=4.0}

Those are the definitions of the objects i'm using

public class ValueObject {

  private int id;
  private double value;

  public String getId() {
    return id;
  }

  public float getValue() {
    return value;
  }

  public void setValue(float value) {
    this.value = value;
  }

}

public class GroupedObject {

    private int from;
    private int to;
    private double value;

    public int getFrom() {
        return from;
    }

    public void setFrom(int from) {
        this.from = from;
    }

    public int getTo() {
        return to;
    }

    public void setTo(int to) {
        this.to = to;
    }

    public double getValue() {
        return value;
    }

    public void setValue(double value) {
        this.value = value;
    }

}

And this is how i'm doing it programmatically.

public class Service {

    public List<GroupedObject> groupToRange(List<ValueObject> list) {

        List<GroupedObject> filtered = new ArrayList<>();

        if (list.size() > 0) {

            ValueObject current = list.get(0);
            GroupedObject dto = new GroupedObject();
            dto.setValue(current.getValue());
            dto.setFrom(current.getId());

            for (int i = 0; i < list.size(); i++) {
                ValueObject vo = list.get(i);
                if (vo.getValue() != current.getValue()) {

                    dto.setTo(current.getId());
                    filtered.add(dto);

                    dto = new GroupedObject();
                    dto.setValue(vo.getValue());
                    dto.setFrom(vo.getId());
                    current = vo;

                } else {
                    current = vo;
                }
                if (i == list.size() - 1) {
                    dto.setTo(vo.getId());
                    filtered.add(dto);
                }
            }
        }
        return filtered;
    }

}

this is the unit test

public class ServiceTest {

    Service service = new Service();

    @Test
    public void testgGoupToRange() {

        List entryList = new ArrayList<>();

        entryList.add(new ValueObject(1, 2.0));
        entryList.add(new ValueObject(2, 2.0));
        entryList.add(new ValueObject(3, 2.0));
        entryList.add(new ValueObject(4, 3.0));
        entryList.add(new ValueObject(5, 3.0));
        entryList.add(new ValueObject(6, 4.0));
        entryList.add(new ValueObject(7, 4.0));
        entryList.add(new ValueObject(8, 4.0));
        entryList.add(new ValueObject(9, 4.0));
        entryList.add(new ValueObject(10, 4.0));

        List responseList = service.groupToRange(entryList);

        responseList.forEach(obj-> System.out.println(obj.toString()));

        assertNotNull(responseList);
        assertEquals(3, responseList.size());

    }

}

I havn´t found a way of doing it whit java 8 and collectors

GuiSim

Here's what I came up with

List<ValueObject> values = Arrays.asList(new ValueObject(1, 2.0),
                                         new ValueObject(2, 2.0),
                                         new ValueObject(3, 3.0),
                                         new ValueObject(4, 4.0),
                                         new ValueObject(5, 4.0),
                                         new ValueObject(6, 4.0));
Map<Double, IntSummaryStatistics> groupedValues = values.stream()
                                                        .collect(Collectors.groupingBy(ValueObject::getValue,
                                                                                       Collectors.summarizingInt(ValueObject::getId)));

List<GroupedObject> groupedObjects = groupedValues.entrySet()
                                                  .stream()
                                                  .map(groupedValue -> new GroupedObject(groupedValue.getValue().getMin(),
                                                                                  groupedValue.getValue().getMax(),
                                                                                  groupedValue.getKey()))
                                                  .collect(Collectors.toList());
System.out.println(groupedObjects);

I'm pretty confident that there's a way to avoid the intermediary Map<Double, IntSummaryStatistics but I haven't figured it out yet. Will update if I do.

EDIT: See @Tunaki's answer for a 1 pass answer.

This is the output

[GroupedObject{from=4, to=6, value=4.0}, GroupedObject{from=1, to=2, value=2.0}, GroupedObject{from=3, to=3, value=3.0}]

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

Java 8 - How to group and sum on a list of maps using stream collectors

From Dev

Java 8 - How to group and sum on a list of maps using stream collectors

From Dev

Map with LIst using Collectors.toMap in Java 8

From Dev

sparse list of values using ranges

From Dev

What is the default Set/List implementation with Collectors in Java 8 Stream API?

From Dev

Using ReduceByKey to group list of values

From Dev

Using ReduceByKey to group list of values

From Dev

Collectors collect a list of pair in java

From Dev

Getting average data from list using Collectors.averagingInt java

From Dev

How to group List of Lists using a certain criteria in Java 8

From Dev

How to multiply values in a list using java 8 streams

From Dev

How to filter a List using Java 8 stream and startwith array of values

From Dev

How to sum the values in List<int[]> using Java 8

From Dev

How to multiply values in a list using java 8 streams

From Dev

issue with java 8 collectors Type mismatch: cannot convert from List<Object> to List<String>

From Dev

Effectively map list of ranges to list of values in file

From Dev

Java 8 - Group a list and find the count

From Dev

Group By List of object on multiple fields Java 8

From Dev

Java8 group a list of lists to map

From Dev

How to use java 8 streams to make a new list by using another's list objects values with filter?

From Dev

Transform List into Map using only two keys and odd or even list indexes as values - Java 8 Stream

From Dev

Java Collectors.groupingBy()---is List ordered?

From Java

Use Collectors to convert List to Map of Objects - Java

From Dev

Use Collectors to convert List to Map of Objects - Java

From Dev

Java Collectors.groupingBy()---is List ordered?

From Dev

Tool to group a list of IP addresses into IP ranges

From Dev

stream creating List of List (nested List) using forEach, Java 8

From Dev

Get enum values as List of String in Java 8

From Dev

Java 8 Collections - Filtering on values in nested list

Related Related

  1. 1

    Java 8 - How to group and sum on a list of maps using stream collectors

  2. 2

    Java 8 - How to group and sum on a list of maps using stream collectors

  3. 3

    Map with LIst using Collectors.toMap in Java 8

  4. 4

    sparse list of values using ranges

  5. 5

    What is the default Set/List implementation with Collectors in Java 8 Stream API?

  6. 6

    Using ReduceByKey to group list of values

  7. 7

    Using ReduceByKey to group list of values

  8. 8

    Collectors collect a list of pair in java

  9. 9

    Getting average data from list using Collectors.averagingInt java

  10. 10

    How to group List of Lists using a certain criteria in Java 8

  11. 11

    How to multiply values in a list using java 8 streams

  12. 12

    How to filter a List using Java 8 stream and startwith array of values

  13. 13

    How to sum the values in List<int[]> using Java 8

  14. 14

    How to multiply values in a list using java 8 streams

  15. 15

    issue with java 8 collectors Type mismatch: cannot convert from List<Object> to List<String>

  16. 16

    Effectively map list of ranges to list of values in file

  17. 17

    Java 8 - Group a list and find the count

  18. 18

    Group By List of object on multiple fields Java 8

  19. 19

    Java8 group a list of lists to map

  20. 20

    How to use java 8 streams to make a new list by using another's list objects values with filter?

  21. 21

    Transform List into Map using only two keys and odd or even list indexes as values - Java 8 Stream

  22. 22

    Java Collectors.groupingBy()---is List ordered?

  23. 23

    Use Collectors to convert List to Map of Objects - Java

  24. 24

    Use Collectors to convert List to Map of Objects - Java

  25. 25

    Java Collectors.groupingBy()---is List ordered?

  26. 26

    Tool to group a list of IP addresses into IP ranges

  27. 27

    stream creating List of List (nested List) using forEach, Java 8

  28. 28

    Get enum values as List of String in Java 8

  29. 29

    Java 8 Collections - Filtering on values in nested list

HotTag

Archive