Boost Your Java Code Efficiency with Guava’s Table API
The article explains Guava’s Table data structure—a two‑key map—covers its main implementations, provides a complete Java demo for creating, querying, updating, and iterating tables, compares it with nested maps, and highlights its type safety, usability, memory efficiency, and immutability advantages.
Java developers often use Map for key‑value storage, but some scenarios require a two‑dimensional mapping where a row key and a column key together identify a value; Guava’s Table interface is designed for this purpose.
What Is Guava Table
Guava’s Table is a special data structure that uses two keys (row key and column key) to map to a single value, effectively acting as a two‑dimensional Map where each cell is uniquely identified by its row and column keys.
Guava Table Implementations
HashBasedTable : The most common implementation, backed by hash tables, offering fast insert, lookup, and delete operations without preserving key order.
TreeBasedTable : Uses red‑black trees to keep rows and columns sorted according to natural order or a provided comparator; iteration in key order is efficient, though insert and lookup may be slower than hash‑based.
ImmutableTable : An immutable implementation that receives all data at creation time and disallows further modification, providing efficient memory usage and safe sharing across threads.
How to Use Guava Table
Below is a complete demo that creates a Table, adds data, retrieves values, updates entries, iterates over cells, checks for the existence of keys, and removes data.
import com.google.common.collect.HashBasedTable;
import com.google.common.collect.Table;
import java.util.Map;
import java.util.Set;
public class GuavaTableAdvancedExample {
public static void main(String[] args) {
// Create a Table instance
Table<String, String, Integer> workHoursTable = HashBasedTable.create();
// Add data
workHoursTable.put("Alice", "ProjectA", 40);
workHoursTable.put("Bob", "ProjectA", 30);
workHoursTable.put("Alice", "ProjectB", 20);
workHoursTable.put("Charlie", "ProjectC", 50);
// Retrieve data
Integer aliceProjectAHours = workHoursTable.get("Alice", "ProjectA");
System.out.println("Alice worked " + aliceProjectAHours + " hours on ProjectA.");
// Get a specific row as a map
Map<String, Integer> aliceWorkHours = workHoursTable.row("Alice");
System.out.println("Alice's work hours: " + aliceWorkHours);
// Get a specific column as a map
Map<String, Integer> projectAWorkHours = workHoursTable.column("ProjectA");
System.out.println("Work hours on ProjectA: " + projectAWorkHours);
// Iterate over the table
for (Table.Cell<String, String, Integer> cell : workHoursTable.cellSet()) {
System.out.println(cell.getRowKey() + " worked " + cell.getValue() + " hours on " + cell.getColumnKey() + ".");
}
// Update data
workHoursTable.put("Alice", "ProjectA", aliceProjectAHours + 5);
System.out.println("After update, Alice worked " + workHoursTable.get("Alice", "ProjectA") + " hours on ProjectA.");
// Check for a specific key‑value pair
boolean hasBobOnProjectB = workHoursTable.contains("Bob", "ProjectB");
System.out.println("Does Bob work on ProjectB? " + hasBobOnProjectB);
// Check if a row or column exists
boolean hasRowKeyCharlie = workHoursTable.containsRow("Charlie");
boolean hasColumnKeyProjectD = workHoursTable.containsColumn("ProjectD");
System.out.println("Does the table have a row for Charlie? " + hasRowKeyCharlie);
System.out.println("Does the table have a column for ProjectD? " + hasColumnKeyProjectD);
// Get all row keys, column keys, and values
Set<String> allRowKeys = workHoursTable.rowKeySet();
Set<String> allColumnKeys = workHoursTable.columnKeySet();
Set<Integer> allValues = workHoursTable.values();
System.out.println("All row keys: " + allRowKeys);
System.out.println("All column keys: " + allColumnKeys);
System.out.println("All values: " + allValues);
// Remove data
workHoursTable.remove("Alice", "ProjectB");
System.out.println("After removal, Alice's work hours on ProjectB: " + workHoursTable.get("Alice", "ProjectB"));
}
}If you do not use Table, you would need to implement a nested Map, which makes certain operations more cumbersome, such as checking for the existence of a column key, which requires iterating all inner maps, and lacks the advanced features and optimizations provided by Guava Table.
// Simulate Table with a nested Map
Map<String, Map<String, Integer>> workHoursMap = new HashMap<>();
// Add data
addWorkHours(workHoursMap, "Alice", "ProjectA", 40);
addWorkHours(workHoursMap, "Bob", "ProjectA", 30);
addWorkHours(workHoursMap, "Alice", "ProjectB", 20);
addWorkHours(workHoursMap, "Charlie", "ProjectC", 50);
// Retrieve data
Integer aliceProjectAHours = getWorkHours(workHoursMap, "Alice", "ProjectA");
System.out.println("Alice worked " + aliceProjectAHours + " hours on ProjectA.");
// Iterate nested Map
for (Map.Entry<String, Map<String, Integer>> entry : workHoursMap.entrySet()) {
String employee = entry.getKey();
Map<String, Integer> projects = entry.getValue();
for (Map.Entry<String, Integer> projectEntry : projects.entrySet()) {
String project = projectEntry.getKey();
Integer hours = projectEntry.getValue();
System.out.println(employee + " worked " + hours + " hours on " + project + ".");
}
}
// Update data
setWorkHours(workHoursMap, "Alice", "ProjectA", aliceProjectAHours + 5);
System.out.println("After update, Alice worked " + getWorkHours(workHoursMap, "Alice", "ProjectA") + " hours on ProjectA.");
// Check for a specific key‑value pair
boolean hasBobOnProjectB = containsWorkHours(workHoursMap, "Bob", "ProjectB");
System.out.println("Does Bob work on ProjectB? " + hasBobOnProjectB);
// Check if a row key exists
boolean hasRowKeyCharlie = workHoursMap.containsKey("Charlie");
System.out.println("Does the nested map have an entry for Charlie? " + hasRowKeyCharlie);
// Check if a column key exists (requires iterating all inner maps)
boolean hasColumnKeyProjectD = false;
for (Map<String, Integer> projectMap : workHoursMap.values()) {
if (projectMap.containsKey("ProjectD")) {
hasColumnKeyProjectD = true;
break;
}
}
System.out.println("Does any employee work on ProjectD? " + hasColumnKeyProjectD);
// Remove data
removeWorkHours(workHoursMap, "Alice", "ProjectB");
System.out.println("After removal, Alice's work hours on ProjectB: " + getWorkHours(workHoursMap, "Alice", "ProjectB"));
private static void addWorkHours(Map<String, Map<String, Integer>> workHoursMap, String rowKey, String columnKey, Integer value) {
workHoursMap.putIfAbsent(rowKey, new HashMap<>());
workHoursMap.get(rowKey).put(columnKey, value);
}
private static Integer getWorkHours(Map<String, Map<String, Integer>> workHoursMap, String rowKey, String columnKey) {
Map<String, Integer> projectMap = workHoursMap.get(rowKey);
return projectMap != null ? projectMap.get(columnKey) : null;
}
private static void setWorkHours(Map<String, Map<String, Integer>> workHoursMap, String rowKey, String columnKey, Integer value) {
workHoursMap.putIfAbsent(rowKey, new HashMap<>());
workHoursMap.get(rowKey).put(columnKey, value);
}
private static boolean containsWorkHours(Map<String, Map<String, Integer>> workHoursMap, String rowKey, String columnKey) {
Map<String, Integer> projectMap = workHoursMap.get(rowKey);
return projectMap != null && projectMap.containsKey(columnKey);
}
private static void removeWorkHours(Map<String, Map<String, Integer>> workHoursMap, String rowKey, String columnKey) {
Map<String, Integer> projectMap = workHoursMap.get(rowKey);
if (projectMap != null) {
projectMap.remove(columnKey);
if (projectMap.isEmpty()) {
workHoursMap.remove(rowKey);
}
}
}Advantages of Guava Table
Type Safety : Table explicitly defines the types of row keys, column keys, and values, reducing casting errors.
Ease of Use : Provides intuitive APIs for insertion, retrieval, and iteration, making code more readable and maintainable.
Memory Efficiency : Implementations are optimized for their specific use cases, offering efficient memory consumption.
Immutability : ImmutableTable enables creation of read‑only tables, which is useful for concurrent programming and immutable‑object patterns.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Programmer1970
Formerly called 'Code to 35'. Add our main WeChat ID to access a wealth of shared resources (algorithms, interview prep, tech stacks: Java, Python, Go, big data). We mainly share serious development techniques, focusing on output-driven input. Occasionally we post life snippets and gossip. Our aim is to attract precise traffic and test advertising opportunities.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
