]> source.dussan.org Git - poi.git/commitdiff
Apply patch from bug #51460 (with some related generics tweaks) - Improve HSSF perfor...
authorNick Burch <nick@apache.org>
Fri, 1 Jul 2011 16:16:55 +0000 (16:16 +0000)
committerNick Burch <nick@apache.org>
Fri, 1 Jul 2011 16:16:55 +0000 (16:16 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1141970 13f79535-47bb-0310-9956-ffa450edef68

src/documentation/content/xdocs/status.xml
src/java/org/apache/poi/hssf/model/InternalSheet.java
src/java/org/apache/poi/hssf/model/RecordStream.java
src/java/org/apache/poi/hssf/record/aggregates/RowRecordsAggregate.java
src/java/org/apache/poi/hssf/record/aggregates/ValueRecordsAggregate.java
src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java

index 69572844b4bf2d3727ad6a1932b3198bde0e7211..293ba59dc91c991e29c089473d34f9f85c8a9d7d 100644 (file)
@@ -34,7 +34,8 @@
 
     <changes>
         <release version="3.8-beta4" date="2011-??-??">
-           <action dev="poi-developers" type="add">51444 - Prevent corrupted output when saving files created by LibreOffice 3.3 </action>
+           <action dev="poi-developers" type="add">51460 - Improve HSSF performance when loading very long rows, by switching the CellValue array to an iterator</action>
+           <action dev="poi-developers" type="fix">51444 - Prevent corrupted output when saving files created by LibreOffice 3.3 </action>
            <action dev="poi-developers" type="add">51422 - Support using RecalcIdRecord to trigger a full formula recalculation on load  </action>
            <action dev="poi-developers" type="add">50474 - Example demonstrating how to update Excel workbook embedded in a WordprocessingML document </action>
            <action dev="poi-developers" type="fix">51431 - Avoid IndexOutOfBoundException when removing freeze panes in XSSF </action>
index d115480815c06439f34c94106e76f7b074cc09c9..0ad87845d2d618067f2259633ca054e12c12ab63 100644 (file)
@@ -360,13 +360,13 @@ public final class InternalSheet {
 
     private static final class RecordCloner implements RecordVisitor {
 
-        private final List<RecordBase> _destList;
+        private final List<Record> _destList;
 
-        public RecordCloner(List<RecordBase> destList) {
+        public RecordCloner(List<Record> destList) {
             _destList = destList;
         }
         public void visitRecord(Record r) {
-            _destList.add((RecordBase)r.clone());
+            _destList.add((Record)r.clone());
         }
     }
 
@@ -378,7 +378,7 @@ public final class InternalSheet {
      * belongs to a sheet.
      */
     public InternalSheet cloneSheet() {
-        List<RecordBase> clonedRecords = new ArrayList<RecordBase>(_records.size());
+        List<Record> clonedRecords = new ArrayList<Record>(_records.size());
         for (int i = 0; i < _records.size(); i++) {
             RecordBase rb = _records.get(i);
             if (rb instanceof RecordAggregate) {
@@ -723,10 +723,27 @@ public final class InternalSheet {
     public void removeRow(RowRecord row) {
         _rowsAggregate.removeRow(row);
     }
+    
+    /**
+     * Get all the value records (from LOC). Records will be returned from the first
+     *  record (starting at LOC) which is a value record.
+     *
+     * <P>
+     * This method is "loc" sensitive.  Meaning you need to set LOC to where you
+     * want it to start searching.  If you don't know do this: setLoc(getDimsLoc).
+     * When adding several rows you can just start at the last one by leaving loc
+     * at what this sets it to.  For this method, set loc to dimsloc to start with,
+     * subsequent calls will return values in (physical) sequence or NULL when you get to the end.
+     *
+     * @return Iterator of CellValueRecordInterface representing the value records
+     */
+    public Iterator<CellValueRecordInterface> getCellValueIterator(){
+       return _rowsAggregate.getCellValueIterator();
+    }
 
     /**
-     * get the NEXT value record (from LOC).  The first record that is a value record
-     * (starting at LOC) will be returned.
+     * Get all the value records (from LOC). Records will be returned from the first
+     *  record (starting at LOC) which is a value record.
      *
      * <P>
      * This method is "loc" sensitive.  Meaning you need to set LOC to where you
@@ -735,8 +752,10 @@ public final class InternalSheet {
      * at what this sets it to.  For this method, set loc to dimsloc to start with,
      * subsequent calls will return values in (physical) sequence or NULL when you get to the end.
      *
-     * @return CellValueRecordInterface representing the next value record or NULL if there are no more
+     * @return Array of CellValueRecordInterface representing the remaining value records
+     * @deprecated use {@link #getValueIterator()} instead
      */
+    @Deprecated
     public CellValueRecordInterface[] getValueRecords() {
         return _rowsAggregate.getValueRecords();
     }
index 8869a9cf03cbe38469263a65373b5cf10e946e42..3fbf96764ced6d328129b317044613787787e809 100644 (file)
@@ -27,7 +27,7 @@ import org.apache.poi.hssf.record.Record;
  */
 public final class RecordStream {
 
-       private final List _list;
+       private final List<Record> _list;
        private int _nextIndex;
        private int _countRead;
        private final int _endIx;
@@ -35,14 +35,14 @@ public final class RecordStream {
        /**
         * Creates a RecordStream bounded by startIndex and endIndex
         */
-       public RecordStream(List inputList, int startIndex, int endIx) {
+       public RecordStream(List<Record> inputList, int startIndex, int endIx) {
                _list = inputList;
                _nextIndex = startIndex;
                _endIx = endIx;
                _countRead = 0;
        }
 
-       public RecordStream(List records, int startIx) {
+       public RecordStream(List<Record> records, int startIx) {
                this(records, startIx, records.size());
        }
 
@@ -61,7 +61,7 @@ public final class RecordStream {
        /**
         * @return the {@link Class} of the next Record. <code>null</code> if this stream is exhausted.
         */
-       public Class peekNextClass() {
+       public Class<? extends Record> peekNextClass() {
                if(!hasNext()) {
                        return null;
                }
index 50092cc9ae721bdbfcd762f8cddde9407e0fe844..e4e92cf70958ca3856a402785ac754d3d06120b2 100644 (file)
@@ -447,7 +447,17 @@ public final class RowRecordsAggregate extends RecordAggregate {
 
                return startHidden;
        }
+       
+       /**
+        * Returns an iterator for the cell values
+        */
+       public Iterator<CellValueRecordInterface> getCellValueIterator() {
+               return _valuesAgg.iterator();
+       }
 
+       /**
+        * @deprecated use {@link #getCellValueIterator()} instead
+        */
        public CellValueRecordInterface[] getValueRecords() {
                return _valuesAgg.getValueRecords();
        }
index 04d1ec0c389501ca62613bd95ad3d56305dcf989..70ad5227fd9da43ad39ee5e7d68e5860319b9528 100644 (file)
@@ -18,6 +18,7 @@
 package org.apache.poi.hssf.record.aggregates;
 
 import java.util.ArrayList;
+import java.util.Iterator;
 import java.util.List;
 
 import org.apache.poi.hssf.model.RecordStream;
@@ -40,7 +41,7 @@ import org.apache.poi.ss.formula.ptg.Ptg;
  * @author  Glen Stampoultzis (glens at apache.org)
  * @author Jason Height (jheight at chariot dot net dot au)
  */
-public final class ValueRecordsAggregate {
+public final class ValueRecordsAggregate implements Iterable<CellValueRecordInterface> {
        private static final int MAX_ROW_INDEX = 0XFFFF;
        private static final int INDEX_NOT_SET = -1;
        private int firstcell = INDEX_NOT_SET;
@@ -301,10 +302,67 @@ public final class ValueRecordsAggregate {
                }
        }
 
+       /**
+        * iterator for CellValueRecordInterface
+        */
+       class ValueIterator implements Iterator<CellValueRecordInterface> {
+
+               int curRowIndex = 0, curColIndex = -1;
+               int nextRowIndex = 0, nextColIndex = -1;
+
+               public ValueIterator() {
+                       getNextPos();
+               }
+
+               void getNextPos() {
+                       if (nextRowIndex >= records.length)
+                               return; // no next already
+
+                       while (nextRowIndex < records.length) {
+                               ++nextColIndex;
+                               if (records[nextRowIndex] == null || nextColIndex >= records[nextRowIndex].length) {
+                                       ++nextRowIndex;
+                                       nextColIndex = -1;
+                                       continue;
+                               }
+
+                               if (records[nextRowIndex][nextColIndex] != null)
+                                       return; // next cell found
+                       }
+                       // no next found
+               }
+
+               public boolean hasNext() {
+                       return nextRowIndex < records.length;
+               }
+
+               public CellValueRecordInterface next() {
+                       if (!hasNext())
+                               throw new IndexOutOfBoundsException("iterator has no next");
+
+                       curRowIndex = nextRowIndex;
+                       curColIndex = nextColIndex;
+                       final CellValueRecordInterface ret = records[curRowIndex][curColIndex];
+                       getNextPos();
+                       return ret;
+               }
+
+               public void remove() {
+                       records[curRowIndex][curColIndex] = null;
+               }
+       }
+
+       /** value iterator */
+       public Iterator<CellValueRecordInterface> iterator() {
+               return new ValueIterator();
+       }
+
        /**
         * Gets all the cell records contained in this aggregate. 
         * Note {@link BlankRecord}s appear separate (not in {@link MulBlankRecord}s).
+        * @deprecated use {@link #iterator()} instead
         */
+       @Deprecated
        public CellValueRecordInterface[] getValueRecords() {
                List<CellValueRecordInterface> temp = new ArrayList<CellValueRecordInterface>();
 
index 77eada34955de9bbd8025de1aa31926a07ee400b..03d33749328e35833bfcf0198f6bf34cd7261cd3 100644 (file)
@@ -142,7 +142,7 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet {
             row = sheet.getNextRow();
         }
 
-        CellValueRecordInterface[] cvals = sheet.getValueRecords();
+        Iterator<CellValueRecordInterface> iter = sheet.getCellValueIterator();
         long timestart = System.currentTimeMillis();
 
         if (log.check( POILogger.DEBUG ))
@@ -151,8 +151,8 @@ public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet {
         HSSFRow lastrow = null;
 
         // Add every cell to its row
-        for (int i = 0; i < cvals.length; i++) {
-            CellValueRecordInterface cval = cvals[i];
+        while (iter.hasNext()) {
+            CellValueRecordInterface cval = iter.next();
 
             long cellstart = System.currentTimeMillis();
             HSSFRow hrow = lastrow;