How and Where to Use Iterators
An object of an iterator interface can be used to traverse through all elements of a collection. Iterators can be used to inspect the data in a collection but they cannot be used to modify the underlying collection. In general, to use an iterator to cycle through the contents of a collection, following steps have to be taken:
- Obtain an iterator to the start of the collection by calling the collection’s iterator method.
- Set up a loop that makes a call to hasNext method. Have the loop iterate as long as hasNext method returns true.
- Within the loop, obtain each element by calling next method.
Aspose.Cells APIs provide a bunch of iterators, however, this article mainly discusses the three types as listed below.
- Cells Iterator
- Rows Iterator
- Columns Iterator
How to use Iterators
Cells Iterator
There are various ways to access the cells' iterator, and one can use any of these methods based on the application requirements. Here are the methods that return the cells' iterator.
- Cells.iterator
- Row.iterator
- Range.iterator
All of the above mentioned methods return the iterator that allows to traverse the collection of cells which have been initialized.
The following code example demonstrates the implementation of the Iterator class for a cells collection.
// For complete examples and data files, please go to https://github.com/aspose-cells/Aspose.Cells-for-Java | |
String dataDir = Utils.getDataDir(CellsIterator.class); | |
// Load a file in an instance of Workbook | |
Workbook book = new Workbook(dataDir + "sample.xlsx"); | |
// Get the iterator from Cells collection | |
Iterator cellIterator = book.getWorksheets().get(0).getCells().iterator(); | |
// Traverse cells in the collection | |
while (cellIterator.hasNext()) { | |
Cell cell = (Cell) cellIterator.next(); | |
; | |
System.out.println(cell.getName() + " " + cell.getValue()); | |
} | |
// Get iterator from an object of Row | |
Iterator rowIterator = book.getWorksheets().get(0).getCells().getRows().get(0).iterator(); | |
// Traverse cells in the given row | |
while (rowIterator.hasNext()) { | |
Cell cell = (Cell) rowIterator.next(); | |
System.out.println(cell.getName() + " " + cell.getValue()); | |
} | |
// Get iterator from an object of Range | |
Iterator rangeIterator = book.getWorksheets().get(0).getCells().createRange("A1:B10").iterator(); | |
// Traverse cells in the range | |
while (rangeIterator.hasNext()) { | |
Cell cell = (Cell) rangeIterator.next(); | |
System.out.println(cell.getName() + " " + cell.getValue()); | |
} |
Rows Iterator
The Rows Iterator can be accessed while using the RowCollection.iterator method. The following code example demonstrates the implementation of the Iterator for RowCollection class.
// For complete examples and data files, please go to https://github.com/aspose-cells/Aspose.Cells-for-Java | |
String dataDir = Utils.getDataDir(RowsIterator.class); | |
// Load a file in an instance of Workbook | |
Workbook book = new Workbook(dataDir + "sample.xlsx"); | |
// Get the iterator for RowCollection | |
Iterator rowsIterator = book.getWorksheets().get(0).getCells().getRows().iterator(); | |
// Traverse rows in the collection | |
while (rowsIterator.hasNext()) { | |
Row row = (Row) rowsIterator.next(); | |
System.out.println(row.getIndex()); | |
} |
Columns Iterator
The Columns Iterator can be accessed while using the ColumnCollection.iterator method. The following code example demonstrates the implementation of the Iterator for ColumnCollection class.
// For complete examples and data files, please go to https://github.com/aspose-cells/Aspose.Cells-for-Java | |
String dataDir = Utils.getDataDir(ColumnsIterator.class); | |
// Load a file in an instance of Workbook | |
Workbook book = new Workbook(dataDir + "sample.xlsx"); | |
// Get the iterator for ColumnsCollection | |
Iterator colsIterator = book.getWorksheets().get(0).getCells().getColumns().iterator(); | |
// Traverse columns in the collection | |
while (colsIterator.hasNext()) { | |
Column col = (Column) colsIterator.next(); | |
System.out.println(col.getIndex()); | |
} |
Where to use Iterators
In order to discuss the advantages of using iterators, lets take a real time example.
Scenario
An application requirement is to traverse all cells in a given Worksheet to read their values. There could be several ways to implement this goal. A few are demonstrated below.
Using Display Range
// For complete examples and data files, please go to https://github.com/aspose-cells/Aspose.Cells-for-Java | |
String dataDir = Utils.getDataDir(UsingDisplayRange.class); | |
// Load a file in an instance of Workbook | |
Workbook book = new Workbook(dataDir + "sample.xlsx"); | |
// Get Cells collection of first worksheet | |
Cells cells = book.getWorksheets().get(0).getCells(); | |
// Get the MaxDisplayRange | |
Range displayRange = cells.getMaxDisplayRange(); | |
// Loop over all cells in the MaxDisplayRange | |
for (int row = displayRange.getFirstRow(); row < displayRange.getRowCount(); row++) { | |
for (int col = displayRange.getFirstColumn(); col < displayRange.getColumnCount(); col++) { | |
// Read the Cell value | |
System.out.println(displayRange.get(row, col).getStringValue()); | |
} | |
} |
Using MaxDataRow & MaxDataColumn
// For complete examples and data files, please go to https://github.com/aspose-cells/Aspose.Cells-for-Java | |
String dataDir = Utils.getDataDir(UsingMaxDataRowAndMaxDataColumn.class); | |
// Load a file in an instance of Workbook | |
Workbook book = new Workbook(dataDir + "sample.xlsx"); | |
// Get Cells collection of first worksheet | |
Cells cells = book.getWorksheets().get(0).getCells(); | |
// Loop over all cells | |
for (int row = 0; row < cells.getMaxDataRow(); row++) { | |
for (int col = 0; col < cells.getMaxDataColumn(); col++) { | |
// Read the Cell value | |
System.out.println(cells.get(row, col).getStringValue()); | |
} | |
} |
As you can observe that both of the above mentioned approaches use more or less similar logic, that is; loop over all cells in the collection to read the cell values. This could be problematic for a number of reasons as discussed below.
- The APIs such as MaxRow, MaxDataRow, MaxColumn, MaxDataColumn & MaxDisplayRange require extra time to gather the corresponding statistics. In case the data matrix (rows x columns) is large, using these APIs could impose performance penalty.
- In most of the cases, not all cells in a given range are instantiated. In such situations to check every cell in the matrix is not so efficient as compared to check only the initialized cells.
- Accessing a cell in a loop as Cells.get(rowIndex, columnIndex) will cause all cell objects in a range to be instantiated, which may eventually cause OutOfMemoryError.
Conclusion
Based on above mentioned facts, following are the possible scenarios where iterators should be used.
- Readonly access of the cell collection is required, that is; requirement is to only inspect the cells.
- Large number of cells are to be traversed.
- Only initialized cells/rows/columns are to be traversed.