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

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改进查找性能的资料请关注我们其它相关文章!

(0)

相关推荐

  • Java HashMap两种简便排序方法解析

    这篇文章主要介绍了Java HashMap两种简便排序方法解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 HashMap的储存是没有顺序的,而是按照key的HashCode实现. key=手机品牌,value=价格,这里以这个例子实现按名称排序和按价格排序. Map phone=new HashMap(); phone.put("Apple",8899); phone.put("SAMSUNG",7000);

  • Java中HashMap里面key为null存放到哪

    我们知道HashMap集合是允许存放null值的 hashMap是根据key的hashCode来寻找存放位置的,那当key为null时, 怎么存储呢? 在put方法里头,其实第一行就处理了key=null的情况. // HashMap的put方法 public V put(K key, V value) { if (table == EMPTY_TABLE) { inflateTable(threshold); } if (key == null) // key为null调用putForNull

  • Java 对HashMap进行排序的三种常见方法

    首先来看看Map集合获取元素的三种常见方法keySet().values().entrySet() 1. values(): 返回map集合的所有value的Collection集合(于集合中无序存放) import java.util.*; public class Main{ public static void main(String[] args){ Map<String, String> map = new HashMap<String, String>(); //构建键

  • 关于Java HashMap自动排序的简单剖析

    1.HashMap概述 HashMap是无序的,这里无序的意思是你取出数据的顺序与你存入数据的顺序不同 2.发现问题 当尝试向HashMap中存入int类型的key,可以看到在输出的时候会自动排序 HashMap<Integer, String> map = new HashMap<>(); map.put(3, "asdf"); map.put(2, "asdf"); map.put(1, "asdf"); map.pu

  • Java实现简易HashMap功能详解

    本文实例讲述了Java实现简易HashMap功能.分享给大家供大家参考,具体如下: 创建节点类 节点类含有的属性:键值对(value,key)以及指向下一节点的next: 这些属性的get以及set方法 代码如下: /** * 节点类 * @author HP * */ public class Node { private Object value; private Object key; private Node next; /** * 空节点 */ public Node() { } /*

  • Java5种遍历HashMap数据的写法

    本文介绍了最好的Java5种遍历HashMap数据的写法,分享给大家,也给自己留一个笔记,具体如下: 通过EntrySet的迭代器遍历 Iterator < Entry < Integer, String >> iterator = coursesMap.entrySet().iterator(); while (iterator.hasNext()) { Entry < Integer, String > entry = iterator.next(); System

  • Java手写简易版HashMap的使用(存储+查找)

    HashMap的基本结构 package com.liuyuhe; public class Node { int hash; Object key; Object value; Node next; } package com.liuyuhe; public class MyHashMap { Node[] table; //位桶数组 int size; //存放键值对的个数 public MyHashMap() { table=new Node[16]; } } put()方法存储键值对 p

  • Java HashSet(散列集),HashMap(散列映射)的简单介绍

    简介 本篇将简单讲解Java集合框架中的HashSet与HashMap. 散列集(HashSet) 快速入门 底层原理:动态数组加单向链表或红黑树.JDK 1.8之后,当链表长度超过阈值8时,链表将转换为红黑树. 查阅HashSet的源码,可以看到HashSet的底层是HashMap,HashSet相当于只用了HashMap键Key的部分,当需要进行添加元素操作时,其值Value始终为常量PRESENT = new Object().以下为HashSet的代码片段: private transi

  • java中hashmap容量的初始化实现

    HashMap使用HashMap(int initialCapacity)对集合进行初始化. 在默认的情况下,HashMap的容量是16.但是如果用户通过构造函数指定了一个数字作为容量,那么Hash会选择大于该数字的第一个2的幂作为容量.比如如果指定了3,则容量是4:如果指定了7,则容量是8:如果指定了9,则容量是16. 为什么要设置HashMap的初始化容量 在<阿里巴巴Java开发手册>中,有一条开发建议是建议我们设置HashMap的初始化容量. 下面我们通过具体的代码来了解下为什么会这么

  • java中JSONObject转换为HashMap(方法+main方法调用实例)

    1.首先要导入json相关的jar包 引入的jar包: (版本自行定义,可以选用使用人数偏多的版本,这样比较稳定) commons-beanutils-1.9.2.jar commons-collections-3.2.1.jar commons-lang-2.6.jar commons-logging-1.2.jar ezmorph-1.0.6.jar json-lib-2.4-jdk15.jar jar包的下载可以去下面这个网址搜索: https://mvnrepository.com/ 2

随机推荐