@Override
  public Iterator<Table> iterator() {
    return new Iterator<Table>() {

      private final Iterator<String> tableNamesIter = tableNames.iterator();
      private Iterator<org.apache.hadoop.hive.metastore.api.Table> batchIter = null;

      @Override
      public boolean hasNext() {
        return ((batchIter != null) && batchIter.hasNext()) || tableNamesIter.hasNext();
      }

      @Override
      public Table next() {
        if ((batchIter == null) || !batchIter.hasNext()) {
          getNextBatch();
        }
        return batchIter.next();
      }

      private void getNextBatch() {
        // get next batch of table names in this list
        List<String> nameBatch = new ArrayList<String>();
        int batchCounter = 0;
        while (batchCounter < batchSize && tableNamesIter.hasNext()) {
          nameBatch.add(tableNamesIter.next());
          batchCounter++;
        }
        // get the Table objects for this batch of table names and get iterator
        // on it

        try {
          if (catName != null) {
            batchIter = msc.getTableObjectsByName(catName, dbname, nameBatch).iterator();
          } else {
            batchIter = msc.getTableObjectsByName(dbname, nameBatch).iterator();
          }
        } catch (TException e) {
          throw new RuntimeException(e);
        }

      }

      @Override
      public void remove() {
        throw new IllegalStateException(
            "TableIterable is a read-only iterable and remove() is unsupported");
      }
    };
  }
Use this to get Table objects for a table list. It provides an iterator to
on the resulting Table objects. It batches the calls to
IMetaStoreClient.getTableObjectsByName to avoid OOM issues in HS2 (with
embedded metastore) or MetaStore server (if HS2 is using remote metastore).
standalone-metastore/metastore-common/src/main/java/org/apache/hadoop/hive/metastore/TableIterable.java