public List<Region> findRegionsByKeyRange(final byte[] startKey, final byte[] endKey) {
        final StampedLock stampedLock = this.stampedLock;
        final long stamp = stampedLock.readLock();
        try {
            final byte[] realStartKey = BytesUtil.nullToEmpty(startKey);
            final NavigableMap<byte[], Long> subRegionMap;
            if (endKey == null) {
                subRegionMap = this.rangeTable.tailMap(realStartKey, false);
            } else {
                subRegionMap = this.rangeTable.subMap(realStartKey, false, endKey, true);
            }
            final List<Region> regionList = Lists.newArrayListWithCapacity(subRegionMap.size() + 1);
            final Map.Entry<byte[], Long> headEntry = this.rangeTable.floorEntry(realStartKey);
            if (headEntry == null) {
                reportFail(startKey);
                throw reject(startKey, "fail to find region by startKey");
            }
            regionList.add(safeCopy(this.regionTable.get(headEntry.getValue())));
            for (final Long regionId : subRegionMap.values()) {
                regionList.add(safeCopy(this.regionTable.get(regionId)));
            }
            return regionList;
        } finally {
            stampedLock.unlockRead(stamp);
        }
    }
@Test
    public void findRegionsByKeyRangeTest() {
        // case-1
        {
            RegionRouteTable table = new RegionRouteTable();
            Region region = makeRegion(-1, null, null);
            table.addOrUpdateRegion(region);
            List<Region> regionList = table.findRegionsByKeyRange(KeyValueTool.makeKey("a"), KeyValueTool.makeKey("w"));
            assertEquals(1, regionList.size());
        }
        // case-2
        {
            RegionRouteTable table = new RegionRouteTable();
            Region r1 = makeRegion(1, null, KeyValueTool.makeKey("c"));
            Region r2 = makeRegion(2, KeyValueTool.makeKey("c"), KeyValueTool.makeKey("e"));
            Region r3 = makeRegion(3, KeyValueTool.makeKey("e"), null);
            table.addOrUpdateRegion(r1);
            table.addOrUpdateRegion(r2);
            table.addOrUpdateRegion(r3);
            List<Region> foundList = table.findRegionsByKeyRange(KeyValueTool.makeKey("adc"),
                KeyValueTool.makeKey("def"));
            assertEquals(2, foundList.size());
            assertEquals(r1.getId(), foundList.get(0).getId());
            assertEquals(r2.getId(), foundList.get(1).getId());

            foundList = table.findRegionsByKeyRange(KeyValueTool.makeKey("c"), KeyValueTool.makeKey("def"));
            assertEquals(1, foundList.size());
            assertEquals(r2.getId(), foundList.get(0).getId());
        }
        // case-3
        {
            RegionRouteTable table = new RegionRouteTable();
            Region r1 = makeRegion(1, null, KeyValueTool.makeKey("c"));
            Region r2 = makeRegion(2, KeyValueTool.makeKey("c"), KeyValueTool.makeKey("e"));
            Region r3 = makeRegion(3, KeyValueTool.makeKey("e"), KeyValueTool.makeKey("g"));
            Region r4 = makeRegion(4, KeyValueTool.makeKey("g"), KeyValueTool.makeKey("i"));
            Region r5 = makeRegion(5, KeyValueTool.makeKey("i"), KeyValueTool.makeKey("k"));
            Region r6 = makeRegion(6, KeyValueTool.makeKey("k"), KeyValueTool.makeKey("n"));
            Region r7 = makeRegion(7, KeyValueTool.makeKey("n"), null);
            table.addOrUpdateRegion(r1);
            table.addOrUpdateRegion(r2);
            table.addOrUpdateRegion(r3);
            table.addOrUpdateRegion(r4);
            table.addOrUpdateRegion(r5);
            table.addOrUpdateRegion(r6);
            table.addOrUpdateRegion(r7);
            List<Region> foundList = table.findRegionsByKeyRange(KeyValueTool.makeKey("adc"),
                KeyValueTool.makeKey("def"));
            assertEquals(2, foundList.size());
            assertEquals(r1.getId(), foundList.get(0).getId());
            assertEquals(r2.getId(), foundList.get(1).getId());

            foundList = table.findRegionsByKeyRange(KeyValueTool.makeKey("c"), KeyValueTool.makeKey("kf"));
            assertEquals(5, foundList.size());
            assertEquals(r2.getId(), foundList.get(0).getId());
            assertEquals(r3.getId(), foundList.get(1).getId());
            assertEquals(r4.getId(), foundList.get(2).getId());
            assertEquals(r5.getId(), foundList.get(3).getId());
            assertEquals(r6.getId(), foundList.get(4).getId());

        }
    }