PHP 中是否有 Java HashMap 等效项?

发布于 2024-11-27 01:17:43 字数 80 浏览 0 评论 0原文

我需要类似于Java中的HashMap的PHP对象,但我在谷歌搜索时没有找到,所以如果有人知道我如何在PHP中模仿HashMap,我们将不胜感激。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

苏别ゝ 2024-12-04 01:17:43

PHP 中的数组可以具有键值结构。

Arrays in PHP can have Key Value structure.

离去的眼神 2024-12-04 01:17:43

在 PHP 中创建类似 Java 的 HashMap,读取复杂度为 O(1)。

打开 phpsh 终端:

php> $myhashmap = array();
php> $myhashmap['mykey1'] = 'myvalue1';
php> $myhashmap['mykey2'] = 'myvalue2';
php> echo $myhashmap['mykey2'];
myvalue2

在这种情况下,$myhashmap['mykey2'] 的复杂度似乎是常数时间 O(1),这意味着当 $myhasmap 的大小接近无穷大时,在给定键的情况下检索值所需的时间保持不变。

证明 php 数组读取的时间是恒定的:

通过 PHP 解释器运行此操作:

php> for($x = 0; $x < 1000000000; $x++){
 ... $myhashmap[$x] = $x . " derp";
 ... }

循环添加 10 亿个键/值,大约需要 2 分钟才能将它们全部添加到 hashmap,这可能会耗尽您的内存。

然后看看查找一次需要多长时间:

php> system('date +%N');echo "  " . $myhashmap[10333] . "  ";system('date +%N');
786946389  10333 derp  789008364

那么 PHP 数组映射查找的速度有多快?

10333 是我们查找的键。 100 万纳秒 == 1 毫秒。从键获取值所需的时间为 206 万纳秒或大约 2 毫秒。如果数组为空,则时间大约相同。对我来说,这看起来像是恒定的时间。

Create a Java like HashMap in PHP with O(1) read complexity.

Open a phpsh terminal:

php> $myhashmap = array();
php> $myhashmap['mykey1'] = 'myvalue1';
php> $myhashmap['mykey2'] = 'myvalue2';
php> echo $myhashmap['mykey2'];
myvalue2

The complexity of the $myhashmap['mykey2'] in this case appears to be constant time O(1), meaning that as the size of $myhasmap approaches infinity, the amount of time it takes to retrieve a value given a key stays the same.

Evidence the php array read is constant time:

Run this through the PHP interpreter:

php> for($x = 0; $x < 1000000000; $x++){
 ... $myhashmap[$x] = $x . " derp";
 ... }

The loop adds 1 billion key/values, it takes about 2 minutes to add them all to the hashmap which may exhaust your memory.

Then see how long it takes to do a lookup:

php> system('date +%N');echo "  " . $myhashmap[10333] . "  ";system('date +%N');
786946389  10333 derp  789008364

So how fast is the PHP array map lookup?

The 10333 is the key we looked up. 1 million nanoseconds == 1 millisecond. The amount of time it takes to get a value from a key is 2.06 million nanoseconds or about 2 milliseconds. About the same amount of time if the array were empty. This looks like constant time to me.

扶醉桌前 2024-12-04 01:17:43

根据您的需求,您可能对 SPL 对象存储类感兴趣。

http://php.net/manual/en/class.splobjectstorage.php

它允许您使用对象作为键,有一个接口来计数、获取哈希值和其他好处。

$s = new SplObjectStorage;
$o1 = new stdClass;
$o2 = new stdClass;
$o2->foo = 'bar';

$s[$o1] = 'baz';
$s[$o2] = 'bingo';

echo $s[$o1]; // 'baz'
echo $s[$o2]; // 'bingo'

Depending on what you want you might be interested in the SPL Object Storage class.

http://php.net/manual/en/class.splobjectstorage.php

It lets you use objects as keys, has an interface to count, get the hash and other goodies.

$s = new SplObjectStorage;
$o1 = new stdClass;
$o2 = new stdClass;
$o2->foo = 'bar';

$s[$o1] = 'baz';
$s[$o2] = 'bingo';

echo $s[$o1]; // 'baz'
echo $s[$o2]; // 'bingo'
把昨日还给我 2024-12-04 01:17:43
$fruits = array (
    "fruits"  => array("a" => "Orange", "b" => "Banana", "c" => "Apple"),
    "numbers" => array(1, 2, 3, 4, 5, 6),
    "holes"   => array("first", 5 => "second", "third")
);

echo $fruits["fruits"]["b"]

输出 'Banana'

取自 https://www.php.net/manual/ en/function.array.php

$fruits = array (
    "fruits"  => array("a" => "Orange", "b" => "Banana", "c" => "Apple"),
    "numbers" => array(1, 2, 3, 4, 5, 6),
    "holes"   => array("first", 5 => "second", "third")
);

echo $fruits["fruits"]["b"]

outputs 'Banana'

taken from https://www.php.net/manual/en/function.array.php

只有一腔孤勇 2024-12-04 01:17:43

