Здравствуйте, я задался вопросом о структуре и работе Map, прочитав несколько статей. Ответы на эти вопросы я не смог найти или упустил при беглом чтении.
у меня есть такой класс ключа
public class KeyClass {
private int firstKeyValue;
private String secondKeyValue;
public KeyClass(int firstKeyValue, String secondKeyValue) {
this.firstKeyValue = firstKeyValue;
this.secondKeyValue = secondKeyValue;
}
public int getFirstKeyValue() {
return firstKeyValue;
}
public void setFirstKeyValue(int firstKeyValue) {
this.firstKeyValue = firstKeyValue;
}
public String getSecondKeyValue() {
return secondKeyValue;
}
public void setSecondKeyValue(String secondKeyValue) {
this.secondKeyValue = secondKeyValue;
}
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (obj == null || obj.getClass() != this.getClass()) {
return false;
}
KeyClass o = (KeyClass) obj;
return (firstKeyValue == o.firstKeyValue) && (secondKeyValue.equals(o.secondKeyValue));
}
@Override
public int hashCode() {
char[] array = secondKeyValue.toCharArray();
int sum = 0;
for(int i = 0; i < array.length; ++i){
sum += array[i];
}
return firstKeyValue + sum;
}
}
и собстна метода main
public class Main {
public static void main(String[] args) {
KeyClass keyClass = new KeyClass(1, "one");
Map map = new HashMap<KeyClass, String>();
//завели бакет по этому ключу(номер бакета определяется по хешу)
map.put(keyClass, "first");
//поменяли ключ(надеемся на потерю значения)
keyClass.setFirstKeyValue(23);
keyClass.setSecondKeyValue(new String("one")); //чтобы даже не в пуле лежала а просто в хипе(чтоб наверняка :в )
//выведет null (так как элемент утерян) Отлично!!!
System.out.println("first value " + map.get(keyClass));
//выведет null (так как такого элемента нет) Отлично!!!
System.out.println("unexisted value " + map.get("str"));
//размер 1 так как элемент все равно внтури (несмотря на то, что он утерян)
//вроде по умолчанию же 16 должен быть??? load factor все дела ?!
System.out.println("size " + map.size());
//кладем в новый бакет(старый с "first" все еще существует)
map.put(keyClass, "alien");
System.out.println("basket with alien" + map.get(keyClass));
//тут я решил посмотреть как будет работать хеш код с учетом неинтернированной строки
System.out.println("hashCode1 : " + keyClass.hashCode());
System.out.println("hashCode2 : " + new KeyClass(23, "one").hashCode());
//хеш одинаковый так как по моему переопределению хешкода место в памяти никак не влияет (ну типа да я так и задумывал)
// но, я в строке использую int значения кодировки символа так что надо рассмотреть следующее
System.out.println("hashCode3 : " + new KeyClass(23, "eno").hashCode()); //ага!!!!!!(хеш такой же)
System.out.println("equals method : "+ new KeyClass(23, "one").equals(new KeyClass(23, "eno"))); //дает false, значит я молодец
//заводим новый бакет
KeyClass anotherOne = new KeyClass(23, "two");
map.put(anotherOne, "new");
//заводим бакет который который будет всегда первым
map.put(null, null);
//значение перетерлось так как hashCode одинаков и equals вернул true
map.put(null, "afterNull");
//тут происходит перетерание по той же причине что и выше, я вообще рассчитывал на лист
map.put(keyClass, "second");
map.put(keyClass, "third");
//и тут поидее я добавляю элемент в бакет с хешом как у keyClass переменной(тоесть "third" и "addToList" должны сформировать лист)
map.put(new KeyClass(23, "eno"), "addToList");
//и тут лежит только third ?!
//Но ведь в случае если хеш одинаковый и equals true, эл-т затирается, а если hash одинаковый но equals false, то создается лист
System.out.println("List : " + map.get(keyClass));
//выведет [afterNull, new, first, third, addToList] но тут мы листа не видим ?!
System.out.println(Arrays.toString(map.values().toArray()));
}
}
1) почему значение длины 1 а не то, которое по умолчанию?
2) верны ли мои рассуждения описанные в комментариях?
3) почему мне так и не удалось получить лист?