键值表

原创 2015年07月06日 22:35:00

什么是键值表

键值表是键值对集合,类似字典,支持存入键值对,按键查值等操作。

对外接口

  • 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");
    }

}

键盘键值表

  • 2015年07月13日 23:34
  • 93KB
  • 下载

虚拟键值表.doc

  • 2012年03月27日 10:49
  • 231KB
  • 下载

ORA-01779: 无法修改与非键值保存表对应的列

项目中通过子查询更新数据时遇到ORA-01779: 无法修改与非键值保存表对应的列,模拟过程如下: 1、创建测试表 CREATE TABLE tt1 (ID INT,col1 VAR...

键盘键值表

  • 2008年04月17日 18:47
  • 224KB
  • 下载

javascript 和 ascii码键值表

  • 2009年09月25日 17:31
  • 3KB
  • 下载

Android KEYCODE键值对应表

Android KEYCODE键值对应大全的整理,并添加几个测试得出的未知按键
  • Yokeqi
  • Yokeqi
  • 2014年12月21日 00:04
  • 1233

键盘键值表

  • 2013年07月11日 17:08
  • 145KB
  • 下载

键盘虚拟键值表

  • 2013年09月27日 09:27
  • 37KB
  • 下载

Windows Mobile 常用键值(VK)对应表

#define VK_TSOFT1   VK_F1               // Softkey 1 #define VK_TSOFT2   VK_F2               // Sof...

键盘键值表

  • 2013年04月20日 23:19
  • 67KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:键值表
举报原因:
原因补充:

(最多只允许输入30个字)