2016-03-24 1 views
0

Мне интересно, если реализация ZonedDateTime.hashCode() будет соответствовать ZonedDateTime.isEqual(...)? Если нет, тогда как можно вычислить такой хэш-код?Is ZonedDateTime hashCode() В соответствии с isEqual()?

EDIT

ВНИМАНИЕ, что этот вопрос о методе isEqual, а не о equals. Это не опечатка в моем вопросе.

EDIT # 2

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

public class Foo { 
    private ZonedDateTime dateTime; 

    @Override 
    public boolean equals(Object obj) { 
     // Boilerplate stuff here... 
     final Foo other = (Foo)obj; 
     return (... && dateTime.isEqual(other.dateTime) && ...); 
    } 

    @Override 
    public int hashCode() { 
     // What do I need to put here so that my implementation of 
     // hashCode is consistent with my implementation of equals? 
     return Objects.hashCode(..., dateTime.?, ...); 
    } 
} 

Как вы можете видеть в реализации, я называю isEqual метод в моей реализации equals, так как я хочу два объекта считаются равными, если запомненные раз указывают на в тот же миг. Что я могу включить в свою реализацию hashCode, так что класс Foo соответствует требованию, чтобы hashCode соответствовал equals?

+0

У вас есть основания думать иначе? Если это так, оно должно быть надлежащим образом задокументировано. – Tunaki

+0

Вам действительно нужно объяснить, почему вы думаете, что это может быть так. В противном случае вопрос, скорее всего, не соответствует теме StackOverflow. –

+0

@fge Нет, спецификация языка гарантирует, что метод 'hashCode' совместим с' equals'. Я спрашиваю, совместим ли он с другим методом, называемым ['isEqual'] (https://docs.oracle.com/javase/8/docs/api/java/time/chrono/ChronoZonedDateTime.html#isEqual-java .time.chrono.ChronoZonedDateTime-), который производит другой результат, равный 'equals'. Это два разных вопроса. –

ответ

3

isEqual() метод Javadoc говорит

Это эквивалентно использованию dateTime1.toInstant().equals(dateTime2.toInstant());.

Поэтому, если вы хотите рассчитать хэш-код, соответствующий этому методу, вам нужно будет использовать zdt.toInstant().hashCode(). Тогда ваш Foo.hashCode() будет соответствовать вашему Foo.equals().

+0

Хорошо, моя возвышенность, но тогда возникает вопрос, почему OP работает с 'ZonedDateTime', а не просто с' Instant'? ;-) Жизнь программиста, вероятно, может быть проще без 'ZonedDateTime'. –

+0

@MenoHochschild Я хочу, чтобы публичный интерфейс был выразительным.Когда кто-то получает или устанавливает время, я хочу, чтобы они явно знали/определяли часовой пояс. Мне также нужно сериализовать время на строку формата «yyDDHHmmss» (с неявным часовым поясом UTC). Насколько я могу судить, нет возможности сериализовать/десериализовать мгновение, не пройдя один из классов DateTime. Так что да, я мог бы хранить Instant за кулисами, но должен был бы преобразовать его назад и вперед для публичного интерфейса и сериализации/десериализации. Кажется, что большая часть дополнительной работы для очень мало пользы. –

+1

@JeffG Ну, я признаю, что 'ZonedDateTime' не является моим личным предпочтением, потому что он имеет сильную тенденцию усложнять ситуацию, чем они есть (см. Также весь этот вопрос и ответы). Как показывает мой опыт, комбинации «Instant» и «ZoneId» обычно достаточно, здесь также достаточно для сериализации для строки даты-времени. Вы думаете, что это невозможно, но это - просто настройте форматировщик с информацией о часовом поясе. И 'ZonedDateTime' также потребуется такой форматтер для сериализации (для JSON?). Часто бывает полезно разбить сложные вещи на несколько простых компонентов. –

2

О ваш вопрос о методе isEqual():

Этот метод не имеет ничего общего с Object -методов equals() и hashCode(). Вероятно, лучше переименовать его в isSimultaneous(), чтобы избежать путаницы и сделать мгновенное сравнение. Создание отношения этого метода с аналогичным именем к последовательности с hashCode() бессмысленно.

Конечно, если два ZonedDateTime -Объектов имеют один и тот же момент, то сравнение на основе isEqual() даст true, но хэш-коду часто отличается из-за различные локальные временные метки. Вы можете считать это несоответствием hashCode() с isEqual(), но это не главное.

Метод isEqual() просто не относится ни к какому контексту, в котором вы используете хэш-поиск.

В обратном направлении, метод hashCode() (или любой вычисленный хэш-код) не имеет значения, если вы используете метод isEqual().

Реакция многих downvoters (и мое первое непонимание вашего вопроса и вашего downvote показывает, что существует много путаницы потенциала в том, что оба метода (equals() и isEqual()) звучат так похожи, но имеют совсем другое значение.

+0

@JeffG Хорошо, я уже обновил свой вопрос. –

+0

Итак, я считаю, что ваш ответ можно суммировать так: «Нет,' hashCode' НЕ гарантированно согласуется с 'isEqual'. Это верно? –

+0

@JeffG Я снова отредактировал свой ответ. Не ищите никакой согласованности 'hashCode()' с 'isEqual()'. Яснее теперь для вас? –

1

Читать исходный код двух методов:

  • isEqual method сравнивает ZonedDateTime экземпляров, чтобы увидеть, если они представляют собой один и тот же момент времени (т.е. равные секунды и равные наносекунды с началом эпохи).

  • The hashCode method of ZonedDateTime вычисляется путем XOR-инга hashcodes на dateTime, offset и zone.

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

+1

Хорошо, это отвечает на первую часть моего вопроса. Вы случайно знаете ответ на второй? Например, будет ли 'ZonedDateTime.toInstant(). HashCode()' генерировать хэш-код, согласованный через 'isEqual()'? –

+0

'Instant.hashCode()' вычисляет хэш секунд и наносекунд. Опять же, просто ответил [читает исходный код] (http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8-b132/java/time/Instant.java#1314) , Обратите внимание, что 'Instant' не имеет метода' isEqual'. –

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

  • Нет связанных вопросов^_^