1654665420
この記事では、equalsメソッドとハッシュコードのパフォーマンスメトリックについて多くのことを書きました。これらのメソッドのパフォーマンスの問題につながる可能性のあるニュアンスはたくさんあります。問題は、それらのいくつかがうまく隠されている可能性があるということです。
主要な問題を要約すると、ハッシュコードメソッドはJavaコレクションAPIの中心です。具体的には、ハッシュテーブル(具体的にはMapインターフェイスハッシュテーブル)のパフォーマンスを使用します。同じことがequalsメソッドにも当てはまります。文字列オブジェクトやプリミティブよりも複雑なものがある場合、オーバーヘッドはすぐに大きくなる可能性があります。
しかし、主な問題は微妙な振る舞いです。この記事に記載されている例は、JavaSEURLクラスの例です。そのクラスのAPIは、これらの個別のオブジェクトの次の比較がtrueと評価されることを指定しています。
new URL("http://127.0.0.1/").equals(new URL("http://localhost/"));
new URL("http://127.0.0.1/").hashcode() == new URL("http://localhost/").hashcode();
これは仕様のバグです。これはすべてのドメインに適用されるため、ハッシュまたは等しいを実行するにはルックアップが必要であることに注意してください。それは非常に高くつく可能性があります。
ヒント: equals / hashcodeのパフォーマンスは、マップやその他のハッシュベースのコレクションなどのキー値コンテナーでの使用に非常に効率的である必要があります
これらの方法には多くの落とし穴があります。それらのいくつかは、大規模にのみ明らかです。たとえば、友人がオブジェクトを比較し、潜在的な値のリストに外部依存する方法を教えてくれました。これはローカルでは優れたパフォーマンスを発揮しましたが、リストに要素が多い本番環境ではゆっくりと実行されました。
ハッシュ関数の生成が遅いかどうかをどのように判断できますか?
それがハッシュ関数のせいであるとどうやって知るのですか?
ほとんどの目的と目的では、問題がequalsメソッドまたはハッシュコードにあることはわかりません。問題を絞り込む必要があります。サーバープロセスは予想よりも時間がかかり、APMに表示される可能性があります。
APMに表示されるのは、Webサービスのパフォーマンスが遅いことです。Lightrunが提供するメトリクスツールを使用して、それを絞り込むことができます。
注:先に進む前に、Lightrunの基本に精通していて、インストールされていることを前提としています。そうでない場合は、この紹介をチェックしてください。
Lightrunには、いくつかのメトリックタイプを設定する機能が含まれています。
すべてのメトリックで条件を使用できることに注意してください。パフォーマンスのオーバーヘッドが特定のユーザーに影響を与える場合は、その特定のユーザーのみに測定を制限できます。
これで、これらのツールを使用してパフォーマンスの問題を絞り込み、根本的な原因を見つけることができます。たとえば、ここでは、メソッドのこれら2つの行に問題があるかどうかを確認できます。
このtictocを追加すると、次のような定期的なプリントアウトが提供されます。
INFO: 13 Feb 2022, 14:50:06 TicToc Stats::
{
"VetListBlock" : {"breakpointId" : "fc27d745-b394-400e-83ee-70d7644272f3","count" : 33,"max" : 32,"mean" : 4.971277332041485,"min" : 1,"name" : "VetListBlock","stddev" : 5.908043099655046,"timestamp" : 1644756606939 }
}
これらのプリントアウトを確認して、これらの行によって発生するオーバーヘッドの感覚をつかむことができます。カウンターを使用して、メソッドを呼び出す頻度を確認することもできます。
注:これらの結果をPrometheus / Grafanaにパイプして視覚化を向上させることができますが、そのためには、このチュートリアルの範囲外の構成が必要です。
コレクションまたはマップがアプリケーションの主なパフォーマンスの低下として見られる場合は、厄介なハッシュコードまたはequalsメソッドに問題がある可能性があります。この時点で、メソッド自体のメトリックを使用して、そのオーバーヘッドを測定できます。
これは、これらをローカルでデバッグする方法と非常によく似ています。疑わしい領域を測定で囲み、テストを再実行します。残念ながら、このアプローチはアプリの再コンパイル/デプロイが必要なため、時間がかかります。また、本番環境では実用的ではありません。このアプローチを使用すると、すべての「疑わしい」領域をすばやく確認し、それらをすべてすばやく絞り込むことができます。
さらに、タグ機能を使用して、一連のサーバーでこれを行うことができます。このようにして、サーバーをスケーリングするときに測定値をスケーリングできます。
可変オブジェクトは、デバッグ中に複数のスレッドから変更できます。これにより、パフォーマンスの問題と思われる問題が発生する可能性があります。シングルスレッドアクセスがあることを確認することで、クリティカルセクションの同期を減らすこともできます。
たとえば、キー値ストアでは、別のスレッドがキーを変更すると、ストアが破損する可能性があります。
これを行う最も簡単な方法は、現在のスレッドが次の条件を使用して現在のスレッドをログに記録することです{Thread.currentThread().getName()}
。
問題は、このような状態が、追跡が難しい出力をトリガーする可能性があることです。何百ものプリントアウトが表示される可能性があります。したがって、スレッドの名前を見つけたら、条件を追加できます。
!Thread.currentThread().getName().equals("threadName")
これは、異なるスレッドからのアクセスのみをログに記録します。これは、以前の投稿でここで説明したことです。
JavaSEのequalsメソッドとhashcodeメソッドのパフォーマンスメトリックは非常に重要です。これらは、特に呼び出しに関連するキー値において、JavaコレクションAPIに広範囲に影響を及ぼします。オブジェクトはこれを効率的に実装する必要がありますが、多くの場合、障害のあるJavaクラスを特定するのは困難です。
Lightrunメトリックを使用して、本番環境で任意のメソッドの時間を計測できます。「実世界」の環境でクラスのパフォーマンスを測定することが重要です。これは、ローカルのテストケースとは異なる場合があります。オブジェクトは、実稼働規模のデータとは根本的に異なる動作をする可能性があり、クラスへの小さな変更が大きな違いを生む可能性があります。
ハッシュのオーバーヘッドを絞り込み、ログを使用してスレッドの問題を特定し、カウンターを使用してAPIの使用状況を特定できます。
このストーリーは、もともとhttps://talktotheduck.dev/debugging-java-equals-and-hashcode-performance-in-productionで公開されました
1654665180
Escribí mucho sobre las métricas de rendimiento del método equals y el código hash en este artículo . Hay muchos matices que pueden conducir a problemas de rendimiento en esos métodos. El problema es que algunas de esas cosas pueden estar bien escondidas.
Para resumir el problema central: el método hashcode es fundamental para la API de colección de Java. En concreto, con el rendimiento de las tablas hash (en concreto, la tabla hash de la interfaz Map). Lo mismo ocurre con el método de igualdad. Si tenemos algo más complejo que un objeto de cadena o una primitiva, la sobrecarga puede crecer rápidamente.
Pero el principal problema es el comportamiento matizado. El ejemplo dado en el artículo es el de la clase URL de Java SE. La API para esa clase especifica que la siguiente comparación de estos objetos distintos se evaluaría como verdadera:
new URL("http://127.0.0.1/").equals(new URL("http://localhost/"));
new URL("http://127.0.0.1/").hashcode() == new URL("http://localhost/").hashcode();
Este es un error en la especificación. Tenga en cuenta que esto se aplica a todos los dominios, por lo que la búsqueda es necesaria para realizar hash o iguales. Eso puede ser muy costoso.
SUGERENCIA: el rendimiento de equals/hashcode debe ser muy eficiente para su uso en contenedores de valores clave como mapas y otras colecciones basadas en hash
Hay tantas trampas con estos métodos. Algunos de ellos solo serían obvios a escala. Por ejemplo, un amigo me mostró un método que comparaba objetos y tenía una dependencia externa de una lista de valores potenciales. Esto funcionó muy bien localmente pero lentamente en producción donde la lista tenía más elementos.
¿Cómo puede saber si una función hash es lenta en producción?
¿Cómo descubres que es culpa de la función hash?
Para la mayoría de los intentos y propósitos, no sabríamos que el problema está en el método equals o el código hash. Tendríamos que reducir el problema. Es probable que un proceso del servidor tarde más de lo esperado y posiblemente aparezca en el APM.
Lo que veríamos en el APM es el rendimiento lento de un servicio web. Podemos reducir eso usando las herramientas de métricas proporcionadas por Lightrun.
Nota: Antes de continuar, asumo que está familiarizado con los conceptos básicos de Lightrun y lo tiene instalado. Si no es así, consulte esta introducción .
Lightrun incluye la capacidad de establecer varios tipos de métricas:
Tenga en cuenta que puede usar condiciones en todas las métricas. Si la sobrecarga de rendimiento afecta a un usuario específico, puede limitar la medición solo a ese usuario específico.
Ahora podemos usar estas herramientas para reducir los problemas de rendimiento y encontrar la causa raíz, por ejemplo, aquí puedo verificar si estas dos líneas en el método tienen fallas:
Agregar este tictoc nos proporciona impresiones periódicas como esta:
INFO: 13 Feb 2022, 14:50:06 TicToc Stats::
{
"VetListBlock" : {"breakpointId" : "fc27d745-b394-400e-83ee-70d7644272f3","count" : 33,"max" : 32,"mean" : 4.971277332041485,"min" : 1,"name" : "VetListBlock","stddev" : 5.908043099655046,"timestamp" : 1644756606939 }
}
Puede revisar estas impresiones para tener una idea de los gastos generales en que incurren estas líneas. También puede usar el contador para ver la frecuencia con la que invocamos un método.
NOTA: Puede canalizar estos resultados a Prometheus/Grafana para una mejor visualización, pero eso requiere alguna configuración que está fuera del alcance de este tutorial.
Si ve una colección o un mapa como la principal penalización de rendimiento en la aplicación, es muy posible que un código hash descarriado o un método de igualdad tengan la culpa. En este punto, puede usar métricas en el propio método para medir su sobrecarga.
Esto es muy similar a la forma en que a menudo depuramos estas cosas localmente. Rodee un área sospechosa con medidas y vuelva a ejecutar la prueba. Desafortunadamente, ese enfoque es lento ya que requiere volver a compilar/implementar la aplicación. También es poco práctico en la producción. Con este enfoque, podemos revisar rápidamente todas las áreas "sospechosas" y reducirlas rápidamente.
Además, podemos hacer eso en un conjunto de servidores usando la función de etiqueta. De esta forma podremos escalar nuestras medidas a medida que escalamos nuestros servidores.
Los objetos mutables se pueden cambiar desde múltiples subprocesos mientras intentamos depurarlos. Esto podría desencadenar problemas que parecen ser problemas de rendimiento. Al verificar que tenemos acceso de hilo único, también podemos reducir la sincronización en secciones críticas.
Por ejemplo, en un almacén de valores clave, si un subproceso independiente muta la clave, el almacén podría corromperse.
La forma más sencilla de hacer esto es registrar el subproceso actual usando la condición El subproceso actual es: {Thread.currentThread().getName()}
:
El problema es que una condición como esta puede desencadenar una salida que es difícil de seguir, es posible que vea cientos de impresiones. Entonces, una vez que averigüemos el nombre del hilo, podemos agregar una condición:
!Thread.currentThread().getName().equals("threadName")
Esto solo registrará el acceso desde diferentes subprocesos. Esto es algo que discutí en mi publicación anterior aquí .
Las métricas de rendimiento de los métodos equals y hashcode en Java SE son cruciales. Tienen un impacto de gran alcance en la API de recopilación de Java, especialmente en las llamadas relacionadas con los valores clave. Los objetos deben implementar esto de manera eficiente, pero a menudo es difícil determinar la clase de Java que tiene la culpa.
Podemos usar las métricas de Lightrun para cronometrar métodos arbitrarios en producción. Es importante medir el rendimiento de la clase en el entorno del "mundo real", que puede diferir de nuestros casos de prueba locales. Los objetos pueden comportarse de manera radicalmente diferente con los datos de escala de producción, y los cambios menores en una clase pueden marcar una gran diferencia.
Podemos reducir la sobrecarga de hashes, usar registros para determinar problemas de subprocesamiento y usar contadores para determinar el uso de una API.
Esta historia se publicó originalmente en https://talktotheduck.dev/debugging-java-equals-and-hashcode-performance-in-production
1654653900
数週間前、私はredditでこの話に出くわしました。この話では、URLクラスをマップのキーとして使用する際の問題について説明しています。これは、 java.net.URLでのhashcode()メソッドの実装が非常に遅いため、このような状況ではこのクラスを使用できなくなります。残念ながら、これはJava API仕様の一部であり、下位互換性を損なうことなく修正することはできなくなりました。
私たちにできることは、equalsとハッシュコードの問題を理解することです。将来、このような問題をどのように回避できるでしょうか。
これを理解するために、ハッシュコードのJavaDocを見てみましょう。
このURLが他のオブジェクトと等しいかどうかを比較します。
指定されたオブジェクトがURLでない場合、このメソッドはすぐにfalseを返します。
2つのURLオブジェクトは、同じプロトコルを持ち、同等のホストを参照し、ホスト上で同じポート番号を持ち、同じファイルとファイルのフラグメントを持っている場合、等しくなります。
両方のホスト名を同じIPアドレスに解決できる場合、2つのホストは同等であると見なされます。それ以外の場合、どちらかのホスト名を解決できない場合は、大文字と小文字を区別せずにホスト名を等しくする必要があります。または、両方のホスト名がnullに等しい。
ホストの比較には名前解決が必要なため、この操作はブロック操作です。
ホストの比較には名前解決が必要なため、この操作はブロック操作です。」
これは不明確かもしれません。簡単なコードブロックでそれを明確にしましょう:
System.out.println(new URL("http://localhost/").equals(new URL("http://127.0.0.1/")));
System.out.println(new URL("http://localhost/").hashCode() == new URL("http://127.0.0.1/").hashCode());
印刷されます:
true
true
これはローカルホストでは非常に簡単かもしれませんが、ドメインを比較し、文字列が同一でない場合(多くの場合、同一ではありません)、DNSルックアップを実行する必要があります。hashcode()呼び出しのためだけにそれを行う必要があります!
この場合の簡単な回避策は、URLを回避することです。Sunはクラスを元のJVMコードに深く埋め込みましたが、ほとんどの目的でURIを使用できます。
たとえば、ハッシュコードを変更し、URLの代わりにURIを使用するように上記からの呼び出しを等しくすると、次の結果が得られます。
System.out.println(new URI("http://localhost/").equals(new URI("http://127.0.0.1/")));
System.out.println(new URI("http://localhost/").hashCode() == new URI("http://127.0.0.1/").hashCode());
両方のステートメントでfalseになります。これは一部のユースケースでは問題になる可能性がありますが、パフォーマンスには大きな違いがあります。
マップキーとして使用したのが文字列だけであれば、問題ありません。この種のバグは、これらの方法を使用するすべての場所で発生する可能性があります。
しかし、それはさらに深くなります。独自のハッシュコードとequalsロジックを使用して独自のクラスを作成する場合、多くの場合、不正なコードの餌食になる可能性があります。ハッシュコードメソッドまたは過度に単純化されたバージョンでの小さなパフォーマンスペナルティは、追跡が非常に難しい大きなパフォーマンスペナルティを引き起こす可能性があります。
たとえば、ハッシュコードメソッドが遅いか正しくないために時間がかかるストリーム操作は、長期的な問題を表す可能性があります。
最良のハッシュコードとequalsメソッドを理解するには、最初にいくつかの平凡なコードを理解する必要があります。今、私は恐ろしいまたは古いコードを表示しません。これは良いコードですが、最善ではありません。
public int hashCode() {
return Objects.hash(id, core, setting, values, sets);
}
このコードは最初は問題ないように見えるかもしれませんが、そうではありませんか?理想的なコードは次のとおりです。
public int hashCode() {
return id;
}
これは高速で、100%ユニークで正しいです。それ以上のことをする理由は文字通りありません。オブジェクトであるidの例外が1つあります。その場合、代わりにObjects.hashCode(id)を実行することをお勧めします。これは、nullなどでも機能します。
まあ、明らかに…これは、ハッシュコードの実装を作成するときに覚えておく必要がある最も重要なことの1つです。このメソッドは高速に実行する必要があり、falseの場合のequalsと一致している必要があります。trueの場合は正しくありません。
明確にするために、ハッシュコードは常にこの法則に従わなければなりません。
assert(obj1.hashCode() != obj2.hashCode() && !obj1.equals(obj2));
つまり、ハッシュコードの結果が異なる場合、オブジェクトは異なる必要があり、equalsからfalseを返す必要があります。しかし、その逆は当てはまりません。
if(obj1.hashCode() == obj2.hashCode()) {
if(obj1.equals(obj2)) {
// this can be false...
}
}
ここでの価値はパフォーマンスにあります。ハッシュコードメソッドは、equalsよりもはるかに高速に実行されるはずです。これにより、潜在的に高価な等しい計算要素とインデックス要素をすばやくスキップできるようになります。
JPA開発者は、多くの場合、ハッシュコードにハードコードされた値を使用するか、Classオブジェクトを使用してhashCode()を生成します。あなたがこれについて考えるまで、これは奇妙に思えます。
データベースにIDを生成させると、オブジェクトが保存され、ソースオブジェクトと等しくなくなります。1つの解決策は、@NaturalId
注釈とデータ型を使用することです。ただし、それにはデータモデルを変更する必要があります。残念ながら、エンティティクラスには適切な回避策はありません。
実際、JPA開発者がLombokで経験した問題の多くは、Lombokがハッシュコードを生成し、メソッドを同等にするためであると理論付けます。それらは問題になる可能性があります。
その長いセットアップについては申し訳ありませんが、はい、それはよくあります。したがって、より一般的なデバッグの意味でこれについて話すには、そのすべての序文が必要でした。これは、一般的なインターフェイスに同様のパラダイムを使用する他の言語にも当てはまることに注意してください。
このブログはパフォーマンスの問題から始まりました。デバッグの観点からその側面について説明したいと思います。多くのプロファイラーでは、ハッシュコードメソッドのオーバーヘッドはほとんど目立たないでしょう。しかし、それは非常に頻繁に呼び出され、広範囲にわたる影響を与えるため、最終的には影響を感じ、他の場所に責任を負わせる可能性があります。
ひざまずく反応は、「ダミー」ハッシュコードメソッドを実装し、結果として生じるパフォーマンスの違いを確認することです。有効な番号の代わりにハードコードされた番号を返すだけです。
これは場合によっては価値があり、ハッシュコードメソッドのパフォーマンスが悪い上記のような問題を解決することさえあります。ただし、マップには役立ちません。ハッシュコードが同じ値を返す場合、それをマップのキーとして使用すると、ハッシュコードが提供できるすべてのパフォーマンス上の利点が事実上無効になります。
ハッシュコード方式が適切かどうかをどうやって知ることができますか?
ええと…デバッガーを使ってそれを理解することができます。マップを調べて、さまざまなバケット間のオブジェクトの分布を確認するだけで、ハッシュコードメソッドの実際の値を把握できます。
コミット時にコード検証プロセスがある場合は、ハッシュコードメソッドの複雑さレベルでルールを定義することを強くお勧めします。スローコードがに浸透するのを防ぐために、これは非常に低く設定する必要があります。
しかし、問題はネストです。たとえば、前に説明したようなコードについて考えてみましょう。
public int hashCode() {
return Objects.hash(id, core, setting, values, sets);
}
短くてシンプルです。それでも、このコードのパフォーマンスはいたるところにある可能性があります。このメソッドは、すべての内部オブジェクトのハッシュコードメソッドを呼び出します。これらの方法は、パフォーマンスの点ではるかに悪い場合があります。これについては警戒する必要があります。前に説明したように、問題のあるURLなどのJDKクラスの場合でも。
多くの場合、ハッシュコードとequalsメソッドを自動生成します。IDEは通常、それがかなり得意です。比較したいフィールドを選択するオプションが提供されます。残念ながら、それらは両方のフィールドのセットをハッシュコードと等号に適用します。
時々、これは問題ではありません。メソッドが小さすぎてプロファイラーにへこみを作ることができないため、重要な場所を「見る」ことができないことがよくあります。しかし、それらには、最適化する必要のある幅広い影響があります。
デバッグにより、マップを検査してバケットの分布を確認できるため、ハッシュコードメソッドのパフォーマンスと、マップや同様のAPIからより一貫性のある結果を取得するために調整する必要があるかどうかを把握できます。
このストーリーは、もともとhttps://talktotheduck.dev/hashcode-and-equals-debugging-performanceで公開されました
1654653600
Hace unas semanas me encontré con esta historia en reddit que analiza el problema con el uso de la clase URL como clave en un mapa. Esto se reduce a una implementación notablemente lenta del método hashcode() en java.net.URL que hace que esta clase sea inutilizable en tales situaciones. Desafortunadamente, esto es parte de la especificación de la API de Java y ya no se puede reparar sin romper la compatibilidad con versiones anteriores.
Lo que podemos hacer es entender el problema con equals y hashcode. ¿Cómo podemos evitar tales problemas en el futuro?
Para entender esto, veamos el JavaDoc de hashcode y es igual a:
Compara esta URL para la igualdad con otro objeto.
Si el objeto dado no es una URL, este método inmediatamente devuelve falso.
Dos objetos de URL son iguales si tienen el mismo protocolo, hacen referencia a hosts equivalentes , tienen el mismo número de puerto en el host y el mismo archivo y fragmento del archivo.
Dos hosts se consideran equivalentes si ambos nombres de host se pueden resolver en las mismas direcciones IP; de lo contrario, si alguno de los nombres de host no se puede resolver, los nombres de host deben ser iguales sin importar las mayúsculas y minúsculas; o ambos nombres de host iguales a nulo.
Dado que la comparación de hosts requiere resolución de nombres, esta operación es una operación de bloqueo.
Dado que la comparación de hosts requiere resolución de nombres, esta operación es una operación de bloqueo”.
Esto podría no estar claro. Vamos a aclararlo con un simple bloque de código:
System.out.println(new URL("http://localhost/").equals(new URL("http://127.0.0.1/")));
System.out.println(new URL("http://localhost/").hashCode() == new URL("http://127.0.0.1/").hashCode());
Imprimirá:
true
true
Esto puede ser bastante simple con localhost, pero si comparamos dominios y las cadenas no son idénticas (que a menudo no lo son), necesitamos hacer una búsqueda de DNS. ¡Necesitamos hacer eso solo para una llamada hashcode()!
Una solución rápida para este caso es evitar la URL. Sun incrustó profundamente la clase en el código JVM original, pero podemos usar URI para la mayoría de los propósitos.
Por ejemplo, si cambiamos el código hash e igualamos las llamadas desde arriba para usar URI en lugar de URL, obtendremos este resultado:
System.out.println(new URI("http://localhost/").equals(new URI("http://127.0.0.1/")));
System.out.println(new URI("http://localhost/").hashCode() == new URI("http://127.0.0.1/").hashCode());
Obtendremos falso para ambas declaraciones. Si bien esto puede ser problemático para algunos casos de uso, es una gran diferencia en el rendimiento.
Si todo lo que alguna vez usamos como clave de mapa fueran cadenas, estaríamos bien. Este tipo de error puede afectarnos en todos los lugares donde usamos estos métodos:
Pero se vuelve más profundo. Al escribir nuestras propias clases con nuestro propio código hash y lógica igual, a menudo podemos ser víctimas de un código incorrecto. Una pequeña penalización de rendimiento en un método de código hash o una versión demasiado simplista puede causar importantes penalizaciones de rendimiento que serían muy difíciles de rastrear.
Por ejemplo, una operación de flujo que lleva más tiempo porque el método hashcode es lento o incorrecto puede representar un problema a largo plazo.
Para comprender el mejor método hashcode y equals, primero debemos comprender un código mediocre. Ahora no mostraré un código horrible o antiguo. Este es un buen código, pero no es el mejor:
public int hashCode() {
return Objects.hash(id, core, setting, values, sets);
}
Este código puede parecer correcto al principio, pero ¿lo es? Aquí está el código ideal:
public int hashCode() {
return id;
}
Esto es rápido, 100% único y correcto. Literalmente no hay razón para hacer nada más allá de eso. Hay una excepción de una identificación que es un objeto. En ese caso, podríamos querer hacer Objects.hashCode(id) en su lugar, que también funcionará para nulo, etc.
Bueno, obviamente... Esta es una de las cosas más importantes que debe tener en cuenta al escribir una implementación de código hash. Este método debe funcionar rápido y debe ser consistente con iguales para el caso falso. No será correcto para el caso de verdadero.
Para aclarar, el código hash siempre debe obedecer esta ley:
assert(obj1.hashCode() != obj2.hashCode() && !obj1.equals(obj2));
Eso significa que si los resultados del código hash son diferentes, los objetos deben ser diferentes y deben devolver falsos de iguales. Pero lo contrario no es el caso:
if(obj1.hashCode() == obj2.hashCode()) {
if(obj1.equals(obj2)) {
// this can be false...
}
}
El valor aquí está en el rendimiento. Un método hashcode debería funcionar mucho más rápido que sus iguales. Debería permitirnos omitir rápidamente el cálculo de equivalencias potencialmente costoso y los elementos de índice.
Los desarrolladores de JPA a menudo solo usan un valor codificado para el código hash o usan el objeto Class para generar el hashCode(). Esto parece raro hasta que piensas en esto.
Si permite que la base de datos genere la ID por usted, guardaría un objeto y ya no sería igual al objeto de origen... Una solución es usar los @NaturalId
tipos de anotación y datos. Pero eso requeriría cambiar el modelo de datos. Desafortunadamente, no existe una solución decente para las clases de entidad.
De hecho, teorizaría que muchos de los problemas que los desarrolladores de JPA experimentaron con Lombok se deben a que genera códigos hash y métodos iguales para usted. Esos podrían ser problemáticos.
Perdón por esa larga configuración, pero sí, muy bien lo es. Así que necesitaba todo ese prefacio para hablar de esto en un sentido más genérico de depuración. Tenga en cuenta que esto es cierto para otros lenguajes que usan paradigmas similares para interfaces comunes.
Este blog comenzó con un problema de rendimiento y me gustaría discutir ese aspecto desde el punto de vista de la depuración. En muchos generadores de perfiles, la sobrecarga de un método hashcode sería casi imperceptible. Pero debido a que se invoca con tanta frecuencia y tiene implicaciones de gran alcance, es posible que finalmente sienta las repercusiones y culpe a otros.
La reacción instintiva sería implementar un método de código hash "ficticio" y ver la diferencia de rendimiento resultante. Simplemente devuelva un número codificado en lugar de un número válido.
Esto es valioso para algunos casos e incluso podría resolver problemas como el mencionado en la parte superior donde el método hashcode funciona mal. Sin embargo, no ayudará con los mapas. Si el código hash arrojara valores idénticos, usarlo como clave en un mapa deshabilitaría efectivamente todos los beneficios de rendimiento que puede ofrecer el código hash.
¿Cómo sabemos si un método hashcode es bueno?
Bueno... Podemos usar el depurador para resolverlo. Simplemente inspeccione su mapa y mire la distribución de los objetos entre los distintos cubos para tener una idea del valor real del método hashcode.
Si tiene un proceso de verificación de código en la confirmación, le recomiendo que defina una regla en el nivel de complejidad de un método hashcode. Esto debe configurarse muy bajo para evitar que se filtre código lento.
Pero el problema es anidar. Por ejemplo, piense en un código como el que discutimos antes:
public int hashCode() {
return Objects.hash(id, core, setting, values, sets);
}
Es corto y simple. Sin embargo, el rendimiento de este código puede estar por todas partes. El método invocaría el método hashcode de todos los objetos internos. Estos métodos pueden ser mucho peores en términos de rendimiento. Tenemos que estar atentos a esto. Incluso para clases JDK como URL que, como discutimos anteriormente, es problemática.
A menudo generamos automáticamente código hash y métodos iguales. Los IDE normalmente son bastante buenos en eso; nos ofrecen la opción de elegir los campos que deseamos comparar. Desafortunadamente, luego aplican ambos conjuntos de campos a hashcode y equals.
A veces, esto no importa. A menudo, no "vemos" los lugares donde realmente importa, ya que los métodos son demasiado pequeños para hacer mella en el generador de perfiles. Pero tienen implicaciones de gran alcance para las que debemos optimizar.
La depuración nos permite inspeccionar el mapa y ver la distribución de depósitos para que podamos tener una idea de qué tan bien está funcionando nuestro método de código hash y si debemos ajustarlo para obtener resultados más consistentes de mapas y API similares.
Esta historia se publicó originalmente en https://talktotheduck.dev/hashcode-and-equals-debugging-performance
1628044440
hashcode() in java, overriding hashcode java, how hashcode is calculated in Java,object class in java, what is hashcode in java, hashcode and equals method in java
hashcode java,hashcode and equals in java,object equals method java,important topics in java,hashcode and equals contract in java,java object class methods
java important interview questions,java beginner tutorial,java collection tutorial for beginners
The 'hashcode and equals contract in java’ is one of the most favorite questions in the java interview room. This question is also very important to test candidates collection fundamental as the hash-based collections like HashSet , hashtable, hashmap etc uses hashcode() and equals() to get its task done. So let’s understand the hashcode() and equals() from object class(java.lang.object) step by step.
This is part 1 of the ‘hashcode and equals series’ and we will only be talking about hashcode in this video and in the next video we will move to the equals method in java.
This tutorial based on the focus on the following topics.
1 hashcode() description
2 Understanding native åmethod in java
3 Understanding the hashcode calculation
4 Overriding hashcode method of Object class
5 Creating custom hashcode method
6 Key points of hashcode()
For more videos, consider subscribing by clicking the link below.
https://www.youtube.com/channel/UCpUYkSDJpHug-vfC5S-NXRA?sub_confirmation=1
Stay tuned and like my Facebook page for more.
https://www.facebook.com/seleniumexpress/
credits : -
(intro)
Adventures by A Himitsu https://soundcloud.com/a-himitsu
Creative Commons — Attribution 3.0 Unported— CC BY 3.0
http://creativecommons.org/licenses/b…
Music released by Argofox https://youtu.be/8BXNwnxaVQE
Music provided by Audio Library https://youtu.be/MkNeIUgNPQ8
intro template :
www.youtube.com/Alexbau01
#java #hashcode
1627409580
Why string is immutable in java is one of the frequently asked interview questions.In the last video, we have covered why string is immutable in string pool point of view.In case you have missed that out you can watch this at the below link
Like string class, String class hashcode() is also special.String class hashcode method compute hashcode only one time and then cached in the string object header forever.In this video, we are going to see this in detail.
Well now a most important question, how is this hashcode caching of string helping us? Well, string is immutable in java, this confirms that the content of the object will not change.If so then there is no meaning of calculating the string hashcode again and again as JVM internally uses string characters to calculate the hashcode. So if the string content is not going to change as it’s immutable, then the hashcode is not going to change.
In this way String caching help us to perform a faster operation with a hash-based collection like hashmap, HashSet where there is need of calculating the hashcode again and again.So string used popularly as a key in the hashmap.
So a Note here: The hashcode method of string class in java run for only one time, calculate the hashcode then cached it in the string object header.
So when it comes to "string in java interview questions”, This topic has so much weight.So let’s explore more with this tutorial and the get the answers to the below questions :
1)What is string hashcode caching?
2)Why is String used as a key in hashmap?
3)What is the benefits string hashcode caching and how they help them hash-based collections.
4)And the most important question, Why string is immutable in java?
In case you might be wanted to know how the hashmap works internally, I have already videos available for this which will beneficial to understand this tutorial.Find it at the below link :
https://www.youtube.com/playlist?list=PL3NrzZBjk6m9do1opOKwx_C7d2HRJzpwG
subscribe to my channel by clicking on the link below.
https://www.youtube.com/channel/UCpUYkSDJpHug-vfC5S-NXRA?sub_confirmation=1
Stay tuned and like my Facebook page for more.
https://www.facebook.com/seleniumexpress/
credits : -
(intro)
1)
Adventures by A Himitsu https://soundcloud.com/a-himitsu
Creative Commons — Attribution 3.0 Unported— CC BY 3.0
http://creativecommons.org/licenses/b…
Music released by Argofox https://youtu.be/8BXNwnxaVQE
Music provided by Audio Library https://youtu.be/MkNeIUgNPQ8
Music by Kevin MacLeod. Available under the Creative Commons Attribution 3.0 Unported license: http://creativecommons.org/licenses/b… Download link: https://incompetech.com/music/royalty…
intro template :
wwww.youtube.com/Alexbau01
#java #hashcode