Guide to Guava Table
1. Overview
In this tutorial, we’ll show how to use the Google Guava’s Table interface and its multiple implementations.
Guava’s Table is a collection that represents a table like structure containing rows, columns and the associated cell values. The row and the column act as an ordered pair of keys.
2. Google Guava’s Table
2.1. Maven Dependency
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>21.0</version>
</dependency>
The latest version of the dependency can be checked here.
2.2. About
If we were to represent Guava’s Table using Collections present in core Java, then the structure would be a map of rows where each row contains a map of columns with associated cell values.
Table represents a special map where two keys can be specified in combined fashion to refer to a single value.
It’s similar to creating a map of maps, for example, Map<UniversityName, Map<CoursesOffered, SeatAvailable>>. Table would be also a perfect way of representing the Battleships game board.
3. Creating
-
Using the create method from the class HashBasedTable which uses LinkedHashMap internally:
Table<String, String, Integer> universityCourseSeatTable = HashBasedTable.create();
-
If we need a Table whose row keys and the column keys need to be ordered by their natural ordering or by supplying comparators, you can create an instance of a Table using the create method from a class called TreeBasedTable, which uses TreeMap internally:
Table<String, String, Integer> universityCourseSeatTable = TreeBasedTable.create();
-
If we know the row keys and the column keys beforehand and the table size is fixed, use the create method from the class ArrayTable:
List<String> universityRowTable = Lists.newArrayList("Mumbai", "Harvard"); List<String> courseColumnTables = Lists.newArrayList("Chemical", "IT", "Electrical"); Table<String, String, Integer> universityCourseSeatTable = ArrayTable.create(universityRowTable, courseColumnTables);
-
If we intend to create an immutable instance of Table whose internal data are never going to change, use the ImmutableTable class (creating which follows a builder pattern):
Table<String, String, Integer> universityCourseSeatTable = ImmutableTable.<String, String, Integer> builder() .put("Mumbai", "Chemical", 120).build();
4. Using
4.1. Retrieval
If we know the row key and the column key then we can get the value associated with the row and the column key:
@Test
public void givenTable_whenGet_returnsSuccessfully() {
Table<String, String, Integer> universityCourseSeatTable
= HashBasedTable.create();
universityCourseSeatTable.put("Mumbai", "Chemical", 120);
universityCourseSeatTable.put("Mumbai", "IT", 60);
universityCourseSeatTable.put("Harvard", "Electrical", 60);
universityCourseSeatTable.put("Harvard", "IT", 120);
int seatCount
= universityCourseSeatTable.get("Mumbai", "IT");
Integer seatCountForNoEntry
= universityCourseSeatTable.get("Oxford", "IT");
assertThat(seatCount).isEqualTo(60);
assertThat(seatCountForNoEntry).isEqualTo(null);
}
4.2. Checking for an Entry
-
Row key
-
Column key
-
Both row key and column key
-
Value
Let’s see how to check for the presence of an entry:
@Test
public void givenTable_whenContains_returnsSuccessfully() {
Table<String, String, Integer> universityCourseSeatTable
= HashBasedTable.create();
universityCourseSeatTable.put("Mumbai", "Chemical", 120);
universityCourseSeatTable.put("Mumbai", "IT", 60);
universityCourseSeatTable.put("Harvard", "Electrical", 60);
universityCourseSeatTable.put("Harvard", "IT", 120);
boolean entryIsPresent
= universityCourseSeatTable.contains("Mumbai", "IT");
boolean courseIsPresent
= universityCourseSeatTable.containsColumn("IT");
boolean universityIsPresent
= universityCourseSeatTable.containsRow("Mumbai");
boolean seatCountIsPresent
= universityCourseSeatTable.containsValue(60);
assertThat(entryIsPresent).isEqualTo(true);
assertThat(courseIsPresent).isEqualTo(true);
assertThat(universityIsPresent).isEqualTo(true);
assertThat(seatCountIsPresent).isEqualTo(true);
}
4.3. Removal
@Test
public void givenTable_whenRemove_returnsSuccessfully() {
Table<String, String, Integer> universityCourseSeatTable
= HashBasedTable.create();
universityCourseSeatTable.put("Mumbai", "Chemical", 120);
universityCourseSeatTable.put("Mumbai", "IT", 60);
int seatCount
= universityCourseSeatTable.remove("Mumbai", "IT");
assertThat(seatCount).isEqualTo(60);
assertThat(universityCourseSeatTable.remove("Mumbai", "IT")).
isEqualTo(null);
}
4.4. Row Key to Cell Value Map
We can get a Map representation with the key as a row and the value as a CellValue by providing the column key:
@Test
public void givenTable_whenColumn_returnsSuccessfully() {
Table<String, String, Integer> universityCourseSeatTable
= HashBasedTable.create();
universityCourseSeatTable.put("Mumbai", "Chemical", 120);
universityCourseSeatTable.put("Mumbai", "IT", 60);
universityCourseSeatTable.put("Harvard", "Electrical", 60);
universityCourseSeatTable.put("Harvard", "IT", 120);
Map<String, Integer> universitySeatMap
= universityCourseSeatTable.column("IT");
assertThat(universitySeatMap).hasSize(2);
assertThat(universitySeatMap.get("Mumbai")).isEqualTo(60);
assertThat(universitySeatMap.get("Harvard")).isEqualTo(120);
}
4.5. Map Representation of a Table
We can get a Map<UniversityName, Map<CoursesOffered, SeatAvailable>> representation by using the columnMap method:
@Test
public void givenTable_whenColumnMap_returnsSuccessfully() {
Table<String, String, Integer> universityCourseSeatTable
= HashBasedTable.create();
universityCourseSeatTable.put("Mumbai", "Chemical", 120);
universityCourseSeatTable.put("Mumbai", "IT", 60);
universityCourseSeatTable.put("Harvard", "Electrical", 60);
universityCourseSeatTable.put("Harvard", "IT", 120);
Map<String, Map<String, Integer>> courseKeyUniversitySeatMap
= universityCourseSeatTable.columnMap();
assertThat(courseKeyUniversitySeatMap).hasSize(3);
assertThat(courseKeyUniversitySeatMap.get("IT")).hasSize(2);
assertThat(courseKeyUniversitySeatMap.get("Electrical")).hasSize(1);
assertThat(courseKeyUniversitySeatMap.get("Chemical")).hasSize(1);
}
4.6. Column Key to Cell Value Map
We can get a Map representation with the key as a column and the value as a CellValue by providing row key:
@Test
public void givenTable_whenRow_returnsSuccessfully() {
Table<String, String, Integer> universityCourseSeatTable
= HashBasedTable.create();
universityCourseSeatTable.put("Mumbai", "Chemical", 120);
universityCourseSeatTable.put("Mumbai", "IT", 60);
universityCourseSeatTable.put("Harvard", "Electrical", 60);
universityCourseSeatTable.put("Harvard", "IT", 120);
Map<String, Integer> courseSeatMap
= universityCourseSeatTable.row("Mumbai");
assertThat(courseSeatMap).hasSize(2);
assertThat(courseSeatMap.get("IT")).isEqualTo(60);
assertThat(courseSeatMap.get("Chemical")).isEqualTo(120);
}
4.7. Get Distinct Row Key
@Test
public void givenTable_whenRowKeySet_returnsSuccessfully() {
Table<String, String, Integer> universityCourseSeatTable
= HashBasedTable.create();
universityCourseSeatTable.put("Mumbai", "Chemical", 120);
universityCourseSeatTable.put("Mumbai", "IT", 60);
universityCourseSeatTable.put("Harvard", "Electrical", 60);
universityCourseSeatTable.put("Harvard", "IT", 120);
Set<String> universitySet = universityCourseSeatTable.rowKeySet();
assertThat(universitySet).hasSize(2);
}
4.8. Get Distinct Column Key
@Test
public void givenTable_whenColKeySet_returnsSuccessfully() {
Table<String, String, Integer> universityCourseSeatTable
= HashBasedTable.create();
universityCourseSeatTable.put("Mumbai", "Chemical", 120);
universityCourseSeatTable.put("Mumbai", "IT", 60);
universityCourseSeatTable.put("Harvard", "Electrical", 60);
universityCourseSeatTable.put("Harvard", "IT", 120);
Set<String> courseSet = universityCourseSeatTable.columnKeySet();
assertThat(courseSet).hasSize(3);
}
5. Conclusion
In this tutorial, we illustrated the methods of the Table class from the Guava library. The Table class provides a collection that represents a table like structure containing rows, columns and associated cell values.
The code belonging to the above examples can be found in the GitHub project – this is a Maven-based project, so it should be easy to import and run as is.