Страницы

Поиск по вопросам

понедельник, 6 января 2020 г.

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

#java #коллекции #структуры_данных #hashcode


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

    public class Node {
        private static String separator = "\\";
        private Map 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 не учитывается.
Может кто-нибудь сказать Почему так происходит?
    


Ответы

Ответ 1



Если посмотреть в исходный код HashMap (точнее его родителя AbstractMap),то можно увидеть как реализовано метод hashCode().Он суммирует хеш коды всех элементов: public int hashCode(){ int h=0; Iterator>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.

Комментариев нет:

Отправить комментарий