plsql HashMap &HashSet implement

Thinking

HashMap 和HashSet其实类似于具有特定存储方式的二维数组。拿Integerhashset为例,我想要往hashset里面存储一个数字5,首先先通过某一种hash算法获得一个hash值比如获得的是3,那么先纵向遍历,查看二维数组的纵列第三个位置上是否为空,如果为空,就将该二维数组的横向初始化,然后把数字5放进初始化的横向数组里面;如果,二维数组第三个位置不为空,那么再继续横向遍历找到位置三并将数字5放入(注意:如果该位置也有值那么会覆盖掉原来的值)

plsql IntegerSet

CREATE OR REPLACE TYPE IntegerSet_gdb AS OBJECT
    (chains IntegerarrayArray , numChains integer , numEntries integer ,
     threshold integer , --阈值
   loadFactor float ,
     cachedChain integer , cachedChainPos integer , CONSTRUCTOR FUNCTION IntegerSet_gdb RETURN SELF AS RESULT, MEMBER PROCEDURE put (k INTEGER ), MEMBER FUNCTION get (k INTEGER ) RETURN boolean , MEMBER FUNCTION getByIndex (self IN OUT NOCOPY IntegerSet_gdb , idx integer ) RETURN INTEGER , MEMBER PROCEDURE remove (k INTEGER ), MEMBER PROCEDURE clear, MEMBER FUNCTION getNumEntries RETURN integer , --整个set里面存储内容的个数 MEMBER FUNCTION isEmpty RETURN boolean , MEMBER FUNCTION toString RETURN varchar2 , MEMBER FUNCTION toArray RETURN IntegerArray_1 , MEMBER FUNCTION getKeyPosition (key INTEGER ) RETURN integer ) ; --通过Hash算法获取hash值 / CREATE OR REPLACE TYPE BODY IntegerSet_gdb AS CONSTRUCTOR FUNCTION IntegerSet_gdb RETURN SELF AS RESULT AS i integer ; BEGIN self.numChains := 11; self.numEntries := 0; self.loadFactor := 0.75; self.threshold := floor (self.numChains * self.loadFactor ); self.cachedChain := 0; self.cachedChainPos := 0; self.chains := IntegerarrayArray (); self.chains.extend (self.numChains ); RETURN; END; MEMBER PROCEDURE put (k INTEGER ) AS pos integer ; newChains IntegerarrayArray ; BEGIN IF self.numEntries > self.threshold THEN  --对超出阈值进行处理 self.numChains := self.numChains * 2; self.threshold := floor (self.numChains * self.loadFactor ); newChains := IntegerarrayArray (); newChains.extend (self.numChains ); FOR i IN 1..self.chains.count LOOP IF self.chains (i ) IS NOT NULL THEN FOR j IN 1..self.chains (i ).count LOOP IF self.chains (i )(j ) IS NOT NULL THEN pos := getKeyPosition (self.chains (i )(j )); IF newChains (pos ) IS NULL THEN newChains (pos ) := IntegerArray_1 (); END IF; newChains (pos ).extend; newChains (pos )(newChains (pos ).count) := self. chains (i )(j ); END IF; END LOOP; END IF; END LOOP; self.chains := newChains ; self.put (k ); END IF; pos := getKeyPosition (k ); --获取hash值   IF self.chains (pos ) IS NOT NULL THEN FOR i IN 1..self.chains (pos ).count LOOP IF self.chains (pos )(i ) = k THEN RETURN; END IF; END LOOP; FOR i IN 1..self.chains (pos ).count LOOP IF self.chains (pos )(i ) IS NULL THEN self.chains (pos )(i ) := k ; self.numEntries := self.numEntries + 1; --总个数+1 RETURN; END IF; END LOOP; self.chains (pos ).extend; self.chains (pos )(self.chains (pos ).count) := k ;  --放入value self.numEntries := self.numEntries + 1; ELSE self.chains (pos ) := IntegerArray_1 (); self.put (k ); END IF; END; MEMBER FUNCTION get (k INTEGER ) RETURN boolean AS pos integer ; i integer ; BEGIN pos := getKeyPosition (k ); IF self.chains (pos ) IS NOT NULL THEN FOR i IN 1..self.chains (pos ).count LOOP IF self.chains (pos )(i ) = k THEN RETURN TRUE; END IF; END LOOP; END IF; RETURN FALSE; END; MEMBER PROCEDURE clear AS oldNumChains integer ; BEGIN self.numEntries := 0; oldNumChains := self.numChains ; self.numChains := 11; self.chains.trim (self.numChains - oldNumChains ); self.threshold := floor (self.numChains * self.loadFactor ); FOR i IN 1..self.chains.count LOOP IF ( self.chains (i ) IS NOT NULL) THEN self.chains (i ).delete; END IF; END LOOP; END; MEMBER PROCEDURE remove (k INTEGER ) AS pos integer ; i integer ; BEGIN pos := getKeyPosition (k ); IF self.chains (pos ).count IS NOT NULL THEN FOR i IN 1..self.chains (pos ).count LOOP IF self.chains (pos )(i ) = k THEN self.chains (pos )(i ) := NULL; self.numEntries := self.numEntries - 1; END IF; END LOOP; END IF; END; MEMBER FUNCTION getNumEntries RETURN integer AS BEGIN RETURN self.numEntries ; END; MEMBER FUNCTION isEmpty RETURN boolean AS BEGIN IF self.getNumEntries () = 0 THEN RETURN TRUE; ELSE RETURN FALSE; END IF; END; MEMBER FUNCTION getByIndex (self IN OUT IntegerSet_gdb , idx integer ) RETURN INTEGER AS BEGIN IF idx >= 1 AND idx <= self.getNumEntries THEN IF self.cachedChain = 0 OR idx = 1 THEN self.cachedChain := 1; self.cachedChainPos := 0; END IF; FOR i IN self.cachedChain ..self.chains.count LOOP IF self.chains (i ) IS NOT NULL THEN FOR j IN self.cachedChainPos + 1..self.chains (i ).count LOOP IF self.chains (i )(j ) IS NOT NULL THEN self.cachedChainPos := j ; RETURN self.chains (i )(j ); END IF; END LOOP; END IF; self.cachedChainPos := 0; self.cachedChain := self.cachedChain + 1; END LOOP; END IF; END; MEMBER FUNCTION toString RETURN varchar2 AS res VARCHAR2 (32767); BEGIN res := ''; FOR i IN 1..self.chains.count LOOP IF self.chains (i ) IS NOT NULL THEN FOR j IN 1..self.chains (i ).count LOOP IF self.chains (i )(j ) IS NOT NULL THEN res := res || ', ' || TO_CHAR (self.chains (i )(j )); END IF; END LOOP; END IF; END LOOP; res := '{ ' || substr (res , 3) || ' }'; RETURN res ; END; MEMBER FUNCTION toArray RETURN IntegerArray_1 AS res IntegerArray_1 ; BEGIN res := IntegerArray_1 (); FOR i IN 1..self.chains.count LOOP IF self.chains (i ) IS NOT NULL THEN FOR j IN 1..self.chains (i ).count LOOP IF self.chains (i )(j ) IS NOT NULL THEN res.extend ; res (res.count ) := self.chains (i )(j ); END IF; END LOOP; END IF; END LOOP; RETURN res ; END; MEMBER FUNCTION getKeyPosition (key INTEGER ) RETURN integer IS BEGIN RETURN mod (abs (integerIdentity (key )), self.numChains ) + 1; END; END ; /

