Newer
Older
libj / include / j / util / hash_map.hpp
/**
 * @file map.hpp
 * @brief J Library Map ヘッダファイル。
 * @copyright  2001 - 2024  Nomura Kei
 * @depends
 *   j/util/collection.hpp
 */
#ifndef J_UTIL_HASH_MAP_HPP
#define J_UTIL_HASH_MAP_HPP

#include <unordered_map>

#include <j/util/map.hpp>
#include <j/util/collection.hpp>

namespace j
{
    namespace util
    {

        /**
         * ハッシュマップ。
         * C++17 のハッシュマップ std::unordered_map を内部で利用しています。
         *
         * @code
         * HashMap<j::lang::String, j::lang::String> map;
         * map.put("key1", "value1");
         * map.put("key2", "value2");
         * map.put("key3", "value3");
         *
         * auto value = map.get("key1");
         * // ※auto : std::optional<j::lang::String>
         * if (value)
         * {
         *      std::cout << value.value() << std::endl;
         * }
         * @endcode
         */
        template <typename K, typename V>
        class HashMap : public Map<K, V>
        {
        public:
            HashMap() = default;
            HashMap(const HashMap &map) : data(map.data) {}
            HashMap(HashMap &&map) noexcept : data(std::move(map.data)) {}
            virtual ~HashMap() = default;

            HashMap &operator=(const HashMap &map)
            {
                if (this != &map)
                {

                    data = map.data;
                }
                return *this;
            }

            HashMap &operator=(HashMap &&map) noexcept
            {
                if (this != &map)
                {
                    data = std::move(map.data);
                }
                return *this;
            }
            /**
             * このマップ内のキー値マッピングの数を返します。
             *
             * @return このマップ内のキーと値のマッピング数
             */
            virtual int size() const noexcept
            {
                return data.size();
            }

            /**
             * このマップがキーと値のマッピングを保持しない場合に true を返します。
             *
             * @return このマップがキーと値のマッピングを保持しない場合は true
             */
            virtual bool isEmpty() const noexcept
            {
                return data.empty();
            }

            /**
             * 指定のキーのマッピングが、このマップに含まれている場合に true を返します。
             *
             * @param key このマップ内にあるかどうかが判定されるキー
             * @return このマップが指定されたキーのマッピングを保持する場合は true
             */
            virtual bool containsKey(const K &key) const
            {
                return (data.find(key) != data.end());
            }

            /**
             * マップが1つまたは複数のキーを指定された値にマッピングしている場合に true を返します。
             *
             * @param value このマップにあるかどうかが判定される値
             * @return このマップが1つまたは複数のキーを指定された値にマッピングしている場合は true
             */
            virtual bool containsValue(const V &value) const
            {
                for (const auto &pair : data)
                {
                    if (pair.second == value)
                    {
                        return true;
                    }
                }
                return false;
            }

            /**
             * 指定されたキーがマップされている値を返します。
             * このマップにそのキーのマッピングが含まれていない場合は、要素を値初期化して参照を返す。
             *
             * @param key 関連付けられた値が返されるキー
             * @return 指定されたキーがマップされている値。
             */
            virtual std::optional<V> get(const K &key) const
            {
                auto it = data.find(key);
                if (it != data.end())
                {
                    return it->second;
                }
                return std::nullopt;
            }

            /**
             * 指定された値と指定されたキーをこのマップで関連付けます。
             *
             * @param key 指定された値が関連付けられるキー
             * @param value 指定されたキーに関連付けられる値
             * @return key に以前関連付けられていた値。
             */
            virtual std::optional<V> put(const K &key, const V &value)
            {
                auto it = data.find(key);
                if (it != data.end())
                {
                    V oldValue = it->second;
                    it->second = value;
                    return oldValue;
                }
                else
                {
                    data[key] = value;
                    return std::nullopt;
                }
            }

            /**
             * このマップからキーのマッピングを削除します。
             *
             * @param key マッピングがマップから削除されるキー
             * @return key に以前に関連付けられていた値
             */
            virtual std::optional<V> remove(const K &key)
            {
                auto it = data.find(key);
                if (it != data.end())
                {
                    V value = it->second;
                    data.erase(it);
                    return value;
                }
                return std::nullopt;
            };

            /**
             * マップからマッピングをすべて削除します。
             */
            virtual void clear() noexcept
            {
                data.clear();
            };

        protected:
            std::unordered_map<K, V> data;
        };

    } // namespace util
} // namespace j

#endif // J_UTIL_HASH_MAP_HPP