Мне нужен PHP-объект, похожий на HashMap в Java, но я не нашел, когда я googled, поэтому, если кто-то знает, как я могу имитировать HashMaps на PHP, помощь будет оценена.
Массивы в PHP могут иметь структуру ключевых значений.
В зависимости от того, что вы хотите, вас может заинтересовать класс SPL Object Storage.
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'
Откройте phph-терминал:
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"; ... }
Цикл добавляет 1 миллиард ключей / значений, требуется около 2 минут, чтобы добавить их все в хэш-карту, которая может исчерпать вашу память.
Затем посмотрите, сколько времени требуется для поиска:
php> system('date +%N');echo " " . $myhashmap[10333] . " ";system('date +%N'); 786946389 10333 derp 789008364
Итак, насколько быстро поиск по карте массива PHP?
10333
– это ключ, который мы подняли. 1 миллион наносекунд == 1 миллисекунда. Время, затрачиваемое на получение стоимости от ключа, составляет 2,06 миллиона наносекунд или около 2 миллисекунд. Примерно столько же времени, если массив был пустым. Это выглядит как постоянное время для меня.
$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"]
выходы «Банан»
Вы можете сделать простой 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; } }
с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; } }
с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