2013-06-24 4 views
1

С этого linkКоллекции перерыв

Название объекты являются неизменяемыми. При прочих равных условиях неизменяемые типы - это путь, особенно для объектов, которые будут использоваться как элементов в наборах или в виде ключей в Картах. Эти коллекции будут разбиты, если вы измените свои элементы или ключи, пока они находятся в коллекции. Как мы узнаем, что класс «Имя» неизменен? (название класса видно по вышеуказанной ссылке)

Что они на самом деле означают, что «коллекции сломаются, если вы измените их элементы?»

Заранее спасибо.

ответ

5

Поскольку с изменяемыми классами вы можете изменить свойства, на основе которых они организованы/упорядочены в Коллекциях, и класс держателя не знал бы об этом.

Подумайте, что вы можете сделать:

public class Name implements Comparable<Name> { 

    private String firstname = null 
    // getters and setters 

    public int compareTo(Name name) { 
     // Compare based in firstName 
    } 
} 

И потом:

Name name1 = new Name("John"); 
Name name2 = new Name("Mike"); 
SortedSet<Name> set = new TreeSet<Name>(); 
set.add(name1); 
set.add(name2); 
name1.setFirstName("Ralph"); 

Теперь, set заказать или нет?

Аналогичным образом, изменения, которые влияют на hashCode экземпляра перерыв HashMap и похожести, потому что первое, что делает эти классы при вставке/извлечения объектов заключается в использовании конкретного bucket на основе этого значения в.

+1

Я думаю, что здесь главное, что оператор относится только к свойствам, которые приписывают методам equals, hascode и compareTo. Другие свойства могут быть изменены без нарушения коллекций. Текст, прерванный в вопросе, является неточным. –

+0

@JoeriHendrickx Если вы определяете 'setter' для любого свойства, тогда вы рискуете, что кто-то будет использовать его в пользовательском' Comparator' для заказа коллекции. Таким образом, вы не можете сказать в общем, что «достаточно, чтобы изменить атрибуты« compareTo/equals/hashCode »не разрешены только атрибуты. – SJuan76

+0

действительно, вы правы. Но, честно говоря, это не такой общий случай. Говорить, что все элементы в коллекции должны быть неизменными, тем не менее будет слишком широким. –

1

Что они означают, поиск по объекту будет провален.

Например:

mylist.get(myObject); 

потерпит неудачу, потому что ссылка на объект вы должны быть разными (в связи с изменениями) от одного, который вы используете, чтобы сделать get(...) вызов.

+0

Фактически для 'List' я ожидал бы, что он будет работать (если только он не отсортирован). – SJuan76

0

Из документов на Map

Примечания: большое внимание должно быть осуществлено, если изменяемые объекты используются в качестве ключей карты. Поведение карты не указывается, если значение объекта изменяется таким образом, который влияет на равные сравнения, пока объект является ключом на карте. Частным случаем этого запрета является то, что карта не может содержать себя как ключ. Хотя допустимо, чтобы карта содержала себя как значение, рекомендуется проявлять особую осторожность: методы equals и hashCode более не определены на такой карте.

Из доков на Set

Примечания: Большое внимание должно быть осуществлено, если изменяемые объекты используются в качестве набора элементов. Поведение набора не указывается, если значение объекта изменяется таким образом, который влияет на равные сравнения, когда объект является элементом в наборе. Особый случай этого запрета состоит в том, что недопустимо, чтобы набор содержал себя как элемент.

Поиск осуществляется с помощью .equals на клавишах, если ключи изменчивы, поиск не удастся.

1

HashSet и HashMap полагаться на контракт на equals() и hashCode описанного в Javadoc для java.lang.Object. Это означает, что для двух объектов, равных equals(), расчетный hashCode() также должен быть равен.

Если hashCode() для объекта в Set или Map изменений во времени объект находится в Set или Map реализации не найти объект, как он сохраняется в ведре для старого hashCode().

Поэтому изменение hashCode() в то время как объект находится в Set или Map - очень плохая идея.

+0

+1 приятный ans .... – Anirudha