Is there Java HashMap equivalent in PHP?

前端 未结 5 1633

I need PHP object similar to HashMap in Java, but I didn\'t find when I googled, so if someone knows how I can mimic HashMaps in PHP, help would be appreciated.

5条回答
  •  -上瘾入骨i
    2020-12-02 12:33

    HashMap that also works with keys other than strings and integers with O(1) read complexity (depending on quality of your own hash-function).

    You can make a simple hashMap yourself. What a hashMap does is storing items in a array using the hash as index/key. Hash-functions give collisions once in a while (not often, but they may do), so you have to store multiple items for an entry in the hashMap. That simple is a hashMap:

    class IEqualityComparer {
        public function equals($x, $y) {
            throw new Exception("Not implemented!");
        }
        public function getHashCode($obj) {
            throw new Exception("Not implemented!");
        }
    }
    
    class HashMap {
        private $map = array();
        private $comparer;
    
        public function __construct(IEqualityComparer $keyComparer) {
            $this->comparer = $keyComparer;
        }
    
        public function has($key) {
            $hash = $this->comparer->getHashCode($key);
    
            if (!isset($this->map[$hash])) {
                return false;
            }
    
            foreach ($this->map[$hash] as $item) {
                if ($this->comparer->equals($item['key'], $key)) {
                    return true;
                }
            }
    
            return false;
        }
    
        public function get($key) {
            $hash = $this->comparer->getHashCode($key);
    
            if (!isset($this->map[$hash])) {
                return false;
            }
    
            foreach ($this->map[$hash] as $item) {
                if ($this->comparer->equals($item['key'], $key)) {
                    return $item['value'];
                }
            }
    
            return false;
        }
    
        public function del($key) {
            $hash = $this->comparer->getHashCode($key);
    
            if (!isset($this->map[$hash])) {
                return false;
            }
    
            foreach ($this->map[$hash] as $index => $item) {
                if ($this->comparer->equals($item['key'], $key)) {
                    unset($this->map[$hash][$index]);
                    if (count($this->map[$hash]) == 0)
                        unset($this->map[$hash]);
    
                    return true;
                }
            }
    
            return false;
        }
    
        public function put($key, $value) {
            $hash = $this->comparer->getHashCode($key);
    
            if (!isset($this->map[$hash])) {
                $this->map[$hash] = array();
            }
    
            $newItem = array('key' => $key, 'value' => $value);        
    
            foreach ($this->map[$hash] as $index => $item) {
                if ($this->comparer->equals($item['key'], $key)) {
                    $this->map[$hash][$index] = $newItem;
                    return;
                }
            }
    
            $this->map[$hash][] = $newItem;
        }
    }
    

    For it to function you also need a hash-function for your key and a comparer for equality (if you only have a few items or for another reason don't need speed you can let the hash-function return 0; all items will be put in same bucket and you will get O(N) complexity)

    Here is an example:

    class IntArrayComparer extends IEqualityComparer {
        public function equals($x, $y) {
            if (count($x) !== count($y))
                return false;
    
            foreach ($x as $key => $value) {
                if (!isset($y[$key]) || $y[$key] !== $value)
                    return false;
            }
    
            return true;
        }
    
        public function getHashCode($obj) {
            $hash = 0;
            foreach ($obj as $key => $value)
                $hash ^= $key ^ $value;
    
            return $hash;
        }
    }
    
    $hashmap = new HashMap(new IntArrayComparer());
    
    for ($i = 0; $i < 10; $i++) {
        for ($j = 0; $j < 10; $j++) {
            $hashmap->put(array($i, $j), $i * 10 + $j);
        }
    }
    
    echo $hashmap->get(array(3, 7)) . "
    "; echo $hashmap->get(array(5, 1)) . "
    "; echo ($hashmap->has(array(8, 4))? 'true': 'false') . "
    "; echo ($hashmap->has(array(-1, 9))? 'true': 'false') . "
    "; echo ($hashmap->has(array(6))? 'true': 'false') . "
    "; echo ($hashmap->has(array(1, 2, 3))? 'true': 'false') . "
    "; $hashmap->del(array(8, 4)); echo ($hashmap->has(array(8, 4))? 'true': 'false') . "
    ";

    Which gives as output:

    37
    51
    true
    false
    false
    false
    false
    

提交回复
热议问题