08. Хэш-множество
Если в множестве нужно хранить большие объекты, а не целые числа, то полная проверка на равенство обойдётся слишком дорого.
Лучше для каждого объекта сначала считать некоторую сводную величину, которая будет занимать меньше места и при этом будет равна у равных объектов.
Лучше всего для такого сведения подходят хэш-функции. Сам результат сведения называют хэшем
объекта. В java
хэш-функция всегда возвращает переменную типа int
,
подробнее о хэшах можно прочитать здесь
Такое множество должно хранить два массива: массив ссылок на объекты и массив хэшей. Сначала для нового объекта высчитывается хэш, потом этот хэш ищется в массиве хэшей, для всех индексов, значения которых совпали с хэшем нового объекта, выполняется проверка самих объектов на равенство. Если ни один хэш не совпал, то и объектов, равных новому точно нет.
В данном блоке требуется разработать множество, хранящее строки.
У строк есть готовые методы сравнения .equals()
расчёта хэша .hashCode()
:
public class Main {
public static void main(String[] args) {
String a = "TEST";
String b = "TEST";
String c = "TEST2";
System.out.println(a.equals(b) + " " + b.equals(c));
System.out.println(a.hashCode() + " " + b.hashCode() + " " + c.hashCode());
}
}
На консоль будет выведено:
true false
2571410 2571410 79713760
Задание
Это задание рассчитано на два урока, за него будет выставлено две оценки
На основе множества MySet
из предыдущего задания требуется написать
класс хэш-множества строк MyHashSet
(массив элементов должен хранить строки):
Использовать встроенные коллекции java запрещается. Перед каждой проверкой на равенство должна быть проверка хэшей
- Поле
elements
, в нём должны храниться элементы множества, а также полеelemCnt
, хранящее количество сохранённых элементов. - Конструктор по умолчанию
MyHashSet()
, в нём должен инициализироваться массив строкelements
десятью пустыми строковыми элементами. Количество элементовelemCnt
должно быть равно . - Конструктор копии
MyHashSet(MyHashSet mySet)
, который на основе множества, переданной в аргументе, инициализирует поля копиями полей полученной из аргументов множества String [] getData()
- возвращает копию массиваelements
, но копироваться должны только сохранённые элементы (доelemCnt
)int [] getHashes()
- возвращает копию массива хэшей, но копироваться должны только сохранённые элементы (доelemCnt
)boolean add(String v)
, он должен добавлять новый элемент в множество (в конец массива). При добавлении элементов в множество необходимо добавлять новый элемент в позицию с индексом, равным количеству уже добавленных элементов. Если массив уже полностью заполнен, то необходимо создать новый, в два полтора больший, и скопировать в него все элементы исходного массива. После этого необходимо добавить новый элемент. При добавлении Метод должен увеличивать количество добавленных элементов множества на . Перед добавлением необходимо проверить, нет ли уже такого элемента в множестве. Если такой элемент уже есть, то возвращаетfalse
, иначеtrue
. Первоначальный размер массива элементов должен быть равен двумboolean remove(String v)
- удаляет элемент, равный переданному в аргументах из множества (не только из массива), возвращаетtrue
, если такой элемент был иfalse
, если нетboolean contains(String v)
- возвращаетtrue
, если в множества есть хотя бы один элемент, равный переданному в аргументах иfalse
, если нетboolean addAll(MyHashSet mySet)
- добавляет в множество все элементы множества, переданной в аргументах по той же логике, что иvoid add(int v)
. Возвращаетtrue
boolean containsAll(MyHashSet mySet)
- возвращаетtrue
, если в множества присутствует каждый из элементов переданной в аргументах множестваboolean removeAll(MyHashSet mySet)
- удаляет все элементы, содержащиеся в множествеmySet
возвращаетtrue
, если был удалён хотя бы один элементboolean retainAll(MyHashSet mySet)
- оставляет только те элементы, которые есть вmySet
возвращаетtrue
, если множество было изменено
Все поля и методы должны иметь модификатор public