Bruno Souza
Bruno Souza

Reputation: 53

Using Guava's Tables.toTable

I have a List of Thing holding two atrributes : status (an Enum) and owner (another object).

I want to obtain a Guava Table<owner, status, Long> by traversing the ArrayList and counting the objects, including a count of 0 if some status isn't in the List, like that:

[owner1, status1, 2], [owner1, status2, 0], [owner2, status1, 3], [owner2, status2, 2]

how to use .collect(Tables.toTable()) in that case?

Upvotes: 4

Views: 1059

Answers (2)

assylias
assylias

Reputation: 328598

You need to provide mappers for the rows, columns, values, a merging function and a table supplier. So something like this:

list.stream().collect(Tables.toTable(
               Thing::getStatus,
               Thing::getOwner,
               t -> 1, //that's your counter
               (i, j) -> i + j, //that's the incrementing function
               HashBasedTable::create //a new table
            ));

Upvotes: 2

Alex Shesterov
Alex Shesterov

Reputation: 27525

The below code would create a table with counts, but without zero-counts.

List<Thing> listOfThings = ...;

Table<Owner, Status, Long> table = 
    listOfThings.stream().collect(
        Tables.toTable(
            Thing::getOwner,             // Row key extractor
            Thing::getStatus,            // Column key extractor
            thing -> 1,                  // Value converter (a single value counts '1')
            (count1, count2) -> count1 + count2, // Value merger (counts add up)
            HashBasedTable::create       // Table creator
        )
    );

To add the missing cells into the table (with zero-values), you would need to additionally iterate though all the possible values (of Status and Owner), and put the 0-value if there's no value yet. Note that, if Owner isn't an enum, there's no trivial way to get all of its possible values.

Or alternatively, instead of doing this, just check for nulls when retrieving values from the table.

Upvotes: 4

Related Questions