в Java hashTable.hashCode() всегда возвращает 0

417
06 августа 2017, 06:49

Есть структура(класс).

    public class Node {
        private static String separator = "\\";
        private Map<String, Node> fileMap = new HashMap<>();
        private Node parent;
        private String absolutePath;
        private Integer hash;
        public void addFile(File file) {
        fileMap.put(file.getAbsolutePath(), new Node(file.getAbsolutePath(), this));
            hash = hashCode();
        }
        public Node(String absolutePath, Node parent) {
            this.absolutePath = absolutePath;
            this.parent = parent;
        }
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Node)) return false;
        Node node = (Node) o;
        if (getFileMap() != null ? !getFileMap().equals(node.getFileMap()) : node.getFileMap() != null) return false;
        return getAbsolutePath().equals(node.getAbsolutePath());
    }
    @Override
    public int hashCode() {
        boolean eq = getFileMap() != null;
        int result;
        if (eq){
            result = getFileMap().hashCode();
            result += 0;
        } else
            result = 0;
        result = 31 * result + getAbsolutePath().hashCode();
        return result;
    }

Данная структура используется для представление иерархии файловой системы. То есть node может содержать сам файл, так и hashTable (fileMap) с вложенными файлами, если это директория, также файлы в hashTable (fileMap) могут быть файлами или директориями.

Специально переопределил метод hashCode() через if для наглядности. Строка result = getFileMap().hashCode(); всегда возвращает 0, сколько бы разных сущностей в ней не было. В итоге hash считается только от параметра "absolutePath". Что меня не устраивает, ведь мне нужно, чтобы хэш был разным в зависимости от вложенных файлов. Иначе получается ситуация в которой, два дерева представляющих файловую систему, например:

testdir/innerdir/1/2

testdir/outdir

и содержащие одинаковую папку в root - "testdir" равны, т.к. хэш вложенных структур в hashTable не учитывается. Может кто-нибудь сказать Почему так происходит?

Answer 1

Если посмотреть в исходный код HashMap (точнее его родителя AbstractMap),то можно увидеть как реализовано метод hashCode().Он суммирует хеш коды всех элементов:

public int hashCode(){
    int h=0;
    Iterator<Entry<K, V>>i=entrySet().iterator();
    while(i.hasNext())
        h+=i.next().hashCode();
    return h;
}

Далее смотрим как реализуют этот метод элементы HashMap - HashMapEntry:

public final int hashCode() {
    return Objects.hashCode(getKey()) ^ Objects.hashCode(getValue());
}

Здесь используется исключающее ИЛИ для хешкодов ключа и значения. То есть, если хешкоды ключа и значение будут равны, то метод вернёт 0.

В итоге получаем, что когда getFileMap() == null, то для этого Node хешкод берётся от getAbsolutePath(). Этот же getAbsolutePath() является ключём в мапе, получается, что хешкоды ключа и значения равны, отсюда и возвращается 0.

READ ALSO
Получить местоположение [дубликат]

Получить местоположение [дубликат]

На данный вопрос уже ответили:

209
Как из кнопочного телефона с делать камеру [требует правки]

Как из кнопочного телефона с делать камеру [требует правки]

help me пожалуйста я очень долго мучаюсь помогите кто знает

256
Поиск и определение участка кода в котором происходит утечка памяти

Поиск и определение участка кода в котором происходит утечка памяти

Вопрос общего характера - как найти утечку памяти? Есть ли какие нибудь хорошие гайды? Можно на английскомБиблиотеку leack canary не советуйте,...

238