Divide A List To Sub-Lists Via Collectors

Consider a List of Color objects with attributes of index, name and group. This object is defined as,

public class Color {

    private int index;

    private String name;

    private Group group;

}

Group is simply an Enum of,

public enum Group {

    RED,
    GREEN,
    BLUE;

}

My list of colors are the following,

    Color royalBlue = new Color(7, "Royal Blue", Group.BLUE);
    Color soulRedCrystal = new Color(2, "Soul Red Crystal", Group.RED);
    Color matchaGreen = new Color(4, "Matcha Green", Group.GREEN);
    Color deepOcean = new Color(5, "Deep Ocean", Group.BLUE);
    Color darkPine = new Color(3, "Dark Pine", Group.GREEN);
    Color sexyRouge = new Color(1, "Sexy Rouge", Group.RED);
    Color hyperlinkBlue = new Color(6, "Hyperlink Blue", Group.BLUE);

    List<Color> colorList = new ArrayList<>();
    // add colors above after

Now, I want to divide these colors into their own sub-lists of color grouping based on the value of the object’s Group attribute.

Traditionally, this can be done with the venerable for loop and some if-else statements.

    List<Color> redGroup = new ArrayList<>();
    List<Color> greenGroup = new ArrayList<>();
    List<Color> blueGroup = new ArrayList<>();

    for (Color color : colorList) {
        if (color.getGroup().equals(Group.BLUE) {
            // assign to its own group of blues
            blueGroup.add(color);
        }
        // Other code omitted for brevity
    }

If I want to not write it with a bunch of if-else statements, the Java 8 Stream API approach can be utilized. For multiple groups, one way is to use Collectors.groupingBy to separate the elements each to their respective group.

    Map<Group, List<Color>> colorGroups = colorList.stream()
            .collect(Collectors.groupingBy(color -> color.getGroup()));

Each color group can then be retrieved (and assigned to a sub-list as necessary) like this,

colorGroups.get(Group.BLUE));

Both ways will have the same output, regardless.

[Color(index=2, name=Soul Red Crystal, group=RED), Color(index=1, name=Sexy Rouge, group=RED)]

[Color(index=4, name=Matcha Green, group=GREEN), Color(index=3, name=Dark Pine, group=GREEN)]

[Color(index=7, name=Royal Blue, group=BLUE), Color(index=5, name=Deep Ocean, group=BLUE), Color(index=6, name=Hyperlink Blue, group=BLUE)]

Or if I want to group these colors according to their index attribute and split them out into evens and odds, use the Collectors.partitioningBy approach.

    Map<Boolean, List<Color>> colorGroups = colorList.stream()
            .collect(Collectors.partitioningBy(color -> color.getIndex() % 2 == 0));

In order to get the even group,

colorGroups.get(true)

Here, true has the colors that have even-numbered index because of our condition – color.getIndex() % 2 == 0. The odd-numbered colors will then be assigned to false.

[Color(index=2, name=Soul Red Crystal, group=RED), Color(index=4, name=Matcha Green, group=GREEN), Color(index=6, name=Hyperlink Blue, group=BLUE)]

[Color(index=7, name=Royal Blue, group=BLUE), Color(index=5, name=Deep Ocean, group=BLUE), Color(index=3, name=Dark Pine, group=GREEN), Color(index=1, name=Sexy Rouge, group=RED)]

Similar Posts: