diff --git a/docs/source/JavaCsharpUsage.md b/docs/source/JavaCsharpUsage.md
index 3af9cfa488147472a0136f5d034b37ab215d54be..cc58f8562c252fe70e44a63b80121b39dd0fc57f 100755
--- a/docs/source/JavaCsharpUsage.md
+++ b/docs/source/JavaCsharpUsage.md
@@ -131,6 +131,36 @@ object are prefixed with `Get`, e.g.:
     monster.GetPos(preconstructedPos);
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
+## Storing dictionaries in a FlatBuffer
+
+FlatBuffers doesn't support dictionaries natively, but there is support to
+emulate their behavior with vectors and binary search, which means you
+can have fast lookups directly from a FlatBuffer without having to unpack
+your data into a `Dictionary` or similar.
+
+To use it:
+-   Designate one of the fields in a table as they "key" field. You do this
+    by setting the `key` attribute on this field, e.g.
+    `name:string (key)`.
+    You may only have one key field, and it must be of string or scalar type.
+-   Write out tables of this type as usual, collect their offsets in an
+    array.
+-   Instead of calling standard generated method,
+    e.g.: `Monster.createTestarrayoftablesVector`,
+    call `CreateMySortedVectorOfTables` in C# or
+    `createSortedVectorOfTables` (from the `FlatBufferBuilder` object) in Java,
+    which will first sort all offsets such that the tables they refer to
+    are sorted by the key field, then serialize it.
+-   Now when you're accessing the FlatBuffer, you can use `LookupByKey`
+    to access elements of the vector, e.g.:
+    `Monster.lookupByKey(tablesVectorOffset, "Frodo", dataBuffer)`,
+    which returns an object of the corresponding table type,
+    or `null` if not found.
+    `LookupByKey` performs a binary search, so should have a similar speed to
+    `Dictionary`, though may be faster because of better caching. `LookupByKey`
+    only works if the vector has been sorted, it will likely not find elements
+    if it hasn't been sorted.
+
 ## Text parsing
 
 There currently is no support for parsing text (Schema's and JSON) directly
diff --git a/java/com/google/flatbuffers/FlatBufferBuilder.java b/java/com/google/flatbuffers/FlatBufferBuilder.java
index f69fbcf96b8251db121b13f4c229f9d1eb7c06e6..fd4b729e6693efdd74fc57864cb3c357f8e11b11 100644
--- a/java/com/google/flatbuffers/FlatBufferBuilder.java
+++ b/java/com/google/flatbuffers/FlatBufferBuilder.java
@@ -389,6 +389,31 @@ public class FlatBufferBuilder {
         return copy;
     }
 
+   /**
+     * Create a vector of tables.
+     *
+     * @param offsets Offsets of the tables.
+     * @return Returns offset of the vector.
+     */
+    public int createVectorOfTables(int[] offsets) {
+        notNested();
+        startVector(Constants.SIZEOF_INT, offsets.length, Constants.SIZEOF_INT);
+        for(int i = offsets.length - 1; i >= 0; i--) addOffset(offsets[i]);
+        return endVector();
+    }
+
+    /**
+     * Create a vector of sorted by the key tables.
+     *
+     * @param obj Instance of the table subclass.
+     * @param offsets Offsets of the tables.
+     * @return Returns offset of the sorted vector.
+     */
+    public <T extends Table> int createSortedVectorOfTables(T obj, int[] offsets) {
+        obj.sortTables(offsets, bb);
+        return createVectorOfTables(offsets);
+    }
+	
    /**
     * Encode the string `s` in the buffer using UTF-8.  If {@code s} is
     * already a {@link CharBuffer}, this method is allocation free.
diff --git a/java/com/google/flatbuffers/Table.java b/java/com/google/flatbuffers/Table.java
index 4087654207ce3a689aa5057a5260367ed1907e41..c9c6545616a7ee79db4080c4f12e6e66659956ad 100644
--- a/java/com/google/flatbuffers/Table.java
+++ b/java/com/google/flatbuffers/Table.java
@@ -61,6 +61,11 @@ public class Table {
     return vtable_offset < bb.getShort(vtable) ? bb.getShort(vtable + vtable_offset) : 0;
   }
 
+  protected static int __offset(int vtable_offset, int offset, ByteBuffer bb) {
+    int vtable = bb.array().length - offset;
+    return bb.getShort(vtable + vtable_offset - bb.getInt(vtable)) + vtable;
+  }
+
   /**
    * Retrieve a relative offset.
    *
@@ -70,6 +75,10 @@ public class Table {
   protected int __indirect(int offset) {
     return offset + bb.getInt(offset);
   }
+  
+  protected static int __indirect(int offset, ByteBuffer bb) {
+    return offset + bb.getInt(offset);
+  }
 
   /**
    * Create a Java `String` from UTF-8 data stored inside the FlatBuffer.
@@ -188,6 +197,72 @@ public class Table {
     }
     return true;
   }
+  
+  /**
+   * Sort tables by the key.
+   *
+   * @param offsets An 'int' indexes of the tables into the bb.
+   * @param bb A {@code ByteBuffer} to get the tables.
+   */
+  protected void sortTables(int[] offsets, ByteBuffer bb) {
+    Integer[] off = new Integer[offsets.length];
+    for (int i = 0; i < offsets.length; i++) off[i] = offsets[i];
+    Arrays.sort(off, (Integer o1, Integer o2) -> keysCompare(o1, o2, bb));
+    for (int i = 0; i < offsets.length; i++) offsets[i] = off[i];
+  }
+
+  /**
+   * Compare two tables by the key.
+   *
+   * @param o1 An 'Integer' index of the first key into the bb.
+   * @param o2 An 'Integer' index of the second key into the bb.
+   * @param bb A {@code ByteBuffer} to get the keys.
+   */
+  protected int keysCompare(Integer o1, Integer o2, ByteBuffer bb) { return 0; }
+  
+  /**
+   * Compare two strings in the buffer.
+   *
+   * @param offset_1 An 'int' index of the first string into the bb.
+   * @param offset_2 An 'int' index of the second string into the bb.
+   * @param bb A {@code ByteBuffer} to get the strings.
+   */
+  protected static int compareStrings(int offset_1, int offset_2, ByteBuffer bb) {
+    offset_1 += bb.getInt(offset_1);
+    offset_2 += bb.getInt(offset_2);
+    int len_1 = bb.getInt(offset_1);
+    int len_2 = bb.getInt(offset_2);
+    int startPos_1 = offset_1 + SIZEOF_INT;
+    int startPos_2 = offset_2 + SIZEOF_INT;
+    int len = Math.min(len_1, len_2);
+    byte[] bbArray = bb.array();
+    for(int i = 0; i < len; i++) {
+      if (bbArray[i + startPos_1] != bbArray[i + startPos_2])
+        return bbArray[i + startPos_1] - bbArray[i + startPos_2];
+    }
+    return len_1 - len_2;
+  }
+  
+  /**
+   * Compare string from the buffer with the 'String' object.
+   *
+   * @param offset_1 An 'int' index of the first string into the bb.
+   * @param key Second string as a byte array.
+   * @param bb A {@code ByteBuffer} to get the first string.
+   */
+  protected static int compareStrings(int offset_1, byte[] key, ByteBuffer bb) {
+    offset_1 += bb.getInt(offset_1);
+    int len_1 = bb.getInt(offset_1);
+    int len_2 = key.length;
+    int startPos_1 = offset_1 + Constants.SIZEOF_INT;
+    int len = Math.min(len_1, len_2);
+    byte[] bbArray = bb.array();
+    for (int i = 0; i < len; i++) {
+      if (bbArray[i + startPos_1] != key[i])
+        return bbArray[i + startPos_1] - key[i];
+    }
+    return len_1 - len_2;
+  }
 }
 
 /// @endcond
diff --git a/net/FlatBuffers/FlatBufferBuilder.cs b/net/FlatBuffers/FlatBufferBuilder.cs
index 8c57abec16fed1b32f54607f19a21a6618e42f58..823659022c4b6ff0411009d9064593debc5213ac 100644
--- a/net/FlatBuffers/FlatBufferBuilder.cs
+++ b/net/FlatBuffers/FlatBufferBuilder.cs
@@ -295,6 +295,18 @@ namespace FlatBuffers
             PutInt(_vectorNumElems);
             return new VectorOffset(Offset);
         }
+		
+        /// <summary>
+        /// Creates a vector of tables.
+        /// </summary>
+        /// <param name="offsets">Offsets of the tables.</param>
+        public VectorOffset CreateVectorOfTables<T>(Offset<T>[] offsets) where T : class
+        {
+            NotNested();
+            StartVector(sizeof(int), offsets.Length, sizeof(int));
+            for (int i = offsets.Length - 1; i >= 0; i--) AddOffset(offsets[i].Value);
+            return EndVector();
+        }
 
         /// @cond FLATBUFFERS_INTENRAL
         public void Nested(int obj)
diff --git a/net/FlatBuffers/Table.cs b/net/FlatBuffers/Table.cs
index bd5e36419dd374612d642a4a7869943e6bfe8e18..ca52d7d027ccb9ecdf62b81dba10e24c029092fe 100644
--- a/net/FlatBuffers/Table.cs
+++ b/net/FlatBuffers/Table.cs
@@ -37,11 +37,22 @@ namespace FlatBuffers
             return vtableOffset < bb.GetShort(vtable) ? (int)bb.GetShort(vtable + vtableOffset) : 0;
         }
 
+        protected static int __offset(int vtableOffset, int offset, ByteBuffer bb)
+        {
+            int vtable = bb.Length - offset;
+            return (int)bb.GetShort(vtable + vtableOffset - bb.GetInt(vtable)) + vtable;
+        }
+
         // Retrieve the relative offset stored at "offset"
         protected int __indirect(int offset)
         {
             return offset + bb.GetInt(offset);
         }
+		
+        protected static int __indirect(int offset, ByteBuffer bb)
+        {
+            return offset + bb.GetInt(offset);
+        }
 
         // Create a .NET String from UTF-8 data stored inside the flatbuffer.
         protected string __string(int offset)
@@ -103,7 +114,40 @@ namespace FlatBuffers
 
             return true;
         }
-
+		
+        // Compare strings in the ByteBuffer.
+        protected static int CompareStrings(int offset_1, int offset_2, ByteBuffer bb)
+        {
+            offset_1 += bb.GetInt(offset_1);
+            offset_2 += bb.GetInt(offset_2);
+            var len_1 = bb.GetInt(offset_1);
+            var len_2 = bb.GetInt(offset_2);
+            var startPos_1 = offset_1 + sizeof(int);
+            var startPos_2 = offset_2 + sizeof(int);
+            var len = Math.Min(len_1, len_2);
+            byte[] bbArray = bb.Data;
+            for(int i = 0; i < len; i++) {
+                if (bbArray[i + startPos_1] != bbArray[i + startPos_2])
+                    return bbArray[i + startPos_1] - bbArray[i + startPos_2];
+            }
+            return len_1 - len_2;
+        }
+		
+        // Compare string from the ByteBuffer with the string object
+        protected static int CompareStrings(int offset_1, byte[] key, ByteBuffer bb)
+        {
+            offset_1 += bb.GetInt(offset_1);
+            var len_1 = bb.GetInt(offset_1);
+            var len_2 = key.Length;
+            var startPos_1 = offset_1 + sizeof(int);
+            var len = Math.Min(len_1, len_2);
+            byte[] bbArray = bb.Data;
+            for (int i = 0; i < len; i++) {
+                if (bbArray[i + startPos_1] != key[i])
+                    return bbArray[i + startPos_1] - key[i];
+            }
+            return len_1 - len_2;
+        }
 
     }
 }
diff --git a/src/idl_gen_general.cpp b/src/idl_gen_general.cpp
index 7e8e8c577a170d523c9a501bd854d7f850fad173..04deb9a0b8046a394e29f8bc30009c258958c660 100644
--- a/src/idl_gen_general.cpp
+++ b/src/idl_gen_general.cpp
@@ -669,6 +669,89 @@ void GenStructBody(const StructDef &struct_def, std::string *code_ptr, const cha
   }
 }
 
