user3222372
user3222372

Reputation: 382

Creating guava Table from Map

I have a Map data structure as mentioned below. I want to convert this into Table. I am trying to achieve this using Tables.newCustomTable() method but getting below error.

Exception in thread "main" java.lang.IllegalArgumentException
    at com.google.common.base.Preconditions.checkArgument(Preconditions.java:111)
    at com.google.common.collect.Tables.newCustomTable(Tables.java:299)

The Code is:

public class TestClass {

  public static void main(String[] args) {
    Map<Integer, Map<Integer, String>> data = Maps.newHashMap();
    Map<Integer, String> internalMap = Maps.newHashMap();

    internalMap.put(1, "A");
    internalMap.put(2, "B");
    internalMap.put(3, "C");

    data.put(1, internalMap);
    data.put(2, internalMap);
    data.put(3, internalMap);

    Table<Integer, Integer, String> table = table(data);
    System.out.println(table);
  }

  public static <R, C, V> Table<R, C, V> table(Map<R, Map<C, V>> toTable) {
    return Tables.newCustomTable(toTable, new Supplier<Map<C, V>>() {
      @Override
      public Map<C, V> get() {
        return Maps.newLinkedHashMap();
      }
    });
  }
}

Upvotes: 2

Views: 3453

Answers (2)

user3222372
user3222372

Reputation: 382

public static <R, C, V> Table<R, C, V> table(Map<R, Map<C, V>> fromTable)
{
    Table<R, C, V> table = HashBasedTable.create();
    for (R rowKey : fromTable.keySet())
    {
        Map<C, V> rowMap = fromTable.get(rowKey);
        for (C columnKey : rowMap.keySet())
        {
            V value = rowMap.get(columnKey);
            table.put(rowKey, columnKey, value);
        }
    }
    return table;
}

Upvotes: 1

Seelenvirtuose
Seelenvirtuose

Reputation: 20618

The documentation of Tables.newCustomTable clearly says:

Throws:
IllegalArgumentException - if backingMap is not empty

So you must provide an empty map, but you filled it with some data.

EDIT as per the comments:

The method Tables.newCustomTable does not transform an already data containing map into a table view. It is used for a more custom behavior when it comes to create the underyling maps. In fact, the method Tables.newCustomTable only gives more control over the concrete type of maps that should be created for rows and columns. For example, it can be used as following:

public static <R extends Comparable<R>, C, V> Table<R, C, V> createTable() {
    return Tables.newCustomTable(Maps.newTreeMap(), new Supplier<Map<C, V>>() {
        @Override
        public Map<C, V> get() {
            return Maps.newLinkedHashMap();
        }
    });
}

Note that I used TreeMap for the rows and LinkedHashMap for the columns. (I needed to constrain the type parameter R to extend Comparable, by the way.)

In most cases you do not need that behavior and thus you can write your method as following:

public static <R, C, V> Table<R, C, V> table(Map<R, Map<C, V>> fromTable)
{
    Table<R, C, V> table = HashBasedTable.create();
    for (R rowKey : fromTable.keySet())
    {
        Map<C, V> rowMap = fromTable.get(rowKey);
        for (C columnKey : rowMap.keySet())
        {
            V value = rowMap.get(columnKey);
            table.put(rowKey, columnKey, value);
        }
    }
    return table;
}

Upvotes: 2

Related Questions