#pragma once #include #include "Array.h" namespace Framework { template class MapEntry { private: K key; V value; public: MapEntry() {} MapEntry( K key, V value ) : key( key ), value( value ) {} K getKey() { return key; } V getValue() { return value; } template friend class HashMap; }; template class HashMap : public virtual ReferenceCounter { private: Array< MapEntry > **buckets; int bucketCount; std::function hash; public: HashMap( int bucketCount, std::function hash ) : ReferenceCounter(), buckets( new Array< MapEntry > *[ bucketCount ] ), bucketCount( bucketCount ), hash( hash ) { memset( buckets, 0, sizeof( Array< MapEntry > * ) * bucketCount ); } ~HashMap() { for( int i = 0; i < bucketCount; i++ ) { if( buckets[ i ] ) buckets[ i ]->release(); } delete[] buckets; } void put( K key, V value ) { int index = hash( key ) % bucketCount; if( !buckets[ index ] ) buckets[ index ] = new Array< MapEntry>(); for( auto iterator = buckets[ index ]->getIterator(); iterator; iterator++ ) { if( iterator._.getKey() == key ) { iterator.set( MapEntry( key, value ) ); return; } } buckets[ index ]->add( MapEntry( key, value ) ); } void remove( K key ) { int index = hash( key ) % bucketCount; if( !buckets[ index ] ) return; int listIndex = 0; for( auto iterator = buckets[ index ]->getIterator(); iterator; iterator++, listIndex++ ) { if( iterator._.getKey() == key ) { buckets[ index ]->remove( listIndex ); return; } } } V get( K key ) const { int index = hash( key ) % bucketCount; if( !buckets[ index ] ) throw "element not found"; for( auto iterator = buckets[ index ]->getIterator(); iterator; iterator++ ) { if( iterator._.getKey() == key ) return iterator._.getValue(); } throw "element not found"; } V safeGet( K key, V fallback ) const { int index = hash( key ) % bucketCount; if( !buckets[ index ] ) return fallback; for( auto iterator = buckets[ index ]->getIterator(); iterator; iterator++ ) { if( iterator._.getKey() == key ) return iterator._.getValue(); } return fallback; } bool has( K key ) const { int index = hash( key ) % bucketCount; if( !buckets[ index ] ) return 0; for( auto iterator = buckets[ index ]->getIterator(); iterator; iterator++ ) { if( iterator._.getKey() == key ) return 1; } return 0; } }; }