HashMap 还可以使用除字符串和整数以外的键,读取复杂度为 O(1)(取决于您自己的哈希函数的质量)。

你可以自己制作一个简单的hashMap。 hashMap 的作用是使用哈希作为索引/键将项目存储在数组中。哈希函数偶尔会发生冲突(不常见,但可能会发生),因此您必须为 hashMap 中的条目存储多个项目。这个简单的就是 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;
    }
}

要使其发挥作用,您还需要一个用于键的哈希函数和一个用于相等的比较器(如果您只有几个项目或由于其他原因不需要速度,您可以让哈希函数返回0;所有项目都将放入同一个桶中,您将获得 O(N) 复杂度)

这是一个示例:

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)) . "<br/>";
echo $hashmap->get(array(5, 1)) . "<br/>";

echo ($hashmap->has(array(8, 4))? 'true': 'false') . "<br/>";
echo ($hashmap->has(array(-1, 9))? 'true': 'false') . "<br/>";
echo ($hashmap->has(array(6))? 'true': 'false') . "<br/>";
echo ($hashmap->has(array(1, 2, 3))? 'true': 'false') . "<br/>";

$hashmap->del(array(8, 4));
echo ($hashmap->has(array(8, 4))? 'true': 'false') . "<br/>";

输出如下:

37
51
true
false
false
false
false

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)) . "<br/>";
echo $hashmap->get(array(5, 1)) . "<br/>";

echo ($hashmap->has(array(8, 4))? 'true': 'false') . "<br/>";
echo ($hashmap->has(array(-1, 9))? 'true': 'false') . "<br/>";
echo ($hashmap->has(array(6))? 'true': 'false') . "<br/>";
echo ($hashmap->has(array(1, 2, 3))? 'true': 'false') . "<br/>";

$hashmap->del(array(8, 4));
echo ($hashmap->has(array(8, 4))? 'true': 'false') . "<br/>";

Which gives as output:

37
51
true
false
false
false
false
树深时见影 2024-12-04 01:17:43

您可以在 php.ini 中为此创建一个自定义 HashMap 类。
如下所示的示例包含基本的 HashMap 属性,例如 get 和 set。

class HashMap{

        public $arr;

        function init() {

            function populate() {
                return null;
            }
            
            // change to 999 for efficiency
            $this->arr = array_map('populate', range(0, 9));

            return $this->arr;

        }
        
        function get_hash($key) {
            $hash = 0;

            for ($i=0; $i < strlen($key) ; $i++) { 
                $hash += ord($key[$i]);
            }
            
            // arr index starts from 0
            $hash_idx = $hash % (count($this->arr) - 1); 
            return $hash_idx;
            
        }

        function add($key, $value) {
            $idx = $this->get_hash($key);
            
            if ($this->arr[$idx] == null) {
                $this->arr[$idx] = [$value];
            } else{

                $found = false;

                $content = $this->arr[$idx];
                
                $content_idx = 0;
                foreach ($content as $item) {

                    // checking if they have same number of streams
                    if ($item == $value) {

                        $content[$content_idx] = [$value];
                        $found = true;
                        break;

                    }
                    
                    $content_idx++;
                }

                if (!$found) {
                    // $value is already an array
                    array_push($content, $value);

                    // updating the array
                    $this->arr[$idx] = $content;
                }

            }

            return $this->arr;

        }

        function get($key) {

            $idx = $this->get_hash($key);
            $content = $this->arr[$idx];

            foreach ($content as $item) {
                if ($item[1] == $key) {
                    return $item;
                    break;
                }
            }
                
        }

    }

希望这有用

You could create a custom HashMap class for that in php.
example as shown below containing the basic HashMap attributes such as get and set.

class HashMap{

        public $arr;

        function init() {

            function populate() {
                return null;
            }
            
            // change to 999 for efficiency
            $this->arr = array_map('populate', range(0, 9));

            return $this->arr;

        }
        
        function get_hash($key) {
            $hash = 0;

            for ($i=0; $i < strlen($key) ; $i++) { 
                $hash += ord($key[$i]);
            }
            
            // arr index starts from 0
            $hash_idx = $hash % (count($this->arr) - 1); 
            return $hash_idx;
            
        }

        function add($key, $value) {
            $idx = $this->get_hash($key);
            
            if ($this->arr[$idx] == null) {
                $this->arr[$idx] = [$value];
            } else{

                $found = false;

                $content = $this->arr[$idx];
                
                $content_idx = 0;
                foreach ($content as $item) {

                    // checking if they have same number of streams
                    if ($item == $value) {

                        $content[$content_idx] = [$value];
                        $found = true;
                        break;

                    }
                    
                    $content_idx++;
                }

                if (!$found) {
                    // $value is already an array
                    array_push($content, $value);

                    // updating the array
                    $this->arr[$idx] = $content;
                }

            }

            return $this->arr;

        }

        function get($key) {

            $idx = $this->get_hash($key);
            $content = $this->arr[$idx];

            foreach ($content as $item) {
                if ($item[1] == $key) {
                    return $item;
                    break;
                }
            }
                
        }

    }

Hope this was useful

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文