Search code examples
javajava-8guava

Converting List of object to Guava Table data structure using lambda


I have list of ImmutableTriple object where for first and middle there could collection of last values (first, middle and last are triple values). Now in order to make it queryable, I need to convert it to Guava Table data structure. I am able to achieve this, with for loop as below but I am wondering if I can achieve this more functionally using lambda expression. here is the piece code -

public static void main(String[] args) {
    //In real world, this list is coming from various transformation of lamda
    final List<ImmutableTriple<LocalDate, Integer, String>> list = ImmutableList.of(
            ImmutableTriple.of(LocalDate.now(), 1, "something"),
            ImmutableTriple.of(LocalDate.now(), 1, "anotherThing")
    );
    Table<LocalDate, Integer, List<String>> table = HashBasedTable.create();
    //is it possible to avoid this forEach and use side effect free lambda.
    list.forEach(s -> {
        final List<String> strings = table.get(s.left, s.middle);
        final List<String> slotList = strings == null ? new ArrayList<>() : strings;
        slotList.add(s.right);
        table.put(s.left, s.middle, slotList);
    });
    System.out.println(table);
}

Solution

  • There is a Tables class which contains a Collector to get your desired result.

    Table<LocalDate, Integer, ImmutableList<String>> collect = list.stream()
            .collect(Tables.toTable(
                    it -> it.left,
                    it -> it.middle,
                    it -> ImmutableList.of(it.right),
                    (l1, l2) -> ImmutableList.<String>builder()
                            .addAll(l1).addAll(l2).build(), 
                    HashBasedTable::create));
    

    If you really want a mutable List then you can use:

    Table<LocalDate, Integer, List<String>> collect = list.stream()
            .collect(Tables.toTable(
                    it -> it.left,
                    it -> it.middle,
                    it -> Lists.newArrayList(it.right),
                    (l1, l2) -> {l1.addAll(l2); return l1;},
                    HashBasedTable::create));