2014-02-01 2 views
1

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

Я использую HashMaps в своем приложении. Поэтому я стараюсь сделать свой пользовательский класс byteArray неизменным, поскольку неизменяемые объекты выполняют более быстрый поиск в хэшмапах. (Я хотел бы получить источник этого факта, пожалуйста)

Я уверен, что мой класс неизменен, но он все еще плохо работает против строки в поисках hashmap. Как я могу быть уверен, что он неизменен?

+1

сделать его полей 'final'. Если какие-либо поля имеют тип массива, не делайте их доступными (то же самое для любого другого изменяемого ссылочного типа). –

+4

Почему неизменные объекты в хэшмапах настолько эффективны? http://stackoverflow.com/questions/10342859/why-are-immutable-objects-in-hashmaps-so-effective – alex

+0

Замечание выше хорошее. Вы должны посмотреть на код ответа на вопрос. Он отвечает WHY строк быстрее. Вы должны сделать то же самое в своем коде, чтобы повысить производительность. –

ответ

-1

Посмотрите в методы нередактируемым коллекции документированы http://docs.oracle.com/javase/7/docs/api/java/util/Collections.html

+0

Просто потому, что коллекция неизменна, не означает, что типы данных, которые она содержит, являются. –

+0

Мой комментарий был совершенно не полезен, тогда? – unigeek

2

Самое главное, чтобы скопировать байты в массиве. Если у вас есть

this.bytes = passedInArray;

Вызывающий абонент может изменить passedInArray и, следовательно, изменять this.bytes. Вы должны сделать

this.bytes = Arrays.copyOf(passedInArray, passedInArray.length);

(или аналогичный, клон Годится тоже). Если этот класс будет в основном использоваться в качестве ключа в Картах, я бы сразу вычислил хэш-код (в конструкторе), проще, чем делать это лениво.

Внесите очевидное equals(), и я думаю, что все готово.

+0

Я использую .clone() Это то же самое? Ах, поэтому ваше высказывание вызывает метод myHashCode() в конструкторе, который обновляет конечное поле hashCode int. то в hashCode() переопределенном методе я могу просто вернуть поле hashCode? –

+0

Да, клон должен быть o.k. (должен признать, что я избегаю клонирования, потому что его сложно/сложно использовать во многих случаях). И да, вызовите myHashCode в конструкторе и установите конечное поле. – user949300

2

Ваш вопрос: «Как я могу быть уверенным, что мой класс неизменен?» Я не уверен, что это то, что вы хотите спросить, но способ сделать ваш класс неизменным указан Джошем Блохом в Эффективная Java, 2nd Ed. в пункте 15 here, и которую я буду суммировать в этом ответе:

  1. Не предоставляйте какие-либо методы мутаторных (методы, которые изменяют состояние объекта, обычно называемые «Сеттера»).
  2. Убедитесь, что класс не может быть расширен. Как правило, сделать класс окончательным. Это препятствует другим подклассифицировать его и модифицировать защищенные поля.
  3. Сделайте все поля окончательными, так что вы не можете их изменить.
  4. Сделать все поля закрытыми, чтобы другие не могли их изменить.
  5. «Обеспечить эксклюзивный доступ к изменяемым компонентам». То есть, если что-то еще указывает на данные и, следовательно, может изменить его, сделайте защитную копию (как указал @ user949300).

Обратите внимание, что неизменяемые объекты автоматически не дают большого повышения производительности. Повышение от неизменяемых объектов будет связано с необходимостью блокировки или копирования объекта и повторного использования его вместо создания нового. Я считаю, что поиски в HashMap используют метод класса hashCode(), и поиск должен быть O(c), или постоянным временем и быстротой. Если у вас возникли проблемы с производительностью, вам может потребоваться просмотреть, есть ли медлительность в вашем методе hashCode() (маловероятно) или проблемы в другом месте.

Одним из возможных вариантов, если вы реализовали hashCode() плохо (или не совсем), и это вызывает большое число столкновений в вашем HashMap - то есть, называя этот метод с различными экземплярами своего класса возвращает в основном аналогичны или же значения - тогда экземпляры будут сохранены в связанном списке по адресу, указанному hashCode(). Перемещение этого списка будет конвертировать вашу эффективность с постоянного времени на линейный, делая производительность намного хуже.

+0

# 4 не нужно (если вы делаете # 3), но в остальном все хорошие моменты. – user949300

+0

@ user949300 Истинно, и Блох соглашается с вами, хотя он продолжает отмечать, что лучше всего делать поля частными, поэтому вы можете изменить их внутреннее представление на более поздний срок. – einnocent

0

Поскольку неизменные объекты выполняют более быстрый поиск в хэшмапах. (Я хотел бы получить источник этого факта)

Нет, это неправда. Производительность в качестве ключа hashmap будет определяться временем выполнения и предотвращением столкновений hashCode.

Я уверен, что мой класс неизменен, но он все еще плохо работает против строки в поисках hashmap. Как я могу быть уверен, что он неизменен?

У вашей проблемы, скорее всего, будет плохой выбор hashCode. Подумайте, основываясь на вашей реализации около Arrays.hashCode.

(Ваш вопрос ArrayList<Byte> vs String in Java говорит вы пытаетесь настроить конкретную реализацию, советы там использовать byte[] хорошо.)

+0

Спасибо за ваш ответ и разъяснение. Я написал массив байтовых массивов. Мой метод hashcode читает: hashCode() {return Arrays.hashCode (byteArray); } Я могу себе представить, что это вызывает больше конфликтов, чем должно быть из-за того, что байт подписан. –

Смежные вопросы