Есть ли в PHP эквивалент Java HashMap? - PullRequest
59 голосов
/ 27 июля 2011

Мне нужен объект PHP, похожий на HashMap в Java, но я не нашел, когда гуглил, поэтому, если кто-то знает, как я могу имитировать HashMaps в PHP, будет полезна помощь.

Ответы [ 5 ]

76 голосов
/ 27 июля 2011

Массивы в PHP могут иметь структуру Key Value.

31 голосов
/ 15 июля 2014

В зависимости от того, что вы хотите, вас может заинтересовать класс хранения объектов 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'
26 голосов
/ 15 февраля 2014

Создайте Java-подобный HashMap в PHP с 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";
 ... }

Цикл добавляет 1 миллиард ключей / значений, требуется около 2 минут, чтобы добавить их все в hashmapчто может исчерпать вашу память.

Затем посмотрите, сколько времени потребуется для поиска:

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

Так как же быстро поиск карты массива PHP?

10333 - это ключ, который мы искали.1 миллион наносекунд == 1 миллисекундаВремя, необходимое для получения значения из ключа, составляет 2,06 миллиона наносекунд или около 2 миллисекунд.Примерно столько же времени, если массив был пуст.Это выглядит как постоянное время для меня.

11 голосов
/ 27 июля 2011
$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"]

выводит «Банан»

взят из http://in2.php.net/manual/en/function.array.php

9 голосов
/ 01 марта 2014

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...