键值表
来源:互联网 发布:sql count(1) 编辑:程序博客网 时间:2024/04/19 12:50
什么是键值表
键值表是键值对集合,类似字典,支持存入键值对,按键查值等操作。
对外接口
public void put(Key key, Value val);
public Value get(Key key);
public boolean contains(Key key);
public Value remove(Key key);
public int size();
public boolean isEmpty();
接口代码
public interface IMap<Key, Value> { /** * 存入键值对 * * @param key * 键 * @param value * 值 */ public void put(Key key, Value value); /** * 按鍵查值 * * @param key * 鍵 * @return 值 */ public Value get(Key key); /** * 判断是否包含某键 * * @param key * 键 * @return <code>true</code> 若包含;否则,<code>false</code> */ public boolean contains(Key key); /** * 删除键为key的键值对 * * @param key * 键 */ public Value remove(Key key); /** * 返回键值对个数 * * @return 键值对个数 */ public int size(); /** * 判断键值表是否为空 * * @return <code>true</code> 如果键值表为空;否则,<code>false</code>。 */ public boolean isEmpty();}
初级实现
package com.gmail.dailyefforts.ds;import java.util.HashMap;import java.util.Map;import java.util.Random;public class SimpleLinkedMap<Key, Value> implements IMap<Key, Value>{ private class Node { private Node prev; private Key key; private Value val; private Node next; public Node(Node prev, Key key, Value val, Node next) { this.prev = prev; this.key = key; this.val = val; this.next = next; } @Override public String toString() { return String.format("%s=%s", String.valueOf(key), String.valueOf(val)); } } private int size; private Node first; private Node last; @Override public void put(Key key, Value val) { for (Node x = first; x != null; x = x.next) { if (key.equals(x.key)) { x.val = val; return; } } Node oldLast = last; last = new Node(last, key, val, null); if (oldLast != null) { oldLast.next = last; } size++; if (first == null) { first = last; } } @Override public Value remove(Key key) { for (Node x = first; x != null; x = x.next) { if (key.equals(x.key)) { if (x.prev == null) { first = x.next; } else { x.prev.next = x.next; } if (x.next == null) { last = x.prev; } else { x.next.prev = x.prev; } size--; return x.val; } } return null; } @Override public boolean contains(Key key) { return get(key) != null; } @Override public Value get(Key key) { for (Node x = first; x != null; x = x.next) { if (key.equals(x.key)) { return x.val; } } return null; } @Override public int size() { return size; } @Override public boolean isEmpty() { return size() == 0; } @Override public String toString() { StringBuilder builder = new StringBuilder(); builder.append('{'); for (Node x = first; x != null; x = x.next) { builder.append(x); if (x.next != null) { builder.append(", "); } } builder.append('}'); return builder.toString(); } public static void main(String[] args) { final int N = 100 * 100; SimpleLinkedMap<Integer, String> map = new SimpleLinkedMap<>(); Map<Integer, String> map2 = new HashMap<>(); for (int i = 0; i < N; i++) { Integer key = Integer.valueOf(i); String value = "item-" + i; map2.put(key, value); map.put(key, value); }// System.out.println(map2);// System.out.println(map); Random random = new Random(System.currentTimeMillis()); for (int i = 0; i < N / 2; i++) { final int key = random.nextInt(N); final String a = map.remove(key); final String b = map2.remove(key); if (a == null) { assert (b == null); } else { assert (a.equals(b)); } } assert(map.size() == map2.size()); for (int i = 0; i < N; i++) { final String a = map.get(i); final String b = map2.get(i); if (a == null) { assert (b == null); } else { assert (a.equals(b)); } } }}
Hash实现
在上面的初级实现中,每次查询都要遍历了整个字典,效率为O(n)。现实中,我们从字典中查询某个单词时,我们借助索引来提高效率,而不是从该字典收录的第一个词开始逐个遍历整个字典。
我们可以利用hash来建立索引,遇到索引相同时再用链表存储。
package com.gmail.dailyefforts.ds;import java.util.HashMap;import java.util.Map;import java.util.Random;public class MyHashMap<Key, Value> implements IMap<Key, Value> { private int size; private static final int M = 100 * 100; private SimpleLinkedMap<Key, Value>[] a = (SimpleLinkedMap<Key, Value>[]) new SimpleLinkedMap[M]; @Override public void put(Key key, Value value) { SimpleLinkedMap<Key, Value> map = map(key); if (!map.contains(key)) { size++; } map.put(key, value); } private int hash(Key key) { // [0, M] return key.hashCode() & 0x7fffffff % M; } private SimpleLinkedMap<Key, Value> map(Key key) { int index = hash(key); if (a[index] == null) { a[index] = new SimpleLinkedMap<Key, Value>(); } return a[index]; } @Override public Value get(Key key) { return map(key).get(key); } @Override public boolean contains(Key key) { return map(key).contains(key); } @Override public Value remove(Key key) { Value value = map(key).remove(key); if (value != null) { size--; } return value; } @Override public int size() { return this.size; } @Override public String toString() { return super.toString(); } @Override public boolean isEmpty() { return size() == 0; } public static void main(String[] args) { final int N = 100 * 100 * 100; MyHashMap<Integer, String> map = new MyHashMap<>(); Map<Integer, String> mapRef = new HashMap<>(); for (int i = 0; i < N; i++) { Integer key = Integer.valueOf(i); String value = "item-" + i; map.put(key, value); mapRef.put(key, value); } assert(map.size() == mapRef.size()); Random random = new Random(System.currentTimeMillis()); for (int i = 0; i < N / 2; i++) { final int key = random.nextInt(N); assert (map.contains(key) == mapRef.containsKey(key)); final String a = map.remove(key); final String b = mapRef.remove(key); if (a == null) { assert (b == null); } else { assert (a.equals(b)); } } assert (map.size() == mapRef.size()); for (int i = 0; i < N; i++) { final int key = random.nextInt(N); final String a = map.get(key); final String b = mapRef.get(key); if (a == null) { assert (b == null); } else { assert (a.equals(b)); } } System.out.println("test passed"); }}
0 0
- 键值表
- 键值表
- 键值表
- 键值表
- 手机键盘键值表
- 虚拟键值表
- MOTO手机键值表
- 键盘键值表
- event.keyCode键值表
- 虚拟键值表
- 键盘键值表
- 虚拟键值表【转】
- 键值保存表
- W3C键值对应表
- 键盘键值表
- 虚拟键值表
- JavaScript键盘键值表
- event.keyCode键值表
- java面向对象编程基本概念
- [学习笔记—Objective-C]《Objective-C 程序设计 第6版》第十一章 分类和协议
- 第4章 基纳法 阅读(PageRank的兄弟)
- perl 面向对象 -> 符号使用
- 2.2 Zend_Controller 基础
- 键值表
- iOS7中的多任务
- linux变量的心得
- Android入门(14)——使用Spinner实现下拉列表
- Android实践-自定义dialog从屏幕底部弹出并且充满屏幕宽度
- Category
- 正处于尴尬的年纪
- UITableView启动后自动设置滚动的位置
- android入门学习-学习规划