+std::string GenByteBufferLength(const char *bb_name) {
+  std::string bb_len = bb_name;
+  if (lang_.language == IDLOptions::kCSharp) bb_len += ".Length";
+  else bb_len += ".array().length";
+  return bb_len;
+}
+
+std::string GenOffsetGetter(flatbuffers::FieldDef *key_field, const char *num = nullptr) {
+  std::string key_offset = "";
+  key_offset += "__offset(" +
+    NumToString(key_field->value.offset) + ", ";
+  if (num) {
+    key_offset += num;
+    key_offset += (lang_.language == IDLOptions::kCSharp ?
+      ".Value, builder.DataBuffer)" : ", _bb)");
+  }
+  else {
+    key_offset += GenByteBufferLength("bb");
+    key_offset += " - tableOffset, bb)";
+  }
+  return key_offset;
+}
+
+std::string GenLookupKeyGetter(flatbuffers::FieldDef *key_field) {
+  std::string key_getter = "      ";
+  key_getter += "tableOffset = __indirect(vectorLocation + 4 * (start + middle)";
+  key_getter += ", bb);\n      ";
+  if (key_field->value.type.base_type == BASE_TYPE_STRING) {
+    key_getter += "comp = " + FunctionStart('C') + "ompareStrings(";
+    key_getter += GenOffsetGetter(key_field);
+    key_getter += ", byteKey, bb);\n";
+  }
+  else {
+    auto get_val = GenGetter(key_field->value.type) +
+      "(" + GenOffsetGetter(key_field) + ")";
+    if (lang_.language == IDLOptions::kCSharp) {
+      key_getter += "comp = " + get_val + ".CompateTo(key);\n";
+    }
+    else {
+      key_getter += GenTypeGet(key_field->value.type) + " val = ";
+      key_getter += get_val + ";\n";
+      key_getter += "      comp = val > key ? 1 : val < key ? -1 : 0;\n";
+    }
+  }
+  return key_getter;
+}
+
+
+std::string GenKeyGetter(flatbuffers::FieldDef *key_field) {
+  std::string key_getter = "";
+  auto data_buffer = (lang_.language == IDLOptions::kCSharp) ?
+    "builder.DataBuffer" : "_bb";
+  if (key_field->value.type.base_type == BASE_TYPE_STRING) {
+    if (lang_.language == IDLOptions::kJava)
+      key_getter += " return ";
+    key_getter += FunctionStart('C') + "ompareStrings(";
+    key_getter += GenOffsetGetter(key_field, "o1") + ", ";
+    key_getter += GenOffsetGetter(key_field, "o2") + ", " + data_buffer + ")";
+    if (lang_.language == IDLOptions::kJava)
+      key_getter += ";";
+  }
+  else {
+    auto field_getter = data_buffer + GenGetter(key_field->value.type).substr(2) +
+      "(" + GenOffsetGetter(key_field, "o1") + ")";
+    if (lang_.language == IDLOptions::kCSharp) {
+      key_getter += field_getter;
+      field_getter = data_buffer + GenGetter(key_field->value.type).substr(2) +
+        "(" + GenOffsetGetter(key_field, "o2") + ")";
+      key_getter += ".CompareTo(" + field_getter + ")";
+    }
+    else {
+      key_getter += "\n    " + GenTypeGet(key_field->value.type) + " val_1 = ";
+      key_getter += field_getter + ";\n    " + GenTypeGet(key_field->value.type);
+      key_getter += " val_2 = ";
+      field_getter = data_buffer + GenGetter(key_field->value.type).substr(2) +
+        "(" + GenOffsetGetter(key_field, "o2") + ")";
+      key_getter += field_getter + ";\n";
+      key_getter += "    return val_1 > val_2 ? 1 : val_1 < val_2 ? -1 : 0;\n ";
+    }
+  }
+  return key_getter;
+}
+
 void GenStruct(StructDef &struct_def, std::string *code_ptr) {
   if (struct_def.generated) return;
   std::string &code = *code_ptr;
@@ -960,6 +1043,7 @@ void GenStruct(StructDef &struct_def, std::string *code_ptr) {
     }
   }
   code += "\n";
