//不说废话直接上代码
public static void main(String[] args)
{
HashMap<String,String> cityMap = new HashMap<String, String>();
cityMapput("广东","广州,深圳,潮州,湛江");
cityMapput("河北", "石家庄,唐山,秦皇岛");
cityMapput("广西", "桂林,南宁,柳州");
Systemoutprintln("广东省:"+cityMapget("广东"));
Systemoutprintln("河北省:"+cityMapget("河北"));
Systemoutprintln("广西省:"+cityMapget("广西"));
}
在Java的世界里 无论类还是各种数据 其结构的处理是整个程序的逻辑以及性能的关键 由于本人接触了一个有关性能与逻辑同时并存的问题 于是就开始研究这方面的问题 找遍了大大小小的论坛 也把《Java 虚拟机规范》 《apress llections ( ) bm ocr shareconnector》 和《Thinking in Java》翻了也找不到很好的答案 于是一气之下把JDK的src 解压出来研究 扩然开朗 遂写此文 跟大家分享感受和顺便验证我理解还有没有漏洞 这里就拿HashMap来研究吧
HashMap可谓JDK的一大实用工具 把各个Object映射起来 实现了 键--值 对应的快速存取 但实际里面做了些什么呢?
在这之前 先介绍一下负载因子和容量的属性 大家都知道其实一个 HashMap 的实际容量就 因子容量 其默认值是 × = 这个很重要 对效率很一定影响!当存入HashMap的对象超过这个容量时 HashMap 就会重新构造存取表 这就是一个大问题 我后面慢慢介绍 反正 如果你已经知道你大概要存放多少个对象 最好设为该实际容量的能接受的数字
两个关键的方法 put和get
先有这样一个概念 HashMap是声明了 Map Cloneable Serializable 接口 和继承了 AbstractMap 类 里面的 Iterator 其实主要都是其内部类HashIterator 和其他几个 iterator 类实现 当然还有一个很重要的继承了Map Entry 的 Entry 内部类 由于大家都有源代码 大家有兴趣可以看看这部分 我主要想说明的是 Entry 内部类 它包含了hash value key 和next 这四个属性 很重要 put的源码如下
public Object put(Object key Object value) { Object k = maskNull(key);
这个就是判断键值是否为空 并不很深奥 其实如果为空 它会返回一个static Object 作为键值 这就是为什么HashMap允许空键值的原因
int hash = hash(k); int i = indexFor(hash table length);
这连续的两步就是 HashMap 最牛的地方!研究完我都汗颜了 其中 hash 就是通过 key 这个Object的 hashcode 进行 hash 然后通过 indexFor 获得在Object table的索引值
table?不要惊讶 其实HashMap也神不到哪里去 它就是用 table 来放的 最牛的就是用 hash 能正确的返回索引 其中的hash算法 我跟JDK的作者 Doug 联系过 他建议我看看《The art of programing vol 》可恨的是 我之前就一直在找 我都找不到 他这样一提 我就更加急了 可惜口袋空空啊!
不知道大家有没有留意 put 其实是一个有返回的方法 它会把相同键值的 put 覆盖掉并返回旧的值!如下方法彻底说明了 HashMap 的结构 其实就是一个表加上在相应位置的Entry的链表
for (Entry e = table[i]; e != null; e = e next) { if (e hash == hash && eq(k e key)) { Object oldvalue = e value; e value = value; //把新的值赋予给对应键值 e recordAccess(this); //空方法 留待实现 return oldvalue; //返回相同键值的对应的旧的值 } } modCount++; //结构性更改的次数 addEntry(hash k value i); //添加新元素 关键所在! return null; //没有相同的键值返回 }
我们把关键的方法拿出来分析void addEntry(int hash Object key Object value int bucketIndex) { table[bucketIndex] = new Entry(hash key value table[bucketIndex]);
因为 hash 的算法有可能令不同的键值有相同的hash码并有相同的table索引 如 key= 和key=Object g的hash都是- 那它经过indexfor之后的索引一定都为i 这样在new的时候这个Entry的next就会指向这个原本的table[i] 再有下一个也如此 形成一个链表 和put的循环对定e next获得旧的值 到这里 HashMap的结构 大家也十分明白了吧?if (size++ >= threshold) //这个threshold就是能实际容纳的量 resize( table length); //超出这个容量就会将Object table重构
所谓的重构也不神 就是建一个两倍大的table(我在别的论坛上看到有人说是两倍加 把我骗了) 然后再一个个indexfor进去!注意!!这就是效率!!如果你能让你的HashMap不需要重构那么多次 效率会大大提高!
说到这里也差不多了 get比put简单得多 大家 了解put get也差不了多少了 对于collections我是认为 它是适合广泛的 当不完全适合特有的 如果大家的程序需要特殊的用途 自己写吧 其实很简单 (作者是这样跟我说的 他还建议我用LinkedHashMap 我看了源码以后发现 LinkHashMap其实就是继承HashMap的 然后override相应的方法 有兴趣的同人 自己looklook)建个 Object table 写相应的算法 就ok啦
举个例子吧 像 Vector list 啊什么的其实都很简单 最多就多了的同步的声明 其实如果要实现像Vector那种 插入 删除不多的 可以用一个Object table来实现 按索引存取 添加等
lishixinzhi/Article/program/Java/hx/201311/27015
public static void main(String[] args) {
Map<String, String> map = new HashMap<String, String>();
mapput("key1", "value1");
mapput("key2", "value2");
mapput("key3", "value3");
Set<String> keySet = mapkeySet();
int i = mapsize()-1;
Map<Integer, String> mapKey = new HashMap<Integer, String>();
Map<Integer, String> mapValue = new HashMap<Integer, String>();
for(javautilMapEntry<String, String> entry : mapentrySet()) {
//将原来MAP的VALUE放入新的MAP的VALUE里面
mapKeyput(i, entrygetValue());
//将原来MAP的KEY放入新的MAP的VALUE 里面
mapValueput(i, entrygetKey());
i--;
}
//打印KEY值
Systemoutprintln(mapKeyget(2));
//打印VALUE值
Systemoutprintln(mapValueget(0));
}
扩展资料:
java键值对的使用
Map集合没有继承Collection接口,但是其提供了key到value的映射。每一个key不能有相同,每个key只能映射一个value值。
下面通过一个程序来说明键值对的使用,下面是一个基本的键值对应用程序:
package Test;
import javautilCollection;
import javautilHashMap;
import javautilIterator;
import javautilMap;
import javautilSet;
public class KeyValue {
public static void main(String[] args) {
Map <String,String> map=new HashMap<>();
mapput("01", "张三");
mapput("02", "王五");
Set<String> set=mapkeySet();
Iterator <String> it=setiterator();
Systemoutprintln("key中集合元素:");
while(ithasNext()){
Systemoutprintln(itnext());
}
Collection <String> coll=mapvalues();
it=colliterator();
Systemoutprintln("value中集合元素:");
while(ithasNext()){
Systemoutprintln(itnext());
}
}
}
输出结果如图所示:
Java里面没有提供像C,C++那样的Sizeof()方法,所以不可以直接取得内存资源大小
但是有提供RuntimegetRuntime ()totalMemory ()和RuntimegetRuntime ()freeMemory ()这样的方法
所以内存使用大小 = totalMemory () - freeMemory();
但是又不能直接传送Hashmap对象去计算必须在创建Haspmap之前gc一次,然后得到大小,创建HaspMap之后再gc一次,得到内存大小,然后相减
===================================
是的,这种方法统计的内存大小是Java使用的内存但是Java垃圾回收机制,所以不能精确到KB那就是我们在计算得时候必须GC得原因
还有一个办法就是上面这么兄弟说得,用序列化把HaspMap序列化(其实就是写入到一个临时文件)然后这个临时文件得大小,就是内存占用得大小这个可以精确到KB,但是效率上,值得考究
Map map=new HashMap();//实例化map对象mapput("key","value");//存放值(值以键(key)-值(value)方式存放。)Systemoutprint(mapget("key")toString());//取值 根据键就可以取到值
import javautilHashMap;
import javautilIterator;
import javautilSet;
public class TestHm {
public static void main(String atgs[]){
HashMap hm=new HashMap();
//添加内容
hmput("Object key1", "Object value");
hmput("Object key2", "Object value");
hmput("Object key3", "Object value");
hmput("Object key4", "Object value");
//删除Object key3
hmremove("Object key3");
//创建数组,声明i作为数组下标
String s[]=new String[hmsize()];
int i=0;
//显示内容
Set set=hmkeySet();
Iterator it=setiterator();
while(ithasNext()){
String t=(String)itnext();
Systemoutprintln(t);
s[i++]=t;
}
//测试数组是否添加值
Systemoutprintln("===================");
for(int t=0;t<=2;t++)
Systemoutprintln(s[t]);
}
}
以上就是关于用java中如何用Hashmap,通过输入Key输出对应的value全部的内容,包括:用java中如何用Hashmap,通过输入Key输出对应的value、Java中对HashMap的深度分析、java 怎么样获取Map中第几个键值对等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)