diff --git a/src/Common/Interfaces/IHashable.php b/src/Common/Interfaces/IHashable.php new file mode 100644 index 0000000..d26f104 --- /dev/null +++ b/src/Common/Interfaces/IHashable.php @@ -0,0 +1,33 @@ + + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +namespace doganoo\PHPAlgorithms\Common\Interfaces; + +interface IHashable { + + public function getHash(): string; + +} \ No newline at end of file diff --git a/src/Common/Util/MapUtil.php b/src/Common/Util/MapUtil.php index 55e6cee..6a75ddd 100644 --- a/src/Common/Util/MapUtil.php +++ b/src/Common/Util/MapUtil.php @@ -28,8 +28,10 @@ use doganoo\PHPAlgorithms\Common\Exception\InvalidKeyTypeException; use doganoo\PHPAlgorithms\Common\Exception\UnsupportedKeyTypeException; +use doganoo\PHPAlgorithms\Common\Interfaces\IHashable; use function array_walk_recursive; use function ceil; +use function doubleval; use function gettype; use function is_array; use function is_bool; @@ -83,20 +85,23 @@ public static function normalizeKey($key): int { */ if (is_string($key)) { $key = MapUtil::stringToKey($key); - } else if (is_object($key)) { - $objectString = MapUtil::objectToString($key); - $key = MapUtil::stringToKey($objectString); + } else if ($key instanceof IHashable) { + $key = $key->getHash(); + $key = MapUtil::stringToKey($key); + } else if (is_object($key) && !($key instanceof IHashable)) { + $objectString = MapUtil::objectToString($key); + $key = MapUtil::stringToKey($objectString); } else if (is_array($key)) { - $arrayString = MapUtil::arrayToKey($key); - $key = MapUtil::stringToKey($arrayString); + $arrayString = MapUtil::arrayToKey($key); + $key = MapUtil::stringToKey($arrayString); } else if (is_double($key)) { - $key = MapUtil::doubleToKey($key); + $key = MapUtil::doubleToKey($key); } else if (is_float($key)) { - $key = MapUtil::doubleToKey(\doubleval($key)); + $key = MapUtil::doubleToKey(doubleval($key)); } else if (is_bool($key)) { - $key = MapUtil::booleanToKey($key); + $key = MapUtil::booleanToKey($key); } else if (is_resource($key) || $key === null) { - $key = MapUtil::booleanToKey(true); + $key = MapUtil::booleanToKey(true); } else if (is_int($key)) { return $key; } else { diff --git a/tests/Table/Entity/HashableObject.php b/tests/Table/Entity/HashableObject.php new file mode 100644 index 0000000..c83ed44 --- /dev/null +++ b/tests/Table/Entity/HashableObject.php @@ -0,0 +1,43 @@ + + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +namespace doganoo\PHPAlgorithmsTest\Table\Entity; + +use doganoo\PHPAlgorithms\Common\Interfaces\IHashable; + +class HashableObject implements IHashable { + + private $id; + + public function __construct($id) { + $this->id = $id; + } + + public function getHash(): string { + return $this->id; + } + +} \ No newline at end of file diff --git a/tests/Table/HashTableTest.php b/tests/Table/HashTableTest.php index 0eb7c76..825b78b 100644 --- a/tests/Table/HashTableTest.php +++ b/tests/Table/HashTableTest.php @@ -26,7 +26,9 @@ namespace doganoo\PHPAlgorithmsTest\Table; +use doganoo\PHPAlgorithms\Common\Interfaces\IHashable; use doganoo\PHPAlgorithms\Datastructure\Table\HashTable; +use doganoo\PHPAlgorithmsTest\Table\Entity\HashableObject; use doganoo\PHPAlgorithmsTest\Util\HashTableUtil; use PHPUnit\Framework\TestCase; use stdClass; @@ -160,11 +162,33 @@ public function testClosure(): void { $this->assertTrue($added); $added = $hashMap->add("test2", new class { - public function x():void { + public function x(): void { } }); $this->assertTrue($added); } + public function testHashableObject(): void { + $obj = new HashableObject("1"); + $table = new HashTable(); + $table->put($obj, "1"); + + $this->assertTrue($table->size() === 1 && $table->get($obj) === "1"); + + $obj2 = new HashableObject("1"); + $table->put($obj2, "2"); + $this->assertTrue($table->size() === 1 && $table->get($obj) === "2"); + + $table->put("1", "3"); + $this->assertTrue( + $table->size() === 2 + && $table->get($obj) === "2" + && $table->get("1") === "3" + ); + + $this->assertInstanceOf(IHashable::class, $table->keySet()[0]); + $this->assertTrue(is_string($table->keySet()[1])); + } + } \ No newline at end of file