+  flatbuffers::FieldDef *key_field = nullptr;
   if (struct_def.fixed) {
     // create a struct constructor function
     code += "  public static " + GenOffsetType(struct_def) + " ";
@@ -1048,6 +1132,7 @@ void GenStruct(StructDef &struct_def, std::string *code_ptr) {
          it != struct_def.fields.vec.end(); ++it) {
       auto &field = **it;
       if (field.deprecated) continue;
+      if (field.key) key_field = &field;
       code += "  public static void " + FunctionStart('A') + "dd";
       code += MakeCamel(field.name);
       code += "(FlatBufferBuilder builder, ";
@@ -1130,6 +1215,53 @@ void GenStruct(StructDef &struct_def, std::string *code_ptr) {
       code += "); }\n";
     }
   }
+  if (struct_def.has_key) {
+    if (lang_.language == IDLOptions::kJava) {
+      code += "\n  @Override\n  protected int keysCompare(";
+      code += "Integer o1, Integer o2, ByteBuffer _bb) {";
+      code += GenKeyGetter(key_field);
+      code += " }\n";
+    }
+    else {
+      code += "\n  public static VectorOffset ";
+      code += "CreateMySortedVectorOfTables(FlatBufferBuilder builder, ";
+      code += "Offset<" + struct_def.name + ">";
+      code += "[] offsets) {\n";
+      code += "    Array.Sort(offsets, (Offset<" + struct_def.name +
+        "> o1, Offset<" + struct_def.name + "> o2) => " + GenKeyGetter(key_field);
+      code += ");\n";
+      code += "    return builder.CreateVectorOfTables(offsets);\n  }\n";
+    }
+
+    code += "\n  public static " + struct_def.name + " " + FunctionStart('L');
+    code += "ookupByKey(" + GenVectorOffsetType();
+    code += " vectorOffset, " + GenTypeGet(key_field->value.type);
+    code += " key, ByteBuffer bb) {\n";
+    code += "    byte[] byteKey = ";
+    if (lang_.language == IDLOptions::kJava)
+      code += "key.getBytes(StandardCharsets.UTF_8);\n";
+    else
+      code += "System.Text.Encoding.UTF8.GetBytes(key);\n";
+    code += "    int vectorLocation = " + GenByteBufferLength("bb");
+    code += " - vectorOffset.Value;\n    int span = ";
+    code += "bb." + FunctionStart('G') + "etInt(vectorLocation), ";
+    code += "middle, start = 0, comp, tableOffset; \n";
+    code += "    vectorLocation += 4;\n";
+    code += "    while (span != 0) {\n";
+    code += "      int middle = span / 2;\n";
+    code += GenLookupKeyGetter(key_field);
+    code += "      if (comp > 0) span = middle;\n";
+    code += "      else if (comp < 0) {\n";
+    code += "        middle++;\n";
+    code += "        start += middle;\n";
+    code += "        span -= middle;\n";
+    code += "      }\n";
+    code += "      else return new " + struct_def.name;
+    code += "().__init(tableOffset, bb);\n";
+    code += "    }\n";
+    code += "    return null;\n";
+    code += "  }\n";
+  }
   code += "}";
   // Java does not need the closing semi-colon on class definitions.
   code += (lang_.language != IDLOptions::kJava) ? ";" : "";
diff --git a/tests/FlatBuffers.Test/FlatBuffersExampleTests.cs b/tests/FlatBuffers.Test/FlatBuffersExampleTests.cs
index 80791dd19b015e4f93d1652aac7dc141ac7a7eca..ed44665a33708995729a80d43eeaa6b4b5d9c025 100644
--- a/tests/FlatBuffers.Test/FlatBuffersExampleTests.cs
+++ b/tests/FlatBuffers.Test/FlatBuffersExampleTests.cs
@@ -39,6 +39,19 @@ namespace FlatBuffers.Test
             // better for performance.
             var fbb = new FlatBufferBuilder(1);
 
+            StringOffset[] names = { fbb.CreateString("Frodo"), fbb.CreateString("Barney"), fbb.CreateString("Wilma") };
+            Offset<Monster>[] off = new Offset<Monster>[3];
+            Monster.StartMonster(fbb);
+            Monster.AddName(fbb, names[0]);
+            off[0] = Monster.EndMonster(fbb);
+            Monster.StartMonster(fbb);
+            Monster.AddName(fbb, names[1]);
+            off[1] = Monster.EndMonster(fbb);
+            Monster.StartMonster(fbb);
+            Monster.AddName(fbb, names[2]);
+            off[2] = Monster.EndMonster(fbb);
+            var sortMons = Monster.CreateMySortedVectorOfTables(fbb, off);
+			
             // We set up the same values as monsterdata.json:
 
             var str = fbb.CreateString("MyMonster");
@@ -79,6 +92,7 @@ namespace FlatBuffers.Test
             Monster.AddTest4(fbb, test4);
             Monster.AddTestarrayofstring(fbb, testArrayOfString);
             Monster.AddTestbool(fbb, false);
+            Monster.AddTestarrayoftables(fbb, sortMons);
             var mon = Monster.EndMonster(fbb);
 
             Monster.FinishMonsterBuffer(fbb, mon);
@@ -102,6 +116,16 @@ namespace FlatBuffers.Test
             // the mana field should retain its default value
             Assert.AreEqual(monster.MutateMana((short)10), false);
             Assert.AreEqual(monster.Mana, (short)150);
+			
+            // Accessing a vector of sorted by the key tables
+            Assert.AreEqual(monster.GetTestarrayoftables(0).Name, "Barney");
+            Assert.AreEqual(monster.GetTestarrayoftables(1).Name, "Frodo");
+            Assert.AreEqual(monster.GetTestarrayoftables(2).Name, "Wilma");
+			
+            // Example of searching for a table by the key
+            Assert.IsTrue(Monster.LookupByKey(sortMons, "Frodo", fbb.DataBuffer) != null);
+            Assert.IsTrue(Monster.LookupByKey(sortMons, "Barney", fbb.DataBuffer) != null);
+            Assert.IsTrue(Monster.LookupByKey(sortMons, "Wilma", fbb.DataBuffer)!= null);
 
             // testType is an existing field and mutating it should succeed
             Assert.AreEqual(monster.TestType, Any.Monster);
diff --git a/tests/JavaTest.java b/tests/JavaTest.java
index c0d7d03fb14932ceb2a5d0ba7272cff4f2b01d08..d53e97327ae0a10bf619ab3555905a18d8903712 100755
--- a/tests/JavaTest.java
+++ b/tests/JavaTest.java
@@ -51,6 +51,19 @@ class JavaTest {
         // better for performance.
         FlatBufferBuilder fbb = new FlatBufferBuilder(1);
 
+        int[] names = {fbb.createString("Frodo"), fbb.createString("Barney"), fbb.createString("Wilma")};
+        int[] off = new int[3];
+        Monster.startMonster(fbb);
+        Monster.addName(fbb, names[0]);
+        off[0] = Monster.endMonster(fbb);
+        Monster.startMonster(fbb);
+        Monster.addName(fbb, names[1]);
+        off[1] = Monster.endMonster(fbb);
+        Monster.startMonster(fbb);
+        Monster.addName(fbb, names[2]);
+        off[2] = Monster.endMonster(fbb);
+        int sortMons = fbb.createSortedVectorOfTables(new Monster(), off);
+		
         // We set up the same values as monsterdata.json:
 
         int str = fbb.createString("MyMonster");
@@ -84,6 +97,7 @@ class JavaTest {
         Monster.addTestarrayofstring(fbb, testArrayOfString);
         Monster.addTestbool(fbb, false);
         Monster.addTesthashu32Fnv1(fbb, Integer.MAX_VALUE + 1L);
+        Monster.addTestarrayoftables(fbb, sortMons);
         int mon = Monster.endMonster(fbb);
 
         Monster.finishMonsterBuffer(fbb, mon);
@@ -121,6 +135,16 @@ class JavaTest {
         // the mana field should retain its default value
         TestEq(monster.mutateMana((short)10), false);
         TestEq(monster.mana(), (short)150);
+		
+		// Accessing a vector of sorted by the key tables
+        TestEq(monster.testarrayoftables(0).name(), "Barney");
+        TestEq(monster.testarrayoftables(1).name(), "Frodo");
+        TestEq(monster.testarrayoftables(2).name(), "Wilma");
+		
+		// Example of searching for a table by the key
+        TestEq(Monster.lookupByKey(sortMons, "Frodo", fbb.dataBuffer()).name(), "Frodo");
+        TestEq(Monster.lookupByKey(sortMons, "Barney", fbb.dataBuffer()).name(), "Barney");
+        TestEq(Monster.lookupByKey(sortMons, "Wilma", fbb.dataBuffer()).name(), "Wilma");
 
         // testType is an existing field and mutating it should succeed
         TestEq(monster.testType(), (byte)Any.Monster);
diff --git a/tests/MyGame/Example/Monster.cs b/tests/MyGame/Example/Monster.cs
index fdfd2b0a37cf47ec415f296ef6713ce2499c430b..95a303cf414fc0f39872a96ee8c412fa451998ba 100644
--- a/tests/MyGame/Example/Monster.cs
+++ b/tests/MyGame/Example/Monster.cs
@@ -129,6 +129,31 @@ public sealed class Monster : Table {
     return new Offset<Monster>(o);
   }
   public static void FinishMonsterBuffer(FlatBufferBuilder builder, Offset<Monster> offset) { builder.Finish(offset.Value, "MONS"); }
+  
+  public static VectorOffset CreateMySortedVectorOfTables(FlatBufferBuilder builder, Offset<Monster>[] offsets) {
+    Array.Sort(offsets, (Offset<Monster> o1, Offset<Monster> o2) => CompareStrings(__offset(10, o1.Value, builder.DataBuffer), __offset(10, o2.Value, builder.DataBuffer), builder.DataBuffer));
+    return builder.CreateVectorOfTables(offsets);
+  }
+
+  public static Monster LookupByKey(VectorOffset vectorOffset, string key, ByteBuffer bb) {
+    byte[] byteKey = System.Text.Encoding.UTF8.GetBytes(key);
+    int vectorLocation = bb.Length - vectorOffset.Value;
+    int span = bb.GetInt(vectorLocation), middle, start = 0, comp, tableOffset; 
+    vectorLocation += 4;
+    while (span != 0) {
+      int middle = span / 2;
+      tableOffset = __indirect(vectorLocation + 4 * (start + middle), bb);
+      comp = CompareStrings(__offset(10, bb.Length - tableOffset, bb), byteKey, bb);
+      if (comp > 0) span = middle;
+      else if (comp < 0) {
+        middle++;
+        start += middle;
+        span -= middle;
+      }
+      else return new Monster().__init(tableOffset, bb);
+    }
+    return null;
+  }
 };
 
 
diff --git a/tests/MyGame/Example/Monster.java b/tests/MyGame/Example/Monster.java
index dc27f8447c7789c8bf54b48199e50d0b4bb4383d..0633dff08a51e13e91c8154597325d518a109279 100644
--- a/tests/MyGame/Example/Monster.java
+++ b/tests/MyGame/Example/Monster.java
@@ -135,5 +135,28 @@ public final class Monster extends Table {
     return o;
   }
   public static void finishMonsterBuffer(FlatBufferBuilder builder, int offset) { builder.finish(offset, "MONS"); }
+
+  @Override
+  protected int keysCompare(Integer o1, Integer o2, ByteBuffer _bb) { return compareStrings(__offset(10, o1, _bb), __offset(10, o2, _bb), _bb); }
+
+  public static Monster lookupByKey(int vectorOffset, String key, ByteBuffer bb) {
+    byte[] byteKey = key.getBytes(StandardCharsets.UTF_8);
+    int vectorLocation = bb.array().length - vectorOffset.Value;
+    int span = bb.getInt(vectorLocation), middle, start = 0, comp, tableOffset; 
+    vectorLocation += 4;
+    while (span != 0) {
+      int middle = span / 2;
+      tableOffset = __indirect(vectorLocation + 4 * (start + middle), bb);
+      comp = compareStrings(__offset(10, bb.array().length - tableOffset, bb), byteKey, bb);
+      if (comp > 0) span = middle;
+      else if (comp < 0) {
+        middle++;
+        start += middle;
+        span -= middle;
+      }
+      else return new Monster().__init(tableOffset, bb);
+    }
+    return null;
+  }
 }