关键词搜索

源码搜索 ×
×

Java中使用HashMap改进查找性能

发布2021-02-07浏览895次

详情内容

Java中,HashMap,其实就是键值对。一个Key,对应一个值;写数据时,指定Key写对应值;读取时凭Key找到相应值。感觉就跟Redis差不多。

// 创建 HashMap 对象 Sites
HashMap<Integer, String> Sites = new HashMap<Integer, String>();
// 添加键值对
Sites.put(1, "Google");
Sites.put(2, "Runoob");
Sites.put(3, "Taobao");
Sites.put(4, "Zhihu");
//读取
String val = Sites.get(1);//得到Google
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

为什么说可以用HashMap来改进性能呢?原因不是说HashMap这种数据结构存储性能就比其他的,比如数组,集合先进多少。我主要看中的,是在知道Key的情况下,找到相应值得速度非常快。如果是用数组,最简单的,用循环;讲究一点,排好序,用折半查找(二分查找)。都比不上用Key在HashMap里直接读取。不知道为什么HashMap在查找方面为啥这么快,估计是存储结构,使用了啥树,并为Key建立了索引。这是另外一个课题,以后再了解。昨天,我只是利用了这个特性,将运行几个小时都没结束的问题,只耗费了十几秒。

问题如下:
有25万条记录,每条记录含经纬度;存在不同记录坐标相同情况。现在想将坐标相同的记录归并在一起。

如果数据是保存在数据库里,那么用SQL进行坐标分组,应该能解决问题。然而并没有数据库,数据是从gdb文件里读出来的。

好吧,将数据保存到数组里,再新建一个集合;然后循环数组,与新集合中的记录逐个比较,坐标相同就归并到新集合,不同就插入新集合。最简单了。结果2个小时过去了,还没有结束的迹象。

想想也对,新集合越来越大,比较的次数也越来越多,仿佛棋盘里的大米一样,每格的大米数量是前一格的两倍;最后即使是整个国家粮库的大米都放进去,都填不满整个棋盘。

将25万条记录先排好序再处理?单是排序就忙死了,不行吧。

将25万条记录先保存到数据库里,再分组?应该也可以,但总觉得笨了一些,而且速度应该也是以分钟算的。

最后决定用HashMap来做这个新集合。
如上所述,HashMap按照Key来写入或读取值。关键是这个Key怎么得来。上面的例子,是写代码的人自己给出了一些字符作为Key。而在我们项目中,可以用经纬度之和的哈希值来作为Key。哈希值相同的,就认为是经纬度相同,只需要判断新集合中,是否存在这个Key对应的元素就可以了,根本无须循环比较。

由于存在两个不同的经纬度加起来,结果是一样的可能性,因此先将经度 乘以1000,再加纬度,这样基本杜绝冲突的机会。

代码如下:

private HashMap<Long,SimpleItem> recGeo(HashMap<Long, SimpleItem> map,String geo,int j){
    /*
        将相同坐标的记录合成一条
        HashMap<Long, SimpleItem> map, 新集合
        String geo, 坐标字符串
        int j 记录ID
     */

    try {
        Point p = (Point)reader.read(geo);
        /*
            计算哈希值
            因为如果采用循环来比较,数据量太大,速度太慢了
            为避免不同坐标出现经度+纬度结果相同的情况,将经度 * 1000再相加
         */
        //计算Key
        long k = Long.valueOf(Double.doubleToLongBits(p.getX() * 1000 + p.getY())).hashCode();
        
        SimpleItem si = map.get(k);
        if(si != null){//新集合中该Key对应元素已存在,应该是相同坐标的记录
            si.getPointers().add(j);//归并
        } else {//否则插入
            si = new SimpleItem();
            si.setGeo(geo);
            List<Integer> pointers = new ArrayList();
            pointers.add(j);
            si.setPointers(pointers);
            map.put(k,si);
        }
    } catch (ParseException e) {
        e.printStackTrace();
    }

    return map;
}

private static GeometryFactory geometryFactory = JTSFactoryFinder.getGeometryFactory( null );
private static WKTReader reader = new WKTReader( geometryFactory );
class SimpleItem{
    private Point geo;
    private List<Integer> pointers;

    public Point getGeo() {
        return geo;
    }

    public void setGeo(String geo) {
        try {
            this.geo = (Point)reader.read(geo);
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }

    public List<Integer> getPointers() {
        return pointers;
    }

    public void setPointers(List<Integer> pointers) {
        this.pointers = pointers;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62

短短几秒,新集合即得到5万个元素。

相关技术文章

点击QQ咨询
开通会员
返回顶部
×
微信扫码支付
微信扫码支付
确定支付下载
请使用微信描二维码支付
×

提示信息

×

选择支付方式

  • 微信支付
  • 支付宝付款
确定支付下载