diff --git oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/sort/ExternalSort.java oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/sort/ExternalSort.java
index b9e30b5..e54d461 100644
--- oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/sort/ExternalSort.java
+++ oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/sort/ExternalSort.java
@@ -34,9 +34,13 @@ import java.util.Collections;
 import java.util.Comparator;
 import java.util.List;
 import java.util.PriorityQueue;
+import java.util.function.Function;
 import java.util.zip.Deflater;
 import java.util.zip.GZIPInputStream;
 import java.util.zip.GZIPOutputStream;
+
+import static java.util.function.Function.identity;
+
 /**
  * Source copied from a publicly available library.
  * @see <a href="https://code.google.com/p/externalsortinginjava/">https://code.google.com/p/externalsortinginjava</a>
@@ -164,7 +168,7 @@ public class ExternalSort {
      * This will simply load the file by blocks of lines, then sort them in-memory, and write the
      * result to temporary files that have to be merged later. You can specify a bound on the number
      * of temporary files that will be created.
-     * 
+     *
      * @param file
      *            some flat file
      * @param cmp
@@ -183,8 +187,44 @@ public class ExternalSort {
      * @return a list of temporary flat files
      */
     public static List<File> sortInBatch(File file, Comparator<String> cmp,
-            int maxtmpfiles, long maxMemory, Charset cs, File tmpdirectory,
-            boolean distinct, int numHeader, boolean usegzip)
+                                         int maxtmpfiles, long maxMemory, Charset cs, File tmpdirectory,
+                                         boolean distinct, int numHeader, boolean usegzip)
+            throws IOException {
+        return sortInBatch(file, cmp, maxtmpfiles, maxMemory, cs, tmpdirectory, distinct,
+                numHeader, usegzip, identity(), identity());
+    }
+
+    /**
+     * This will simply load the file by blocks of lines, then sort them in-memory, and write the
+     * result to temporary files that have to be merged later. You can specify a bound on the number
+     * of temporary files that will be created.
+     * 
+     * @param file
+     *            some flat file
+     * @param cmp
+     *            string comparator
+     * @param maxtmpfiles
+     *            maximal number of temporary files
+     * @param cs
+     *            character set to use (can use Charset.defaultCharset())
+     * @param tmpdirectory
+     *            location of the temporary files (set to null for default location)
+     * @param distinct
+     *            Pass <code>true</code> if duplicate lines should be discarded.
+     * @param numHeader
+     *            number of lines to preclude before sorting starts
+     * @param usegzip use gzip compression for the temporary files
+     * @param typeToString
+     *            function to map string to custom type. User for coverting line to custom type for the
+     *            purpose of sorting
+     * @param stringToType
+     *          function to map custom type to string. Used for storing sorted content back to file
+     * @return a list of temporary flat files
+     */
+    public static <T> List<File> sortInBatch(File file, Comparator<T> cmp,
+                                             int maxtmpfiles, long maxMemory, Charset cs, File tmpdirectory,
+                                             boolean distinct, int numHeader, boolean usegzip,
+                                             Function<T, String> typeToString, Function<String, T> stringToType)
             throws IOException {
         List<File> files = new ArrayList<File>();
         BufferedReader fbr = new BufferedReader(new InputStreamReader(
@@ -193,7 +233,7 @@ public class ExternalSort {
         long blocksize = estimateBestSizeOfBlocks(file, maxtmpfiles, maxMemory);
 
         try {
-            List<String> tmplist = new ArrayList<String>();
+            List<T> tmplist = new ArrayList<>();
             String line = "";
             try {
                 int counter = 0;
@@ -207,7 +247,7 @@ public class ExternalSort {
                             counter++;
                             continue;
                         }
-                        tmplist.add(line);
+                        tmplist.add(stringToType.apply(line));
                         // ram usage estimation, not
                         // very accurate, still more
                         // realistic that the simple 2 *
@@ -216,13 +256,13 @@ public class ExternalSort {
                                 .estimatedSizeOf(line);
                     }
                     files.add(sortAndSave(tmplist, cmp, cs,
-                            tmpdirectory, distinct, usegzip));
+                            tmpdirectory, distinct, usegzip, typeToString));
                     tmplist.clear();
                 }
             } catch (EOFException oef) {
                 if (tmplist.size() > 0) {
                     files.add(sortAndSave(tmplist, cmp, cs,
-                            tmpdirectory, distinct, usegzip));
+                            tmpdirectory, distinct, usegzip, typeToString));
                     tmplist.clear();
                 }
             }
