如何在Java中实现以二进制数组为键、以二进制数组为值的缓存

如何在Java中实现以二进制数组为键、以二进制数组为值的缓存,java,arrays,caching,hashmap,Java,Arrays,Caching,Hashmap,我需要创建一个包含所有城市和机场的java缓存。因此,如果我查询缓存中的某个位置,比如某个城市,它应该返回该城市中的所有机场,如果我查询的位置是机场,我应该返回该机场。 此外,每个位置都必须存储为缓存中的字节数组。(因为用于查询缓存的公开接口将byte[]作为位置的参数) 其他考虑因素包括: 检索必须非常快,尽可能快 缓存仅在系统启动时加载一次。获取后不会更改 上膛了 由于它只加载了一次,如果这样可以加快检索速度的话,我们可以对它进行排序 到目前为止,我得到的是: 方法1 在byte[]数组上创

我需要创建一个包含所有城市和机场的java缓存。因此,如果我查询缓存中的某个位置,比如某个城市,它应该返回该城市中的所有机场,如果我查询的位置是机场,我应该返回该机场。 此外,每个位置都必须存储为缓存中的字节数组。(因为用于查询缓存的公开接口将byte[]作为位置的参数) 其他考虑因素包括:

  • 检索必须非常快,尽可能快
  • 缓存仅在系统启动时加载一次。获取后不会更改 上膛了
  • 由于它只加载了一次,如果这样可以加快检索速度的话,我们可以对它进行排序
  • 到目前为止,我得到的是:

    方法1

    在byte[]数组上创建一个瘦包装器,比如ByteWrapper。将每个位置(机场和城市)作为地图中的一个键(TreeMap?)。使用字节包装器列表(包含机场,如果适用)作为值

    方法2

    创建按位置排序的多维字节[]数组。它本质上是一张地图。然后使用二进制搜索来定位键并返回结果

    你有什么建议?如果你有更好的主意,请告诉我
    谢谢

    您不需要字节数组,字符串就可以了

    将项目添加到此缓存的频率?我猜这完全是静态的,因为他们不是每天都在建造新的城市或机场

    因此,您可以使用两个多散列图,一个键入城市,另一个键入机场。签出谷歌多重地图

    如果您正在使用mySQL,那么实际上可以使用基于内存存储引擎的表


    许多数据库可以在内存中固定一个表,Oracle绝对可以,所以这是另一种方法。

    您不需要字节数组,字符串就可以了

    将项目添加到此缓存的频率?我猜这完全是静态的,因为他们不是每天都在建造新的城市或机场

    因此,您可以使用两个多散列图,一个键入城市,另一个键入机场。签出谷歌多重地图

    如果您正在使用mySQL,那么实际上可以使用基于内存存储引擎的表


    许多数据库可以将表固定在内存中,Oracle绝对可以,因此这是另一种方式。

    公开的API基于字节[]这一事实不一定决定缓存的内部细节

    第二个观察结果是,这不是一个广义的数据结构问题。所有机场的空间和所有城市的空间都是有限的,都是众所周知的。(你甚至知道尺寸)

    哈希映射、树等都是算法,可以保证某些性能特性在通用的既定范围内

    既然数据完整性不是问题(“数据不变”),而且如果空间考虑不重要(“尽可能快”),那么为什么不:

    [编辑:这部分内容在剪切和粘贴过程中不知何故被剪切掉了:如果您知道这些集合,并且它们实际上是静态的,那么您可以为您的城市和机场编制索引(编号)。]

    // these need to get initialized on startup
    // this initialization can be optimized.
    
    Map<byte[], Long> airportIndexes = new HashMap<byte[], Long>(NUMBER_OF_AIRPORTS);
    Map<byte[], Long> citiesIndexes = new HashMap<byte[], Long>(NUMBER_OF_CITIES);
    
    Map<Long, byte[]> airports = new HashMap<Long, byte[]>(NUMBER_OF_AIRPORTS);
    Map<Long, byte[]> cities = new HashMap<Long, byte[]>(NUMBER_OF_CITIES);
    
    long[][] airportToCitiesMappings = new byte[NUMBER_OF_AIRPORTS][];
    long[][] citiesToAirportMappings = new byte[NUMBER_OF_CITIES][];
    
    
    public List<byte[]> getCitiesNearAirport(byte[] airportName) {
       Long[] cityIndexes = getCitiesByIdxNearAirport(airportName);
       List<byte[]> cities = new ArrayList<byte[]>(cityIndexes.length);
       for(Long cityIdx : cityIndexes) {
           cities.add(cities.get(cityIdx));
       }
       return cities;
    }
    public long[] getCitiesByIdxNearAirport(Long airportIdx) {
       return airportToCitiesMappings[airportIdx];
    }
    public long[] getCitiesNearAirport(byte[] airportName) {
       return getCitiesNearAirport(airportIndexes.get(airportName));
    }
    public long[] getCitiesNearAirport(Long airportIdx) {
       return airportToCitiesMappings[airportIdx];
    }
    // .. repeat above pattern for airports.
    
    //这些需要在启动时初始化
    //可以优化此初始化。
    Map airportIndexes=新HashMap(机场数量);
    Map CitiesIndex=新的HashMap(城市数量);
    地图机场=新HashMap(机场数量);
    地图城市=新HashMap(城市数量);
    long[][]airportToCitiesMappings=新字节[机场数量][];
    long[]citiesToAirportMappings=新字节[城市数量][];
    公共列表getCitiesNearAirport(字节[]airportName){
    Long[]CityIndex=getCitiesByIdxNearAirport(airportName);
    列表城市=新阵列列表(cityindex.length);
    用于(长城市索引:城市索引){
    cities.add(cities.get(cityIdx));
    }
    回归城市;
    }
    公共长[]getCitiesByIdxNearAirport(长机场){
    返回airportToCitiesMappings[AirportDX];
    }
    公共长[]getCitiesNearAirport(字节[]airportName){
    返回getCitiesNearAirport(airportIndexes.get(airportName));
    }
    公共长[]getCitiesNearAirport(长机场){
    返回airportToCitiesMappings[AirportDX];
    }
    // .. 对机场重复上述模式。
    

    这将为您提供O(1)时间性能特征。就空间而言,有相当多的冗余

    公开的API基于字节[]这一事实不一定决定缓存的内部细节

    第二个观察结果是,这不是一个广义的数据结构问题。所有机场的空间和所有城市的空间都是有限的,都是众所周知的。(你甚至知道尺寸)

    哈希映射、树等都是算法,可以保证某些性能特性在通用的既定范围内

    既然数据完整性不是问题(“数据不变”),而且如果空间考虑不重要(“尽可能快”),那么为什么不:

    [编辑:这部分内容在剪切和粘贴过程中不知何故被剪切掉了:如果您知道这些集合,并且它们实际上是静态的,那么您可以为您的城市和机场编制索引(编号)。]

    // these need to get initialized on startup
    // this initialization can be optimized.
    
    Map<byte[], Long> airportIndexes = new HashMap<byte[], Long>(NUMBER_OF_AIRPORTS);
    Map<byte[], Long> citiesIndexes = new HashMap<byte[], Long>(NUMBER_OF_CITIES);
    
    Map<Long, byte[]> airports = new HashMap<Long, byte[]>(NUMBER_OF_AIRPORTS);
    Map<Long, byte[]> cities = new HashMap<Long, byte[]>(NUMBER_OF_CITIES);
    
    long[][] airportToCitiesMappings = new byte[NUMBER_OF_AIRPORTS][];
    long[][] citiesToAirportMappings = new byte[NUMBER_OF_CITIES][];
    
    
    public List<byte[]> getCitiesNearAirport(byte[] airportName) {
       Long[] cityIndexes = getCitiesByIdxNearAirport(airportName);
       List<byte[]> cities = new ArrayList<byte[]>(cityIndexes.length);
       for(Long cityIdx : cityIndexes) {
           cities.add(cities.get(cityIdx));
       }
       return cities;
    }
    public long[] getCitiesByIdxNearAirport(Long airportIdx) {
       return airportToCitiesMappings[airportIdx];
    }
    public long[] getCitiesNearAirport(byte[] airportName) {
       return getCitiesNearAirport(airportIndexes.get(airportName));
    }
    public long[] getCitiesNearAirport(Long airportIdx) {
       return airportToCitiesMappings[airportIdx];
    }
    // .. repeat above pattern for airports.
    
    //这些需要在启动时初始化
    //可以优化此初始化。
    Map airportIndexes=新HashMap(机场数量);
    Map CitiesIndex=新的HashMap(城市数量);
    地图机场=新HashMap(机场数量);
    地图城市=新HashMap(城市数量);
    long[][]airportToCitiesMappings=新字节[机场数量][];
    long[]citiesToAirportMappings=新字节[城市数量][];
    公共列表getCitiesNearAirport(字节[]airportName){
    Long[]CityIndex=getCitiesByIdxNearAirport(airportName);
    列表城市=新阵列列表(cityindex.length);
    用于(长城市索引:城市索引){
    cities.add(cities.get(cityIdx));
    }
    回归城市;
    }
    公共长[]getCitiesByIdxNearAirport(长
    
    Map<byte[], List<byte[]>> m = new TreeMap<byte[], List<byte[]>>(new Comparator<byte[]>() {
        public int compare(byte[] o1, byte[] o2) {
            int result = (o1.length < o2.length ? -1 : (o1.length == o2.length ? 0 : 1));
            int index = 0;
            while (result == 0 && index < o1.length) {
                result = (o1[index] < o2[index] ? -1 : (o1[index] == o2[index] ? 0 : 1));
                index++;
            }
            return result;
        }
    });
    
    private static byte[][][] cache = null; // this is the actual cache
    // this map has ByteArrayWrapper(a wrapper over byte[]) as key which
    //  can be an airport or city and index of corresponding 
    // airport/airports in byte[][][]cache as value
    Map<ByteArrayWrapper, Integer> byteLocationIndexes = null;
    /**
    * This is how cache is queried. You can pass an airport or city as a location parameter
    * It will fetch the corresponding airport/airports
    */
    private byte[][] getAllAirportsForLocation(ByteArrayWrapper location) {
        byte[][] airports = null;
        airports = byteLocationIndexes.get(location)== null ? null : cache[byteLocationIndexes.get(location).intValue()];
        return airports;
    }