2016-02-29 2 views
0

В моей программе java у меня есть карта с корреляцией между someID и объектом данных типа MyClass.Как я могу реализовать асимметричный эквивалент funciton?

ConcurrentMap<Integer, MyClass> a; 

Реже, но регулярно, я должен проверить, содержит ли один из объектов «значение» определенный длинный переменный b. Поскольку я не знаю корреляции someId с моим другим, я не могу получить к нему доступ через карту. Для этого я хотел бы использовать containsValue:

a.containsValue(otherId) 

Для достижения этой цели я переписал в хэш-код и функция равна.

@Override 
public boolean equals(Object o) { 
    if ((o instanceof MyClass) && (((MyClass) o).someId().equals(this.someId()))) { 
     return true; 
    } else 
    if ((o instanceof Long) && ((Long) o) == this.otherId) { 
     return true; 
    } else { 
     return false; 
    } 
} 

ПРИМЕЧАНИЕ: Иначе в коде необязательно должен быть некоторый идентификатор карты.

Первый оператор if симметричен, второй, очевидно, нет. Я понимаю, что это нехорошо, но писать петлю каждый раз тоже не приятно. В this post говорят, что асимметричные равенства будут игнорироваться. Как я могу заставить java игнорировать проблему асимметрии?

+0

равно должен быть симметричным по определению, и в этом случае вы не можете сделать это «игнорировать» проблема потому что вы не можете изменить класс 'Long'. если ваш ключ может быть «Длинным», просто сделайте его длинным. –

+0

Вызов 'containsValue' на карте следует избегать, где это возможно, так как это операция' O (n) '. –

ответ

4

Это вы используете Java-8, это не очень трудно написать:

a.values().stream().anyMatch(myObj -> myObj.otherId() == wantedId); 
2

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

Занятия в Java API (и в более общем плане) реализованы так, чтобы ожидать, что это свойство будет удерживаться, и поэтому оно может вести себя непредсказуемо, если вы намеренно нарушаете контракт.

Добавить новый метод для ваших классов, который явно предназначен для тестирования этого свойства ассиметрических объектов, например. compareAssymetrically.

2

Проблема с equals реализации является то, что для Long экземпляра l и MyClass например m, m.equals(l) может вернуться в то время как истинный l.equals(m) всегда будет возвращать false, так как вы не можете изменить Long «s осуществление equals.

Если вы используете какие-либо классы, которые используют equals (ArrayList, HashMap, и т.д ...) вы не можете контролировать, будет ли m.equals(l) или l.equals(m) называются, так что ваш код не может вести себя, как вы хотите, чтобы вести.

Если вы хотите, чтобы проверить, если Long является «равно» к MyClass например, создать MyClass экземпляр которого otherId равно, что Long, и сравнить эти два MyClass экземпляров.

@Override 
public boolean equals(Object o) { 
    if (o instanceof MyClass) { 
     MyClass m = (MyClass) o; 
     if (m.someId().equals(this.someId())) { 
      return true; 
     } else if (m.otherId == this.otherId) { 
      return true; 
     } else { 
      return false; 
     } 
    } 
    return false; 
} 

public boolean equals(Long l) { 
    MyClass m = new MyClass(); 
    m.setOtherId(l); 
    return equals(m); 
} 
+0

Я считаю, что ваш ответ технически правильный ответ на мои вопросы и путь. Я принял ответ Тагира, потому что это то, что я сейчас использую. – Jochen

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