Недавно я прочитал этот Документ Работ Разработчика.
Документ - все об определении hashCode()
и equals()
эффективно и правильно, однако я не могу выяснить, почему мы должны переопределить эти два метода.
Как я могу принять решение для реализации этих методов эффективно?
Посмотрите на библиотеку ffmpeg-php. Это единственный простой способ манипулировать видео различных форматов в PHP.
Есть также обертка называется PHP Video Toolkit , вы можете найти его здесь: http://sourceforge.net/projects/phpvideotoolkit/
-121--3565850-Я не думаю, что вы можете сделать совсем то, что вы хотите с MPI. Я программист Fortran, так что потерпите, если мое понимание Си немного шатко. Вы хотите, кажется, передать структуру данных, состоящую из 1 int и 1 последовательности (которые вы передаете, передавая расположение первого символа в последовательности) из одного процесса в другой? Я думаю, что вам придется пройти последовательность фиксированной длины - что, следовательно, должно было бы быть так долго, как любая из последовательностей, которые вы действительно хотите пройти. Зона приема для сбора этих последовательностей должна быть достаточно большой, чтобы принимать все последовательности вместе с их длиной.
Вероятно, вы захотите объявить новый тип данных MPI для ваших структур; Затем их можно собрать и, поскольку собранные данные включают длину последовательности, восстановить полезные части последовательности в приемнике.
Я не уверен в этом, но я никогда не сталкивался с действительно переменной длиной сообщения, как вы, кажется, хотите использовать, и это, по-видимому, чувствует un-MPI-как. Но это может быть что-то реализованное в последней версии MPI, что я просто никогда не спотыкался, хотя, глядя на документацию он-лайн это не кажется так.
-121--4817525-Джошуа Блох говорит на эффективной Java
Вы должны переопределить hashCode () в каждом классе, который переопределяет равно (). Невыполнение этого требования приведет к нарушению общего договора на Object.hashCode (), что не позволит вашему классу нормально функционировать в сочетании со всеми коллекциями на основе хэша, включая HashMap, HashSet и Hashtable.
Попробуем понять это на примере того, что произойдет, если мы переопределим equals ()
без переопределения hashCode ()
и попытаемся использовать Map
.
Скажем, что у нас есть такой класс, и что два объекта MyClass
равны, если их поле
равно (с hashCode ()
и equals ()
, генерируемыми затмением)
public class MyClass {
private final String importantField;
private final String anotherField;
public MyClass(final String equalField, final String anotherField) {
this.importantField = equalField;
this.anotherField = anotherField;
}
public String getEqualField() {
return importantField;
}
public String getAnotherField() {
return anotherField;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((importantField == null) ? 0 : importantField.hashCode());
return result;
}
@Override
public boolean equals(final Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
final MyClass other = (MyClass) obj;
if (importantField == null) {
if (other.importantField != null)
return false;
} else if (!importantField.equals(other.importantField))
return false;
return true;
}
}
Override only equals
Если переопределено только equals
, то при вызове myMap.put(во-первых, someValue)
сначала хэшируется в каком-то сегменте и при вызове myMap.put(во-вторых, thomeOtherValue)
он будет хэширован в каком-либо другом сегменте (поскольку они имеют другой hashCode
). Таким образом, хотя они равны, так как они не хэшируются в одном ведре, карта не может понять это, и оба они остаются на карте.
Хотя нет необходимости переопределять равно ()
, если мы переопределяем hashCode ()
,давайте посмотрим, что произойдет в этом конкретном случае, когда мы знаем, что два объекта MyClass
равны, если их поле
равно, но мы не переопределяем равно ()
.
Override only hashCode
Представьте, что это
MyClass first = new MyClass("a","first");
MyClass second = new MyClass("a","second");
Если переопределить только hashCode
, то при вызове myMap.put (first, someValue)
сначала вычисляет hashCode
и сохраняет его в заданном сегменте. Затем при вызове myMap.put (second, someOtherValue)
следует заменить первое на второе в соответствии с Картографической документацией , поскольку они равны (в соответствии с бизнес-требованием).
Но проблема заключается в том, что значение равно не было переопределено, поэтому, когда карта хэширует second
и выполняет итерацию в области поиска объекта k
так, что second.equals (k)
является правдой, она не находит ничего, так как second.equals (первый)
будет false
.
Надеюсь, было ясно
Вы должны переопределить hashCode() в каждом класса, который переопределяет equals(). Неспособность сделать это приведет к нарушению общего соглашения для Object.hashCode(), что помешает вашему классу функционировать должным образом в сочетании со всеми основанными на хэше коллекциями, включая HashMap, HashSet и Hashtable.
из Effective Java, by Joshua Bloch
Последовательно определяя equals()
и hashCode()
, вы можете улучшить удобство использования ваших классов в качестве ключей в коллекциях на основе хэшей. Как объясняется в документации API для hashCode: "Этот метод поддерживается в интересах хэш-таблиц, таких как те, которые предоставляются java.util.Hashtable
".
Лучшим ответом на ваш вопрос о том, как эффективно реализовать эти методы, будет предложение прочитать главу 3 книги Effective Java.
newmeths = {
'two': lambda self: 2,
}
class MC(type):
def __init__(cls, name, bases, dict):
for k, v in newmeths.iteritems():
setattr(cls, k, v)
super(MC, cls).__init__(name, bases, dict)
class C(object):
__metaclass__ = MC
pass
c=C()
print c.two()
-121--2953999- Поскольку они не переопределяются, в Object будет использоваться реализация по умолчанию.
Учитывая, что равенство экземпляров и значения hascode обычно требуют знания того, что составляет объект, они, как правило, должны быть переопределены в вашем классе, чтобы иметь какой-либо ощутимый смысл.
-121--530669-Предположим, что у вас есть класс (A), который объединяет два других класса (B) (C), и необходимо сохранить экземпляры (A) внутри хэш-таблицы. Реализация по умолчанию позволяет различать только экземпляры, но не по (B) и (C). Таким образом, два экземпляра A могут быть равны, но по умолчанию нельзя сравнивать их правильным путь.
Проще говоря, метод equals в Object проверяет равенство ссылок, в то время как два экземпляра вашего класса могут быть семантически равны, если их свойства равны. Это, например, важно при помещении объектов в контейнер, использующий equals и hashcode, как HashMap и Set. Допустим, у нас есть класс типа:
public class Foo {
String id;
String whatevs;
Foo(String id, String whatevs) {
this.id = id;
this.whatevs = whatevs;
}
}
Мы создаем два экземпляра с одинаковым id:
Foo a = new Foo("id", "something");
Foo b = new Foo("id", "something else");
Без переопределения equals мы получим:
Правильно? Ну, может быть, если это то, что вам нужно. Но, допустим, мы хотим, чтобы объекты с одинаковым id были одним и тем же объектом, независимо от того, что это два разных экземпляра. Мы переопределим equals (и hashcode):
public class Foo {
String id;
String whatevs;
Foo(String id, String whatevs) {
this.id = id;
this.whatevs = whatevs;
}
@Override
public boolean equals(Object other) {
if (other instanceof Foo) {
return ((Foo)other).id.equals(this.id);
}
}
@Override
public int hashCode() {
return this.id.hashCode();
}
}
Что касается реализации equals и hashcode, я могу порекомендовать использовать вспомогательные методы Guava
Это полезно при использовании Объектов значений . Ниже приводится отрывок из Портлендского репозитория шаблонов :
Примерами объектов значений являются такие вещи , как числа, даты, деньги и строки. Обычно это небольшие объекты, которые используются довольно широко. Их идентичность основана на их состоянии , а не на их идентичности объекта. Таким образом, вы может иметь несколько копий одного и того же объекта концептуальной ценности.
Таким образом, у меня может быть несколько копий объекта , представляющего дату 16 января 1998 года. Любые из этих копий будут равны друг другу. Для небольшого объекта , такого как этот, часто проще создать новые и перемещать их, чем полагаться на один объект для представления Дата.
Объект значения всегда должен переопределять .equals () в Java (или = в Smalltalk). (Не забудьте переопределить .hashCode () как .)
Потому что, если вы не переопределите их, вы будете использовать реализацию по умолчанию в Object.
Учитывая, что равенство экземпляров и значения hascode обычно требуют знания того, что составляет объект, их обычно необходимо переопределить в вашем классе, чтобы они имели какое-либо осязаемое значение.
Оба метода определены в классе Object. И оба они находятся в простейшей реализации. Поэтому, когда вам нужно добавить дополнительную реализацию к этим методам, вы должны переопределить их в своем классе.
Для Ex: метод equals () в объекте проверяет только его равенство по ссылке. Поэтому, если вам нужно сравнить его состояние, вы можете переопределить это, как это сделано в классе String.