定义接口类 IHasMap
public interface IHasMap {
public void put(String key,Object object);
public Object get(String key);
}
定义键值类 Entry
public class Entry {
public Object key;
public Object value;
public Entry(Object key, Object value) {
super();
this.key = key;
this.value = value;
}
@Override
public String toString() {
return "[key=" + key + ", value=" + value + "]";
}
}
定义传入字符串返回对应1-2000的数字值 模拟hashcode类
/**
* 自定义字符串的hashcode
*/
public class hashcode {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
//生成100个字符串 长度2-10不等
for(int i=0;i<100;i++){
list.add(Test06.captcha((int) (Math.random() * 8) + 2));
}
for (String s : list) {
//System.out.println(s+"的自定义hashcode是:"+Myhashcode(s));
System.out.printf("%-10s的自定义hashcode是:%d%n",s,Myhashcode(s));
}
}
/**
* 静态方法 返回一个字符串的hashcose
*/
public static int Myhashcode(String string) {
int hashcode = 0;
if (0 != string.length()) {
//(s[0]+ s[1] + s[2] + s[3]+ s[n-1])*23 自定义算法
return add(string);
} else {
return hashcode;
}
}
public static int add(String str) {
int[] strsum = new int[str.length()];
for(int i=0;i<str.length();i++){
int i1 = str.charAt(i);
strsum[i] = i1;
}
int sum = 0;
for (int i : strsum) {
sum += i;
}
sum = sum*23;
if(sum<0){//如果是负取绝对值
sum = Math.abs(sum);
}
if((sum>1999)){//超过1999取余
sum = sum%2000;
}
return sum;
}
}
创建MyHashMap类 模拟HashMap类 并做性能测试
/**
* 根据前面学习的hashcode的原理和自定义hashcode, 设计一个MyHashMap,实现接口IHashMap
*
* MyHashMap内部由一个长度是2000的对象数组实现。
*
* 设计put(String key,Object value)方法
* 首先通过上一个自定义字符串的hashcode练习获取到该字符串的hashcode,然后把这个hashcode作为下标,定位到数组的指定位置。
* 如果该位置没有数据,则把字符串和对象组合成键值对Entry,再创建一个LinkedList,把键值对,放进LinkedList中,最后把LinkedList 保存在这个位置。
* 如果该位置有数据,一定是一个LinkedList,则把字符串和对象组合成键值对Entry,插入到LinkedList后面。
*
* 设计 Object get(String key) 方法
* 首先通过上一个自定义字符串的hashcode练习获取到该字符串的hashcode,然后把这个hashcode作为下标,定位到数组的指定位置。
* 如果这个位置没有数据,则返回空
* 如果这个位置有数据,则挨个比较其中键值对的键-字符串,是否equals,找到匹配的,把键值对的值,返回出去。找不到匹配的,就返回空
*/
public class MyHashMap implements IHasMap {
public static void main(String[] args) {
List<Hero> hs = new ArrayList<>();
System.out.println("300万个对象初始化开始");
for (int i=0;i<3000000;i++){
Hero h = new Hero("hero"+random());//hero-5555
hs.add(h);
}
//hero英雄属性name相同的对象放在同一个list集合中 name作为Key
MyHashMap myHashMap = new MyHashMap();
for (Hero h : hs){
List<Hero> list = (List<Hero>) myHashMap.get(h.name);//找到这个集合对象 键值对的value
if(list==null){
list = new ArrayList<>();//
myHashMap.put(h.name,list);//hero-5555
}
list.add(h);// name相同的英雄对象直接放到集合中
}
System.out.println("300万个对象初始化结束");
System.out.println("开始查找");
long s = System.currentTimeMillis();
List<Hero> re = (List<Hero>) myHashMap.get("hero5555");
long e = System.currentTimeMillis();
System.out.println("MyHashMap名字是hero-5555的英雄有:" + re.size()+"个"+" 时间:"+(e-s)+"毫秒");
//for循环
s = System.currentTimeMillis();
int count = 0;
for (Hero h : hs) {
if (h.name.equals("hero5555")){
count++;
}
}
e = System.currentTimeMillis();
System.out.println("for名字是hero-5555的英雄有:" + count +"个"+" 时间:"+(e-s)+"毫秒");
}
public static int random(){
return (int)((Math.random()*9000)+1000);
}
//MyHashMap内部由一个长度是2000的对象数组实现
LinkedList<Entry>[] values = new LinkedList[2000];
@Override
public void put(String key, Object object) {
//拿到hashcode
int hashcodes = hashcode.Myhashcode(key);//获得该字符串的 hashcode 1-2000
//找到对应的Linkedlist
LinkedList<Entry> list = values[hashcodes];//找到链表数组下标为hashcode的链表对象
//判断是否为空 如果空就创建一个实例 如果这个链表下面的对象为空(Entry - 键值对对象)
if(null == list ){
list = new LinkedList<>();//创建一个链表容器
values[hashcodes] = list;//放到该链表数组对应的下标下边
}
//判断key是否有对应的键值对
boolean found = false;
for (Entry entry : list) {//如果该数组下标的链表对象不为空 就判断链表对象Entry的键KEY是否相等 如果相等就更新值Value
// 如果已经有了 则替换
if(key.equals(entry.key)){
entry.value = object;
found = true;
break;
}
}
//如果没有存在的键值对 则创建
if(!found){// 如果该键key的对象不存在 就创建一个Entry键值对象
Entry entry = new Entry(key,object);
list.add(entry);//添加的对象中
}
}
@Override
public Object get(String key) {//根据键的字符串查询对应存放数组的位置 找到位置后查询匹配的Key然后返回
// 获取hashcode
int hashcodes = hashcode.Myhashcode(key);
// 找到hashcode对应的linkedlist
LinkedList<Entry> list = values[hashcodes];
if(null == list){
return null;
}
Object res = null;
//挨个比较每个键值队的key 找到匹配的返回对象
for(Entry entry : list) {
if (entry.key.equals(key)) {
res = entry.value;
break;
}
}
return res;
}
@Override
public String toString() {
LinkedList<Entry> res = new LinkedList<>();
for (LinkedList<Entry> linkedList : values) {
if(null == linkedList){
continue;
}else {
res.addAll(linkedList);
}
}
return res.toString();
}
}
运行结果
300万个对象初始化开始
300万个对象初始化结束
开始查找
MyHashMap名字是hero-5555的英雄有:349个 时间:0毫秒
for名字是hero-5555的英雄有:349个 时间:33毫秒
https://how2j.cn?p=316556学习及视频讲解 how2j