localdisk

PHP とか Java とか Web とか好きなことを書きます。

PHPでJava風のHashMapを作ってみた

仕事中にカッとなって作った。特に反省はしていない。
終電が迫っているのでとりあえずソースだけ貼っておく。こういったちょっとしたソースを気軽に置いておける場所とかがあるのかな? CodeReposは僕にはちょっと敷居が高い。というか怖い。
ソースの解説は帰宅してからということで。電車がやばい!帰ってご飯食べたので解説。
entrySet/keySet/valuesメソッドを追加。

解説

大したものでもないですが、一応。
PHP5になってSPL(Standard PHP Livrary)というクラスライブラリが導入されてます。

あまり意識されてない方でもException自体は馴染みがあるのではないでしょうか。今回作成したものもSPLのArrayObjectを拡張したものです。結構ちゃんと使えるメソッドが揃っていてちょっと手を加えるだけでJavaのHashMapっぽいものはちゃんと作れたりします。この分だとArrayListっぽいものを作るのも簡単だと思います。
「hashとlistの区別がついていない」とか言われるPHPですが、ちょっと手を加えてあげればちゃんといい感じに使えます。
enjoy PHP!

<?php
/**
 * JavaのHashMapっぽいクラス
 * <code>
 * $map = new HashMap();
 * $map->put('foo', 'bar');
 * $map->get('foo'); // bar
 * </code>
**/
class HashMap extends ArrayObject {
    /**
     * コンストラクタ
     *
     * @param array $array
     */
    public function __construct($array = array()) {
        parent::__construct($array, ArrayObject::ARRAY_AS_PROPS);
    }
    /**
     * マップが指定のキーのマッピングを保持する場合に true を返します
     *
     * @param  integer|string $key
     * @return boolean
     */
    public function containsKey($key) {
        return parent::offsetExists($key);
    }
    /**
     * マップが 1 つまたは複数のキーと指定された値をマッピングしている場合に true を返します
     *
     * @param  mixed $value
     * @return boolean
     */
    public function containsValue($value) {
        foreach ($this as $k => $v) {
            if ($value === $v) {
                return true;
            }
        }
        return false;
    }
    /**
     * 指定されたキーがマップされている値を返します
     *
     * @param  integer|string $key
     * @return mixed
     */
    public function get($key) {
        return parent::offsetGet($key);
    }
    /**
     * 指定された値と指定されたキーをこのマップに関連付けます
     * @param  integer|string $key
     * @param  mixed          $value
     * @return void
     */
    public function put($key = null, $value = null) {
        if ($value === null) {
            return;
        }
        if ($key === null) {
            parent::append($value);
            return;
        }
        parent::offsetSet($key, $value);
    }
    /**
     * 指定されたマップからすべてのマッピングをマップにコピーします
     *
     * @param ArrayObject $map
     */
    public function putAll(ArrayObject $map) {
        $i = $map->getIterator();
        foreach ($i as $k => $v) {
            $this->put($k, $v);
        }
    }
    /**
     * マップがキーと値のマッピングを保持しない場合に true を返します
     *
     * @return boolean
     */
    public function isEmpty() {
        return parent::count() === 0 ? true : false;
    }
    /**
     * 指定されたキーのマッピングがあればマップから削除します
     *
     * @param <type> $key
     */
    public function remove($key) {
        parent::offsetUnset($key);
    }
    /**
     * マップ内のキー値マッピングの数を返します
     *
     * @return integer
     */
    public function size() {
        return parent::count();
    }
    /**
     * このマップに含まれるマップの Iterator ビューを返します
     * 
     * @return ArrayIterator
     */
    public function entrySet() {
        return parent::getIterator();
    }
    /**
     * このマップに含まれるキーの Iterator ビューを返します
     *
     * @return ArrayIterator
     */
    public function keySet() {
        $a = array();
        foreach ($this as $k => $v) {
            $a[] = $k;
        }
        return new ArrayIterator($a);
    }
    /**
     * このマップに含まれるマップの Iterator ビューを返します
     * 
     * @return ArrayIterator
     */
    public function values() {
        $a = array();
        foreach ($this as $k => $v) {
            $a[] = $v;
        }
        return new ArrayIterator($a);
    }
}