@@ -260,7 +300,7 @@ public class ExternalSort {
 
     /**
      * Sort a list and save it to a temporary file
-     * 
+     *
      * @return the file containing the sorted data
      * @param tmplist
      *            data to be sorted
@@ -274,8 +314,31 @@ public class ExternalSort {
      *            Pass <code>true</code> if duplicate lines should be discarded.
      */
     public static File sortAndSave(List<String> tmplist,
-            Comparator<String> cmp, Charset cs, File tmpdirectory,
-            boolean distinct, boolean usegzip) throws IOException {
+                                   Comparator<String> cmp, Charset cs, File tmpdirectory,
+                                   boolean distinct, boolean usegzip) throws IOException {
+        return sortAndSave(tmplist, cmp, cs, tmpdirectory, distinct, usegzip, identity());
+    }
+
+    /**
+     * Sort a list and save it to a temporary file
+     * 
+     * @return the file containing the sorted data
+     * @param tmplist
+     *            data to be sorted
+     * @param cmp
+ *            string comparator
+     * @param cs
+*            charset to use for output (can use Charset.defaultCharset())
+     * @param tmpdirectory
+*            location of the temporary files (set to null for default location)
+     * @param distinct
+     * @param typeToString
+     *        function to map string to custom type. User for coverting line to custom type for the
+     *        purpose of sorting
+     */
+    public static <T> File sortAndSave(List<T> tmplist,
+                                   Comparator<T> cmp, Charset cs, File tmpdirectory,
+                                   boolean distinct, boolean usegzip, Function<T, String> typeToString) throws IOException {
         Collections.sort(tmplist, cmp);
         File newtmpfile = File.createTempFile("sortInBatch",
                 "flatfile", tmpdirectory);
@@ -291,12 +354,12 @@ public class ExternalSort {
         }
         BufferedWriter fbw = new BufferedWriter(new OutputStreamWriter(
                 out, cs));
-        String lastLine = null;
+        T lastLine = null;
         try {
-            for (String r : tmplist) {
+            for (T r : tmplist) {
                 // Skip duplicate lines
                 if (!distinct || (lastLine == null || (lastLine != null && cmp.compare(r, lastLine) != 0))) {
-                    fbw.write(r);
+                    fbw.write(typeToString.apply(r));
                     fbw.newLine();
                     lastLine = r;
                 }
@@ -370,7 +433,7 @@ public class ExternalSort {
 
     /**
      * This merges a bunch of temporary flat files
-     * 
+     *
      * @param files
      *            The {@link List} of sorted {@link File}s to be merged.
      * @param distinct
@@ -389,10 +452,42 @@ public class ExternalSort {
      * @return The number of lines sorted. (P. Beaudoin)
      * @since v0.1.4
      */
-    public static int mergeSortedFiles(List<File> files, File outputfile,
-            final Comparator<String> cmp, Charset cs, boolean distinct,
-            boolean append, boolean usegzip) throws IOException {
-        ArrayList<BinaryFileBuffer> bfbs = new ArrayList<BinaryFileBuffer>();
+    public static <T> int mergeSortedFiles(List<File> files, File outputfile,
+                                           final Comparator<String> cmp, Charset cs, boolean distinct,
+                                           boolean append, boolean usegzip) throws IOException {
+        return mergeSortedFiles(files, outputfile, cmp, cs, distinct, append, usegzip, Function.identity(), Function.identity());
+    }
+
+    /**
+     * This merges a bunch of temporary flat files
+     * 
+     * @param files
+     *            The {@link List} of sorted {@link File}s to be merged.
+     * @param outputfile
+     *            The output {@link File} to merge the results to.
+     * @param cmp
+     *            The {@link Comparator} to use to compare {@link String}s.
+     * @param cs
+     *            The {@link Charset} to be used for the byte to character conversion.
+     * @param distinct
+     *            Pass <code>true</code> if duplicate lines should be discarded. (elchetz@gmail.com)
+     * @param append
+     *            Pass <code>true</code> if result should append to {@link File} instead of
+     *            overwrite. Default to be false for overloading methods.
+     * @param usegzip
+     *            assumes we used gzip compression for temporary files
+     * @param typeToString
+     *            function to map string to custom type. User for coverting line to custom type for the
+     *            purpose of sorting
+     * @param stringToType
+     *          function to map custom type to string. Used for storing sorted content back to file
+     * @since v0.1.4
+     */
+    public static <T> int mergeSortedFiles(List<File> files, File outputfile,
+                                           final Comparator<T> cmp, Charset cs, boolean distinct,
+                                           boolean append, boolean usegzip, Function<T, String> typeToString,
+                                           Function<String, T> stringToType) throws IOException {
+        ArrayList<BinaryFileBuffer<T>> bfbs = new ArrayList<>();
         for (File f : files) {
             final int bufferSize = 2048;
             InputStream in = new FileInputStream(f);
@@ -405,12 +500,12 @@ public class ExternalSort {
                         cs));
             }
 
-            BinaryFileBuffer bfb = new BinaryFileBuffer(br);
+            BinaryFileBuffer<T> bfb = new BinaryFileBuffer<>(br, stringToType);
             bfbs.add(bfb);
         }
         BufferedWriter fbw = new BufferedWriter(new OutputStreamWriter(
                 new FileOutputStream(outputfile, append), cs));
-        int rowcounter = merge(fbw, cmp, distinct, bfbs);
+        int rowcounter = merge(fbw, cmp, distinct, bfbs, typeToString);
         for (File f : files) {
             f.delete();
         }
@@ -428,16 +523,19 @@ public class ExternalSort {
      *            Pass <code>true</code> if duplicate lines should be discarded. (elchetz@gmail.com)
      * @param buffers
      *            Where the data should be read.
-     * @return The number of lines sorted. (P. Beaudoin)
-     * 
+     * @param typeToString
+     *            function to map string to custom type. User for coverting line to custom type for the
+     *            purpose of sorting
+     *
      */
-    public static int merge(BufferedWriter fbw, final Comparator<String> cmp, boolean distinct,
-            List<BinaryFileBuffer> buffers) throws IOException {
-        PriorityQueue<BinaryFileBuffer> pq = new PriorityQueue<BinaryFileBuffer>(
-                11, new Comparator<BinaryFileBuffer>() {
+    public static <T> int merge(BufferedWriter fbw, final Comparator<T> cmp, boolean distinct,
+                            List<BinaryFileBuffer<T>> buffers, Function<T, String> typeToString)
+            throws IOException {
+        PriorityQueue<BinaryFileBuffer<T>> pq = new PriorityQueue<>(
+                11, new Comparator<BinaryFileBuffer<T>>() {
                     @Override
-                    public int compare(BinaryFileBuffer i,
-                            BinaryFileBuffer j) {
+                    public int compare(BinaryFileBuffer<T> i,
+                            BinaryFileBuffer<T> j) {
                         return cmp.compare(i.peek(), j.peek());
                     }
                 });
@@ -447,14 +545,14 @@ public class ExternalSort {
             }
         }
         int rowcounter = 0;
-        String lastLine = null;
+        T lastLine = null;
         try {
             while (pq.size() > 0) {
-                BinaryFileBuffer bfb = pq.poll();
-                String r = bfb.pop();
+                BinaryFileBuffer<T> bfb = pq.poll();
+                T r = bfb.pop();
                 // Skip duplicate lines
                 if (!distinct || (lastLine == null || (lastLine != null && cmp.compare(r, lastLine) != 0))) {
-                    fbw.write(r);
+                    fbw.write(typeToString.apply(r));
                     fbw.newLine();
                     lastLine = r;
                 }
@@ -630,14 +728,16 @@ public class ExternalSort {
     };
 }
 
-class BinaryFileBuffer {
-    public BufferedReader fbr;
-    private String cache;
+class BinaryFileBuffer<T> {
+    public final BufferedReader fbr;
+    private final Function<String, T> stringToType;
+    private T cache;
     private boolean empty;
 
-    public BinaryFileBuffer(BufferedReader r)
+    public BinaryFileBuffer(BufferedReader r, Function<String, T> stringToType)
             throws IOException {
         this.fbr = r;
+        this.stringToType = stringToType;
         reload();
     }
 
@@ -647,7 +747,7 @@ class BinaryFileBuffer {
 
     private void reload() throws IOException {
         try {
-            if ((this.cache = fbr.readLine()) == null) {
+            if ((this.cache = stringToType.apply(fbr.readLine())) == null) {
                 this.empty = true;
                 this.cache = null;
             } else {
@@ -663,15 +763,15 @@ class BinaryFileBuffer {
         this.fbr.close();
     }
 
-    public String peek() {
+    public T peek() {
         if (empty()) {
             return null;
         }
         return this.cache;
     }
 
-    public String pop() throws IOException {
-        String answer = peek();
+    public T pop() throws IOException {
+        T answer = peek();
         reload();
         return answer;
     }
diff --git oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/sort/ExternalSortTest.java oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/sort/ExternalSortTest.java
index c8848f9..ae71973 100644
--- oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/sort/ExternalSortTest.java
+++ oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/sort/ExternalSortTest.java
@@ -16,6 +16,7 @@
  */
 package org.apache.jackrabbit.oak.commons.sort;
 
+import static com.google.common.collect.Iterables.transform;
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
@@ -31,9 +32,17 @@ import java.nio.channels.FileChannel;
 import java.nio.charset.Charset;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.Comparator;
 import java.util.List;
 import java.util.Scanner;
+import java.util.function.Function;
+
+import com.google.common.base.Charsets;
+import com.google.common.base.Joiner;
+import com.google.common.collect.Iterables;
+import com.google.common.io.Files;
+import com.google.common.primitives.Ints;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Rule;
@@ -443,6 +452,90 @@ public class ExternalSortTest {
 
     }
 
+    @Test
+    public void customType() throws Exception{
+        File out = folder.newFile();
+        int testCount = 1000;
+
+        List<TestLine> testLines = new ArrayList<>(1000);
+        for (int i = 0; i < testCount; i++) {
+            testLines.add(new TestLine(i + ":" + "foo-"+i));
+        }
+
+        Collections.shuffle(testLines);
+
+        Comparator<TestLine> cmp = Comparator.naturalOrder();
+        Charset charset = Charsets.UTF_8;
+
+        Function<String, TestLine> stringToType = line -> line != null ? new TestLine(line) : null;
+        Function<TestLine, String> typeToString = tl -> tl != null ? tl.line : null;
+
+        String testData = Joiner.on('\n').join(transform(testLines, tl -> tl.line));
+        File testFile = folder.newFile();
+        Files.write(testData, testFile, charset);
+
+        List<File> listOfFiles = ExternalSort.sortInBatch(testFile, cmp,
+                ExternalSort.DEFAULTMAXTEMPFILES,
+                100,
+                charset,
+                folder.newFolder(),
+                false,
+                0,
+                false,
+                typeToString,
+                stringToType);
+
+        ExternalSort.mergeSortedFiles(listOfFiles, out, cmp,
+                charset, false, true, false, typeToString, stringToType);
+
+
+        Collections.sort(testLines);
+
+        List<TestLine> linesFromSortedFile = new ArrayList<>();
+        Files.readLines(out, charset).forEach(line -> linesFromSortedFile.add(new TestLine(line)));
+
+        assertEquals(testLines, linesFromSortedFile);
+
+    }
+
+    private static class TestLine implements Comparable<TestLine> {
+        final String line;
+        final int value;
+
+        public TestLine(String line) {
+            this.line = line;
+            this.value = Integer.valueOf(line.substring(0, line.indexOf(':')));
+        }
+
+        @Override
+        public int compareTo(TestLine o) {
+            return Ints.compare(value, o.value);
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+
+            TestLine testLine = (TestLine) o;
+
+            if (value != testLine.value) return false;
+            return line.equals(testLine.line);
+        }
+
+        @Override
+        public int hashCode() {
+            int result = line.hashCode();
+            result = 31 * result + value;
+            return result;
+        }
+
+        @Override
+        public String toString() {
+            return line;
+        }
+    }
+
     public static ArrayList<String> readLines(File f) throws IOException {
         ArrayList<String> answer = new ArrayList<String>();
         BufferedReader r = new BufferedReader(new FileReader(f));
