Java中使用HashMap改进查找性能的步骤

 更新时间:2021年02月07日 15:01:56   作者:左直拳  
这篇文章主要介绍了Java中使用HashMap改进查找性能的步骤,帮助大家更好的理解和使用Java,感兴趣的朋友可以了解下

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

为什么说可以用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;
  }
}

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

以上就是Java中使用HashMap改进查找性能的步骤的详细内容,更多关于Java HashMap改进查找性能的资料请关注脚本之家其它相关文章!

相关文章

  • SpringBoot使用Prometheus采集自定义指标数据的方法详解

    SpringBoot使用Prometheus采集自定义指标数据的方法详解

    随着微服务在生产环境大规模部署和应用,随之而来也带来了新的问题,其中比较关键的就是关于微服务的运维和监控,本文将结合微服务运维监控中的指标监控进行详细的说明,需要的朋友可以参考下
    2024-07-07
  • 基于SpringBoot应用监控Actuator安全隐患及解决方式

    基于SpringBoot应用监控Actuator安全隐患及解决方式

    这篇文章主要介绍了SpringBoot应用监控Actuator安全隐患及解决方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-07-07
  • 如何在Netty中注解使用Service或者Mapper

    如何在Netty中注解使用Service或者Mapper

    这篇文章主要介绍了如何在Netty中注解使用Service或者Mapper,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-02-02
  • 详解Java多线程编程中LockSupport类的线程阻塞用法

    详解Java多线程编程中LockSupport类的线程阻塞用法

    LockSupport类提供了park()和unpark()两个方法来实现线程的阻塞和唤醒,下面我们就来详解Java多线程编程中LockSupport类的线程阻塞用法:
    2016-07-07
  • Java 汉字获取拼音或首字母工具类代码分析

    Java 汉字获取拼音或首字母工具类代码分析

    在本篇内容里小编给大家分享的是一篇关于Java 汉字获取拼音或首字母工具类知识点内容,有需要的朋友们可以学习参考下。
    2021-06-06
  • JDBC用法小结

    JDBC用法小结

    这篇文章主要介绍了JDBC用法,较为详细的分析了基于JDBC进行数据库操作的技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2014-12-12
  • Java基础:彻底搞懂java多线程

    Java基础:彻底搞懂java多线程

    篇文章主要介绍了Java多线程的相关资料,帮助大家更好的理解和学习Java线程相关知识,感兴趣的朋友可以了解下,希望能给你带来帮助
    2021-08-08
  • 使用ObjectMapper解析json不用一直new了

    使用ObjectMapper解析json不用一直new了

    这篇文章主要为大家介绍了使用ObjectMapper解析json不用一直new了的方法详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-06-06
  • springboot使用线程池(ThreadPoolTaskExecutor)示例

    springboot使用线程池(ThreadPoolTaskExecutor)示例

    大家好,本篇文章主要讲的是springboot使用线程池(ThreadPoolTaskExecutor)示例,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下,方便下次浏览
    2021-12-12
  • Java导出Execl疑难点处理的实现

    Java导出Execl疑难点处理的实现

    这篇文章主要介绍了Java导出Execl疑难点处理的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-04-04

最新评论