#java #коллекции #структуры_данных #hashcode
Есть структура(класс). public class Node { private static String separator = "\\"; private MapfileMap = 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.
Комментариев нет:
Отправить комментарий