Написание простой хэш-карты String с использованием параллельных массивов. Получение нулевого значения для некоторых ключей после перехеширования

В первый раз я получаю коллизию в методе put, т.е. когда hasKey возвращает -1, запускается метод rehashing, и значение, вызвавшее коллизию, переходит в удвоенный массив в, вероятно, пустой слот. Но System.out.println(m.get("1000")); дает мне ноль для некоторых ключей, что означает, что они были потеряны. Я не понимаю, как они могли быть потеряны, потому что в keyArray нет ничего, что могло бы их заменить.

import java.util.*;

public class StringMapParallel implements Iterable<String>{

    private int nButckets = 2000;
    private String[] keyArray = new String[nButckets];
    private String[] valueArray = new String[nButckets];
    private int numberOfEntries = 0;

    public static void main(String[] args) {


        StringMapParallel m = new StringMapParallel();
;
        for (int i = 0; i < 8000; i++) {
            m.put(String.valueOf(i), String.valueOf(i));
        }
        System.out.println(m.get("1000"));


    }



    private void rehashing() {
        if (numberOfEntries > (int) (0.3 * nButckets)) {
            int newBucketsNumber = nButckets * 2;
            String[] newKeyArray = new String[newBucketsNumber];
            String[] newValueArray = new String[newBucketsNumber];

            for (int i = 0; i < keyArray.length; i++) {
                if (keyArray[i] != null) {
                    int index = keyArray[i].hashCode() % newBucketsNumber;
                    newKeyArray[index] = keyArray[i];
                    newValueArray[index] = valueArray[keyArray[i].hashCode() % nButckets];
                }
            }           
            /*
            for (String key: this) {
                int index = key.hashCode() % newBucketsNumber;
                newKeyArray[index] = key;
                if (key == null) System.out.println(key); 
                newValueArray[index] = valueArray[key.hashCode() % nButckets];              
            }
            */
            keyArray = newKeyArray;
            valueArray = newValueArray;
            nButckets = newBucketsNumber;
        }
    }

    public void put(String key, String value) {
        int index = key.hashCode() % nButckets;
        int hasKey = hasKey(index, key);
        if (hasKey == 1) {
            valueArray[index] = value;
        } else if (hasKey == 0){
            keyArray[index] = key;
            valueArray[index] = value;
            numberOfEntries++;
        } else {
            rehashing();
            index = key.hashCode() % nButckets;
            keyArray[index] = key;
            valueArray[index] = value;
            numberOfEntries++;
        }
    }

    public String get(String key) {
        int index = key.hashCode() % nButckets;
        if (hasKey(index, key) == 1) return valueArray[index];
        return null;
    }

    private int hasKey(int index, String key) {
        if (keyArray[index] == null) {
            return 0;
        } else if (keyArray[index].equals(key)) {
            return 1;
        } else {
            return -1;
        }
    }

    public Iterator<String> iterator(){
        Iterator<String> iter = new Iterator<String>() {
            private int currentIndex = 0;
            private int nEntries = 0;

            @Override
            public boolean hasNext() {
                return nEntries < numberOfEntries && numberOfEntries != 0;
            }

            @Override
            public String next() {
                for (int i = currentIndex; i < keyArray.length; i++) {
                    if (keyArray[i] != null) {
                        currentIndex = i + 1;
                        nEntries++;
                        return keyArray[i];
                    }
                }
                return null;
            }
        };
        return iter;
    }

}
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
0
91
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Значение int index = key.hashCode() % nButckets; в вашем алгоритме для ключей 1000 и 6357 одинаково, то есть 1423. Следовательно, ваш алгоритм перезаписывает keyArray[1423]=1000 на keyArray[1423]=6357.

Когда вы печатаете m.get(String.valueOf(1000)), следующий метод get() проверяет наличие index, а также key, поэтому он вернет null. Прочтите комментарий в коде для дальнейшего объяснения.

public String get(String key) {
    //System.out.println(key+" "+ key.hashCode());
    int index = key.hashCode() % nButckets;
    System.out.println(index+"bfb"+hasKey(index, key));
    //hasKey(index, key) would return -1, because key[1423] is 6357, and not 1000 as you expected.
    if (hasKey(index, key) == 1) return valueArray[index]; 
     return null;
}

private int hasKey(int index, String key) {
    //System.out.println(keyArray[index]);
    if (keyArray[index] == null) {
        return 0;
    } else if (keyArray[index].equals(key)) {
        return 1;
    } else {
        return -1;
    }
}

Другие вопросы по теме