Как сохранить тот же хэш-код, даже несмотря на упорядочение изменения объекта в списке в Java?

#java #hashcode

#java #хэш-код

Вопрос:

 Class A {
   private String test1;
   private String test2;
}

Class Feature {
   private List<A> obj;

   /* 
    HashCode which should return same value even though i change ordering of objects in List
   */
}
 

Текущее поведение:

 > List<A> contains [obj1, obj2, obj3] -> Some hashCode (Ex: 9058203945)
> List<A> contains [obj2, obj1, obj3] -> Some other hashCode (Ex:-23423423)
 

Я хочу, чтобы мой хэш-код списка был таким же, если я изменю порядок элементов в списке.

Любая помощь?

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

Комментарии:

1. Ваш вопрос неясен. Вы говорите о результате hashCode метода on List ?

2. Напишите свой метод хэш-кода таким образом, чтобы порядок элементов не имел значения. Например, возьмите XOR хэш-кодов элементов. Другим способом было бы использовать a Set вместо a List .

3. Хэш-код класса объектов зависит от List<A> хэш-кода, что в основном означает, что вы хотели бы изменить поведение (например) Функция хэш-кода ArrayList, которая невозможна. Вам придется переопределить функцию hashCode вашего класса. Кроме того, заказы обычно имеют значение в хэше. Это действительно плохая практика — не заботиться о заказах в хеш-функции.

Ответ №1:

Не уверен, но я предполагаю, что вы имеете в виду List#hashCode метод.

Упорядочение элементов — это само определение List

Порядок элементов, содержащихся в a List , является основной концепцией списка. Таким образом, изменение порядка приводит к появлению совсем другого списка. Эти два списка концептуально не равны, поэтому они не возвращают и не должны возвращать одно и то же значение хэша (за исключением случайного совпадения, что чрезвычайно редко при использовании приличной хэш-функции).

Технически вы можете создать подкласс List класса и переопределить hashCode метод. Вы можете делать все, что вам нравится, в своем собственном hashCode методе. Но это было бы очень плохой идеей, поскольку это нарушает семантику a List .

Set

Если вас не волнует порядок ваших элементов, вместо этого используйте другую коллекцию List .

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

 Set < DayOfWeek > setX = Set.of( DayOfWeek.TUESDAY , DayOfWeek.WEDNESDAY );
Set < DayOfWeek > setY = Set.of( DayOfWeek.WEDNESDAY , DayOfWeek.TUESDAY );

boolean sameHashCode = ( setX.hashCode() == setY.hashCode() );

System.out.println( "setX.hashCode() = "   setX.hashCode() );
System.out.println( "setY.hashCode() = "   setY.hashCode() );
System.out.println( "sameHashCode = "   sameHashCode );
 

При запуске.

setX.hashCode() = -838114520

setY.hashCode() = -838114520

sameHashCode = true

Это работает в разных реализациях Set .

 Set < DayOfWeek > setX =new TreeSet<>() ;
setX.add( DayOfWeek.TUESDAY);
setX.add( DayOfWeek.WEDNESDAY);

Set < DayOfWeek > setY = new HashSet <>();
setY.add( DayOfWeek.WEDNESDAY );
setY.add( DayOfWeek.TUESDAY );

boolean sameHashCode = ( setX.hashCode() == setY.hashCode() );
 

sameHashCode = true

Это были объекты enum выше. Работает ли это с String объектами? ДА.

 Set < String > setX = new TreeSet <>();
setX.add( "Alice" );
setX.add( "Bob" );
setX.add( "Carol" );

Set < String > setY = new HashSet <>();
setY.add( "Bob" );
setY.add( "Alice" );
setY.add( "Carol" );

boolean sameHashCode = ( setX.hashCode() == setY.hashCode() );
 

sameHashCode = true

Set отличается

Имейте в виду одно существенное различие между Set и List :

  • List позволяет дублировать. Один объект может быть добавлен в список несколько раз и занимать несколько слотов в этом списке.
  • Set запрещает дублирование. A Set отличается, содержит только одну ссылку на какой-либо конкретный объект. Добавление одного конкретного объекта несколько раз не имеет никакого эффекта после первого раза.

Чтобы процитировать Set Javadoc:

Коллекция, которая не содержит повторяющихся элементов. Более формально, наборы не содержат пары элементов e1 и e2, таких, что e1.equals(e2), и не более одного нулевого элемента. Как следует из его названия, этот интерфейс моделирует абстракцию математического множества.

 Set < String > setY = new TreeSet <>();
setY.add( "Jan" );
setY.add( "Marsha" );
setY.add( "Marsha" );
setY.add( "Marsha" );
setY.add( "Cindy" );
 

setY.toString(): [Синди, Ян, Марша]

Комментарии:

1. Хорошо объяснено! Для будущих посетителей эта ссылка может быть полезна для лучшего понимания hashCode и equals методов List .

2. Все мои сомнения устранены, спасибо @Basil Bourque.