plsql varchar2varchar2Map

CREATE OR REPLACE TYPE Varchar2Varchar2Map_gdb AS OBJECT
    (chains Vrchr2vrchr2mp1ntryrryArr , numChains integer ,
     numEntries integer , threshold integer , loadFactor float ,
     CONSTRUCTOR FUNCTION Varchar2Varchar2Map_gdb RETURN SELF AS RESULT,
     MEMBER PROCEDURE put (k VARCHAR2 , v VARCHAR2 ),
     MEMBER FUNCTION get (k VARCHAR2 ) RETURN VARCHAR2 ,
     MEMBER PROCEDURE remove (k VARCHAR2 ),
     MEMBER FUNCTION containsKey (k VARCHAR2 ) RETURN boolean ,
     MEMBER FUNCTION getKeys RETURN Varchar2Set_gdb ,
     MEMBER FUNCTION getEntries RETURN Varchar2varchar2map1entrySet ,
     MEMBER FUNCTION getNumEntries RETURN integer ,
     MEMBER FUNCTION isEmpty RETURN boolean , MEMBER PROCEDURE clear,
     MEMBER FUNCTION toString RETURN varchar2 ,
     MEMBER FUNCTION getKeyPosition (key VARCHAR2 ) RETURN integer ) ;
/

CREATE OR REPLACE TYPE BODY Varchar2Varchar2Map_gdb AS
    CONSTRUCTOR FUNCTION Varchar2Varchar2Map_gdb RETURN SELF AS RESULT AS
    i integer ; BEGIN
        self.numChains  := 11;
        self.numEntries  := 0;
        self.loadFactor  := 0.75;
        self.threshold  := floor (self.numChains  * self.loadFactor );
        self.chains  := Vrchr2vrchr2mp1ntryrryArr ();
        self.chains.extend (self.numChains );
        RETURN;
    END;
    MEMBER PROCEDURE put (k VARCHAR2 , v VARCHAR2 ) AS
    pos integer ; newChains Vrchr2vrchr2mp1ntryrryArr ; BEGIN
        IF  self.numEntries  > self.threshold  THEN
            self.numChains  := self.numChains  * 2;
            self.threshold  := floor (self.numChains  * self.loadFactor );
            newChains  := Vrchr2vrchr2mp1ntryrryArr ();
            newChains.extend (self.numChains );
            FOR i IN 1..self.chains.count
            LOOP
                IF  self.chains (i ) IS NOT NULL THEN
                    FOR j IN 1..self.chains (i ).count
                    LOOP
                        IF  self.chains (i )(j ) IS NOT NULL THEN
                            pos  := getKeyPosition (self.chains (i )(j ).k);
                            IF  newChains (pos ) IS NULL THEN
                                newChains (pos ) := Varchar2varchar2map1entryArray ();
                            END IF;
                            newChains (pos ).extend;
                            newChains (pos )(newChains (pos ).count) := self.
                                                                        chains (i )(j );
                        END IF;
                    END LOOP;
                END IF;
            END LOOP;
            self.chains  := newChains ;
            self.put (k , v );
        END IF;
        pos  := getKeyPosition (k );
        IF  self.chains (pos ) IS NOT NULL THEN
            FOR i IN 1..self.chains (pos ).count
            LOOP
                IF  self.chains (pos )(i ).k = k  THEN
                    self.chains (pos )(i ).v := v ; RETURN; END IF;
            END LOOP;
            FOR i IN 1..self.chains (pos ).count
            LOOP
                IF  self.chains (pos )(i ) IS NULL THEN
                    self.chains (pos )(i ) := Varchar2Varchar2Map1Entry_gdb (k ,
                                                                         v );
                    self.numEntries  := self.numEntries  + 1;
                    RETURN;
                END IF;
            END LOOP;
            self.chains (pos ).extend;
            self.
            chains (pos )(self.
                          chains (pos ).count) := Varchar2Varchar2Map1Entry_gdb (k ,
                                                                             v );
            self.numEntries  := self.numEntries  + 1;
        ELSE
            self.chains (pos ) := Varchar2varchar2map1entryArray ();
            self.put (k , v );
        END IF;
    END;
    MEMBER FUNCTION get (k VARCHAR2 ) RETURN VARCHAR2  AS
    pos integer ; i integer ; BEGIN
        pos  := getKeyPosition (k );
        IF  self.chains (pos ) IS NOT NULL THEN
            FOR i IN 1..self.chains (pos ).count
            LOOP
                IF  self.chains (pos )(i ).k = k  THEN
                    RETURN self.chains (pos )(i ).v; END IF;
            END LOOP;
        END IF;
        RETURN NULL;
    END;
    MEMBER PROCEDURE remove (k VARCHAR2 ) AS
    pos integer ; i integer ; BEGIN
        pos  := getKeyPosition (k );
        IF  self.chains (pos ) IS NOT NULL THEN
            FOR i IN 1..self.chains (pos ).count
            LOOP
                IF  self.chains (pos )(i ).k = k  THEN
                    self.chains (pos )(i ) := NULL;
                    self.numEntries  := self.numEntries  - 1;
                END IF;
            END LOOP;
        END IF;
    END;
    MEMBER FUNCTION getKeys RETURN Varchar2Set_gdb  AS
    keys Varchar2Set_gdb ; BEGIN
        keys  := Varchar2Set_gdb ();
        FOR i IN 1..self.chains.count
        LOOP
            IF  self.chains (i ) IS NOT NULL THEN
                FOR j IN 1..self.chains (i ).count
                LOOP
                    IF  self.chains (i )(j ) IS NOT NULL THEN
                        keys.put (self.chains (i )(j ).k); END IF;
                END LOOP;
            END IF;
        END LOOP;
        RETURN keys ;
    END;
    MEMBER FUNCTION getEntries RETURN Varchar2varchar2map1entrySet  AS
    entries Varchar2varchar2map1entrySet ; BEGIN
        entries  := Varchar2varchar2map1entrySet ();
        FOR i IN 1..self.chains.count
        LOOP
            IF  self.chains (i ) IS NOT NULL THEN
                FOR j IN 1..self.chains (i ).count
                LOOP
                    IF  self.chains (i )(j ) IS NOT NULL THEN
                        entries.
                        put (Varchar2Varchar2Map1Entry_gdb (self.chains (i )(j ).k,
                                                        self.
                                                        chains (i )(j ).v));
                    END IF;
                END LOOP;
            END IF;
        END LOOP;
        RETURN entries ;
    END;
    MEMBER FUNCTION containsKey (k VARCHAR2 ) RETURN boolean  AS
    pos integer ; i integer ; BEGIN
        pos  := getKeyPosition (k );
        IF  self.chains (pos ) IS NOT NULL THEN
            FOR i IN 1..self.chains (pos ).count
            LOOP IF  self.chains (pos )(i ).k = k  THEN RETURN TRUE; END IF;
            END LOOP;
        END IF;
        RETURN FALSE;
    END;
    MEMBER FUNCTION getNumEntries RETURN integer  AS
    BEGIN RETURN self.numEntries ; END;
    MEMBER FUNCTION isEmpty RETURN boolean  AS
    BEGIN
        IF  self.getNumEntries () = 0 THEN RETURN TRUE; ELSE RETURN FALSE;
        END IF;
    END;
    MEMBER PROCEDURE clear AS
    oldNumChains integer ; BEGIN
        self.numEntries  := 0;
        oldNumChains  := self.numChains ;
        self.numChains  := 11;
        self.chains.trim (self.numChains  - oldNumChains );
        self.threshold  := floor (self.numChains  * self.loadFactor );
        FOR i IN 1..self.chains.count
        LOOP
            IF  ( self.chains (i ) IS NOT NULL) THEN self.chains (i ).delete;
            END IF;
        END LOOP;
    END;
    MEMBER FUNCTION toString RETURN varchar2  AS
    res VARCHAR2 (32767); BEGIN
        res  := '';
        FOR i IN 1..self.chains.count
        LOOP
            IF  self.chains (i ) IS NOT NULL THEN
                FOR j IN 1..self.chains (i ).count
                LOOP
                    IF  self.chains (i )(j ) IS NOT NULL THEN
                        res  := res  || ', '
                        || self.chains (i )(j ).toString();
                    END IF;
                END LOOP;
            END IF;
        END LOOP;
        res  := '{ ' || substr (res , 3) || ' }';
        RETURN res ;
    END;
    MEMBER FUNCTION getKeyPosition (key VARCHAR2 ) RETURN integer  IS
    BEGIN RETURN mod (abs (djb2 (key )), self.numChains ) + 1; END;
END ;
/

refference

http://blog.csdn.net/vking_wang/article/details/14166593

每天一点点
原文地址:https://www.cnblogs.com/juliazhang/p/5091683.html