Index: src/uk/me/parabola/splitter/SplitIntList.java
===================================================================
--- src/uk/me/parabola/splitter/SplitIntList.java	Sun Jul 19 23:51:09 BST 2009
+++ src/uk/me/parabola/splitter/SplitIntList.java	Sun Jul 19 23:51:09 BST 2009
@@ -0,0 +1,90 @@
+/**
+ * Chris Miller
+ */
+package uk.me.parabola.splitter;
+
+/**
+ * Maintains a list of int primitives. Internally the ints are held
+ * in multiple arrays so we can grow without having to copy one huge
+ * array and momentarily require 2x the amount of memory.
+ */
+public class SplitIntList {
+	private static final int DEFAULT_SEGMENT_SIZE = 100000;
+
+	private final int segmentSize;
+	private int[][] segments = new int[0][];
+	private int size;
+
+	public SplitIntList() {
+		segmentSize = DEFAULT_SEGMENT_SIZE;
+	}
+
+	public SplitIntList(int segmentSize) {
+		this.segmentSize = segmentSize;
+	}
+
+	public void add(int value) {
+		ensureCapacity();
+		segments[segments.length - 1][size++ % segmentSize] = value;
+	}
+
+	public int get(int i) {
+		return segments[i / segmentSize][i % segmentSize];
+	}
+
+	public int size() {
+		return size;
+	}
+
+	private void ensureCapacity() {
+		if (size % segmentSize == 0) {
+			int[][] temp = segments;
+			segments = new int[temp.length + 1][];
+			System.arraycopy(temp, 0, segments, 0, temp.length);
+			segments[temp.length] = new int[segmentSize];
+		}
+	}
+
+	public Iterator getIterator() {
+		return new Iterator();
+	}
+
+	/**
+	 * @return an iterator that deletes segments as it is finished with
+	 * them. This is useful when copying the contents into other lists
+	 * since it means we can free up some memory as we go rather than
+	 * holding it all until the copy has finished.
+	 */
+	public Iterator getDeletingIterator() {
+		return new Iterator(true);
+	}
+
+	/**
+	 * Iterates over all the segments.
+	 */
+	public class Iterator {
+		private final boolean deleteAfter;
+		private int currentIndex;
+
+		private Iterator(boolean deleteAfter) {
+			this.deleteAfter = deleteAfter;
+		}
+
+		private Iterator() {
+			this(false);
+		}
+
+		public boolean hasNext() {
+			return currentIndex < size;
+		}
+
+		public int next() {
+			int result = SplitIntList.this.get(currentIndex++);
+			if (deleteAfter && currentIndex % segmentSize == 0) {
+				// throw away the previous segment
+				segments[(currentIndex - 1) / segmentSize] = null;
+			}
+			return result;
+		}
+	}
+}
Index: src/uk/me/parabola/splitter/DivisionParser.java
===================================================================
--- src/uk/me/parabola/splitter/DivisionParser.java	(revision 29)
+++ src/uk/me/parabola/splitter/DivisionParser.java	Sun Jul 19 23:45:13 BST 2009
@@ -35,7 +35,7 @@
 
 	private static final int MODE_NODE = 1;
 
-	private SplitIntMap coords = new SplitIntMap();
+	private SplitIntList coords = new SplitIntList();
 	private final MapDetails details = new MapDetails();
 
 	// Mixed nodes and ways in the file.
