Что не так с моими функциями удаления для связанного списка с несколькими картами? - PullRequest
0 голосов
/ 09 февраля 2019

Я реализую мультикарту, используя linkedlist в Java.Но что-то не так с двумя методами удаления и методом замены.Я тестировал все три метода с помощью Junit, и они все прошли, но не смогли пройти грейдер.

В реализации используются два типа узлов:

MapNode: эти узлы будут использоваться для хранения ключей и ссылки на список значений, связанных с этим ключом.

ValueNode: эти узлы будут использоваться для хранения значений, связанных с ключом.

На диаграмме ниже показана структура LinkedList_Multimap.https://imgur.com/a/EUD4DeE

     /* Replaces the entry for the specified key only if currently mapped to the
     * specified value. 
     * 
     * Throws: NullPointerException - if the specified key or
     * oldValue or newValue is null. 
     * IllegalStateException - if the key is not
     * in the multimap, or oldValue is not already associated with key; or if
     * oldValue and newValue are the same.
     *
     * @param key - key with which the specified value is associated
     * @param oldValue - value expected to be associated with the specified key
     * @param newValue  - value to be associated with the specified key
     * @return true if the value was replaced
     */

    @Override
    public boolean replace(K key, V oldValue, V newValue)
    {
        if(key==null || oldValue == null || newValue==null) 
            throw new NullPointerException("Something is null!");

        if(oldValue.equals(newValue))
            throw new IllegalStateException("Old and new values are the same!");

        if(head == null || head.getValues() == null) return false;

        MapNode<K, V> curr = head; 

        while(!curr.getKey().equals(key)){
             if(curr.getNext()==null){  //no existing key               
                 throw new IllegalStateException("The key is not in the multimap!");
             }
             curr = curr.getNext(); 
         }      
        ValueNode<V> currV = curr.getValues();

        if(currV.getValue().equals(oldValue)) {
            ValueNode<V> newV = new ValueNode<>(newValue);
            curr.setValues(newV);
            newV.setNext(currV.getNext());  
            return true; 
        }

        ValueNode<V> preV =null;

        while(!currV.getValue().equals(oldValue)){
            if(currV.getNext()==null){  //no existing old value              
                throw new IllegalStateException("The value is not associated with the key!");
            }
            if(curr.getNext()!= null && curr.getNext().getValues().equals(oldValue)) {
                preV = new ValueNode<>(newValue);
            }

            currV = currV.getNext();
        }  

        ValueNode<V> newV = new ValueNode<>(newValue);
        if(preV==null) {
            curr.setValues(newV);
        }
        else {
            preV.setNext(newV);
        }
        newV.setNext(currV.getNext());      
        return true;
    } 

-> Я получил исключение NullPointerException при замене тестирования.

    /*
     * Removes the mapping for a key from this map if it is present. The key and
     * its associated values are removed. Throws: 
     * NullPointerException - if the
     * specified key is null. 
     * IllegalStateException - if key is not in the
     * multimap
     *
     * @param key
     *            - key whose mapping is to be removed from the multimap
     * @return the head of the list of values mapped to the key or null if the map contained
     *         no mapping for the key
     */    
    @Override
    public ValueNode<V> remove(Object key)
    {
        if(key == null) 
            throw new NullPointerException("The key is null!");

        if(head == null) 
            return null;

        MapNode<K, V> curr = head; 

        if(curr.getKey().equals(key)) {
            head = curr.getNext();
            curr.setNext(null);
            size --;
            return curr.getValues();

        }
        MapNode<K, V> prev = null;
        while(!curr.getKey().equals(key)){
             if(curr.getNext()==null){  //no existing key               
                 throw new IllegalStateException("The key is not in the multimap!");
             }
             if(curr.getNext()!= null && curr.getNext().getKey().equals(key)) {
                prev = curr;
             }
             curr = curr.getNext(); 
        }
        prev.setNext(curr.getNext());
        curr.setNext(null);
        size--;

        return curr.getValues();        
    }

-> Я получил сообщение «ожидается <2>, но было <3>» для проверки удаления ключа.

    /*
     * Removes the entry for the specified key only if it is currently mapped to
     * the specified value. value is removed from the list of values. If value
     * is the only value associated with key, then key is also removed. 
     * Throws:
     * NullPointerException - if the specified key or value is null.
     * IllegalStateException - if key is not in the multimap.
     *  key is not removed if it is not mapped with value
     *
     * @param key
     *            - key with which the specified value is associated
     * @param value
     *            - value expected to be associated with the specified key
     * @return true if the value was removed.
     */
    @Override
    public boolean remove(Object key, Object value)
    {

        if(key == null || value == null) 
            throw new NullPointerException("The key or the value is null!");
        if(head == null) 
            return false;

        MapNode<K, V> curr = head;      

        while(!curr.getKey().equals(key)){
             if(curr.getNext()==null){  //no existing key               
                 throw new IllegalStateException("The key is not in the multimap!");
             }             
             curr = curr.getNext(); 
        }
//      if(curr.getValues()==null) 
//          return false;

        ValueNode<V> currV = curr.getValues();
        ValueNode<V> preV = null;

        if(currV.getValue().equals(value)) {
            if(currV.getNext()==null) {
                remove(key);    
                return true;

                }
            curr.setValues(currV.getNext());
            currV.setNext(null);        
            return true;
        }
        while (!currV.getValue().equals(value)) {
            if(currV.getNext()==null)
                return false; 
            if( currV.getNext()!= null && currV.getNext().getValue().equals(value))
                preV = curr.getValues();
            currV = currV.getNext();
        }   
        preV.setNext(currV.getNext());
        currV.setNext(null);  


        return true;    
    }

-> Я получил сообщение "ожидаемый <3>, но было <5>" для удаления ключа и проверки значения.

...