@@ -68,7 +68,6 @@
 			if (qName.equals("node")) {
 				mode = MODE_NODE;
 
-				String id = attributes.getValue("id");
 				String slat = attributes.getValue("lat");
 				String slon = attributes.getValue("lon");
 
@@ -83,7 +82,7 @@
 				int glon = co.getLongitude();
 				int coord = ((glat << 8) & 0xffff0000) + ((glon >> 8) & 0xffff);
 
-				coords.put(Integer.parseInt(id), coord);
+				coords.add(coord);
 
 				details.addToBounds(co);
 
Index: src/uk/me/parabola/splitter/SubArea.java
===================================================================
--- src/uk/me/parabola/splitter/SubArea.java	(revision 29)
+++ src/uk/me/parabola/splitter/SubArea.java	Sun Jul 19 22:45:08 BST 2009
@@ -42,17 +42,17 @@
 	private Area extendedBounds;
 	private BufferedWriter writer;
 
-	private SplitIntMap coords;
+	private SplitIntList coords;
 	private int size;
 
-	public SubArea(Area bounds, SplitIntMap coords) {
+	public SubArea(Area bounds, SplitIntList coords) {
 		this.bounds = bounds;
 		this.coords = coords;
 	}
 
 	public SubArea(Area area) {
 		this.bounds = area;
-		coords = new SplitIntMap();
+		coords = new SplitIntList();
 	}
 
 	public void clear() {
@@ -65,7 +65,7 @@
 		return bounds;
 	}
 
-	public SplitIntMap getCoords() {
+	public SplitIntList getCoords() {
 		return coords;
 	}
 
@@ -73,8 +73,8 @@
 		return mapid;
 	}
 
-	public void put(int key, int co) {
-		coords.put(key, co);
+	public void add(int co) {
+		coords.add(co);
 	}
 
 	public int getSize() {
Index: test/uk.me.parabola.splitter/TestIntList.java
===================================================================
--- test/uk.me.parabola.splitter/TestIntList.java	Sun Jul 19 22:45:08 BST 2009
+++ test/uk.me.parabola.splitter/TestIntList.java	Sun Jul 19 22:45:08 BST 2009
@@ -0,0 +1,38 @@
+/**
+ * Copyright © 2008 Chris Miller
+ */
+package uk.me.parabola.splitter;
+
+import org.testng.annotations.Test;
+import org.testng.Assert;
+
+/**
+ * 
+ */
+public class TestIntList {
+	@Test
+	public void testIntList() {
+		SplitIntList list = new SplitIntList(10);
+		for (int i = 0; i < 100; i++) {
+			list.add(i);
+		}
+
+		Assert.assertEquals(list.size(), 100);
+
+		for (int i = 0; i < 100; i++) {
+			Assert.assertEquals(list.get(i), i);
+		}
+
+		SplitIntList.Iterator it = list.getIterator();
+		int i = 0;
+		while (it.hasNext()) {
+			Assert.assertEquals(it.next(), i++);
+		}
+
+		it = list.getDeletingIterator();
+		i = 0;
+		while (it.hasNext()) {
+			Assert.assertEquals(it.next(), i++);
+		}
+	}
+}
Index: src/uk/me/parabola/splitter/AreaSplitter.java
===================================================================
--- src/uk/me/parabola/splitter/AreaSplitter.java	(revision 29)
+++ src/uk/me/parabola/splitter/AreaSplitter.java	Sun Jul 19 22:45:08 BST 2009
@@ -16,7 +16,6 @@
  */
 package uk.me.parabola.splitter;
 
-import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.ListIterator;
 
@@ -32,10 +31,10 @@
 	/**
 	 * Split a single area which would normally be the complete area of the map.
 	 * We just split areas that are too big into two.  We make a rough determination
-	 * of the largest dimention and split that way.
+	 * of the largest dimension and split that way.
 	 * 
 	 * @param area The original area.
-	 * @param max The maximimum number of nodes that any area can contain.
+	 * @param max The maximum number of nodes that any area can contain.
 	 * @return An array of areas.  Each will have less than the specified number of nodes.
 	 */
 	public AreaList split(SubArea area, int max) {
@@ -50,12 +49,12 @@
 			ListIterator<SubArea> it = l.listIterator();
 			while (it.hasNext()) {
 				SubArea workarea = it.next();
-				SplitIntMap map = workarea.getCoords();
-				if (map == null) {
+				SplitIntList list = workarea.getCoords();
+				if (list == null) {
 					continue;
 				}
 
-				int size = map.size();
+				int size = list.size();
 				System.out.println("comparing size " + workarea.getSize());
 				if (size < max) {
 					workarea.clear();
@@ -95,14 +94,14 @@
 		System.out.println("left = " + left);
 		System.out.println("right = " + right);
 
-		SplitIntMap baseCoords = base.getCoords();
+		SplitIntList baseCoords = base.getCoords();
 
-		Iterator<IntIntMap.Entry> it = baseCoords.fastIterator();
+	  SplitIntList.Iterator it = baseCoords.getIterator();
 		int count = 0;
 		long total = 0;
 		while (it.hasNext()) {
-			IntIntMap.Entry entry = it.next();
-			int lon = extractLongitude(entry.getValue());
+			int val = it.next();
+			int lon = extractLongitude(val);
 			assert lon >= left && lon <= right : lon;
 			count++;
 			total += lon - left + 1;
@@ -120,15 +119,13 @@
 		SubArea a1 = new SubArea(b1);
 		SubArea a2 = new SubArea(b2);
 
-		it = baseCoords.fastDeletingIterator();
+		it = baseCoords.getDeletingIterator();
 		while (it.hasNext()) {
-			IntIntMap.Entry entry = it.next();
-			int key = entry.getKey();
-			int co = entry.getValue();
+			int co = it.next();
 			if (extractLongitude(co) < mid) {
-				a1.put(key, co);
+				a1.add(co);
 			} else {
-				a2.put(key, co);
+				a2.add(co);
 			}
 		}
 
@@ -142,15 +139,15 @@
 		int top = bounds.getMaxLat();
 		int bot = bounds.getMinLat();
 
-		SplitIntMap caseCoords = base.getCoords();
+		SplitIntList caseCoords = base.getCoords();
 
-		Iterator<IntIntMap.Entry> it = caseCoords.fastIterator();
+		SplitIntList.Iterator it = caseCoords.getIterator();
 		int count = 0;
 		long total = 0;
 		while (it.hasNext()) {
-			IntIntMap.Entry entry = it.next();
-			int lat = extractLatitude(entry.getValue());
-			assert lat >= bot && extractLongitude(entry.getValue()) <= top : lat;
+			int val = it.next();
+			int lat = extractLatitude(val);
+			assert lat >= bot && extractLongitude(val) <= top : lat;
 			count++;
 			total += lat - bot;
 		}
@@ -167,15 +164,13 @@
 
 		caseCoords = base.getCoords();
 
-		it = caseCoords.fastDeletingIterator();
+		it = caseCoords.getDeletingIterator();
 		while (it.hasNext()) {
-			IntIntMap.Entry entry = it.next();
-			int key = entry.getKey();
-			int co = entry.getValue();
+			int co = it.next();
 			if (extractLatitude(co) <= mid) {
-				a1.put(key, co);
+				a1.add(co);
 			} else {
-				a2.put(key, co);
+				a2.add(co);
 			}
 		}
 
