配列のインデックスがわかっている場合は、配列またはHashMapを使用する方が(パフォーマンス面で)良いですか?例の「オブジェクト配列/マップ」は単なる例であり、実際のプロジェクトでは別のクラスによって生成されるため、個々の変数を使用できないことに注意してください。
ArrayExample:
SomeObject[] objects = new SomeObject[2];
objects[0] = new SomeObject("Obj1");
objects[1] = new SomeObject("Obj2");
void doSomethingToObject(String Identifier){
SomeObject object;
if(Identifier.equals("Obj1")){
object=objects[0];
}else if(){
object=objects[1];
}
//do stuff
}
HashMapExample:
HashMap objects = HashMap();
objects.put("Obj1",new SomeObject());
objects.put("Obj2",new SomeObject());
void doSomethingToObject(String Identifier){
SomeObject object = (SomeObject) objects.get(Identifier);
//do stuff
}
HashMapの方がはるかに良く見えますが、これを優先するため、私は本当にこれに対するパフォーマンスが必要です。
編集:そうですね、それはアレイです。提案はまだ歓迎されています
編集:言及するのを忘れていました。Array/ HashMapのサイズは常に同じです(6)
編集: HashMapの方が速いようです配列:128msハッシュ:103ms
使用するサイクルが少ない場合、HashMapは2倍の速さでした
テストコード:
import Java.util.HashMap;
import Java.util.Random;
public class Optimizationsest {
private static Random r = new Random();
private static HashMap<String,SomeObject> hm = new HashMap<String,SomeObject>();
private static SomeObject[] o = new SomeObject[6];
private static String[] Indentifiers = {"Obj1","Obj2","Obj3","Obj4","Obj5","Obj6"};
private static int t = 1000000;
public static void main(String[] args){
CreateHash();
CreateArray();
long loopTime = ProcessArray();
long hashTime = ProcessHash();
System.out.println("Array: " + loopTime + "ms");
System.out.println("Hash: " + hashTime + "ms");
}
public static void CreateHash(){
for(int i=0; i <= 5; i++){
hm.put("Obj"+(i+1), new SomeObject());
}
}
public static void CreateArray(){
for(int i=0; i <= 5; i++){
o[i]=new SomeObject();
}
}
public static long ProcessArray(){
StopWatch sw = new StopWatch();
sw.start();
for(int i = 1;i<=t;i++){
checkArray(Indentifiers[r.nextInt(6)]);
}
sw.stop();
return sw.getElapsedTime();
}
private static void checkArray(String Identifier) {
SomeObject object;
if(Identifier.equals("Obj1")){
object=o[0];
}else if(Identifier.equals("Obj2")){
object=o[1];
}else if(Identifier.equals("Obj3")){
object=o[2];
}else if(Identifier.equals("Obj4")){
object=o[3];
}else if(Identifier.equals("Obj5")){
object=o[4];
}else if(Identifier.equals("Obj6")){
object=o[5];
}else{
object = new SomeObject();
}
object.kill();
}
public static long ProcessHash(){
StopWatch sw = new StopWatch();
sw.start();
for(int i = 1;i<=t;i++){
checkHash(Indentifiers[r.nextInt(6)]);
}
sw.stop();
return sw.getElapsedTime();
}
private static void checkHash(String Identifier) {
SomeObject object = (SomeObject) hm.get(Identifier);
object.kill();
}
}
HashMapは下の配列を使用するため、配列を正しく使用するよりも速くなることはありません。
Random.nextInt()
は、arrayを使用して配列をテストしても結果にバイアスがかかる場合でも、テストしているものより何倍も遅くなります。
配列のベンチマークが非常に遅い理由は、配列へのアクセス自体ではなく、等しい比較によるものです。
HashTable
は通常、HashMap
よりもはるかに低速ですが、これは同じことを実行しますが、同期も行われるためです。
マイクロベンチマークの一般的な問題は、何もしないコードの削除に非常に優れているJITです。注意しないと、コードが何も実行しないようにJITを十分に混乱させたかどうかをテストすることになります。
これが、C++システムを実行するマイクロベンチマークを記述できる理由の1つです。これは、Javaがより単純な言語であり、推論しやすく、したがって何も役に立たないコードを検出するためです。これは、Javaが「何も役に立たない」はC++よりもはるかに高速です;)
インデックスがわかっている場合の配列はより高速です(HashMapは、背後でリンクリストの配列を使用します。これにより、実行する必要があるハッシュ操作は言うまでもなく、配列アクセスよりもオーバーヘッドが少し増えます)
そしてFYI HashMap<String,SomeObject> objects = HashMap<String,SomeObject>();
はそれを作るので、キャストする必要はありません
示されている例では、HashTableが勝つと思います。配列アプローチの問題は、スケーリングしないことです。テーブルに3つ以上のエントリが必要で、doSomethingToObjectの条件分岐ツリーが手に負えなくなって遅くなると思います。
論理的には、HashMap
は間違いなくあなたのケースに適しています。配列の場合は(アルゴリズムで)文字列の比較を何回か行う必要があるため、パフォーマンスの観点からもメリットがありますが、HashMapでは、負荷係数が高すぎない場合はハッシュコードを使用するだけです。多くの要素を追加する場合は、配列とHashMapの両方のサイズを変更する必要がありますが、HashMapの場合は、要素も再配布する必要があります。この使用例では、HashMapが失われます。
決して、決して、if if/else if/else if/else if/else if/else if/else if else if that else if。何度も繰り返したのは、Javaインタプリタがそのようなコードブロックにヒットしたときに行うように感じさせるためです。
他に複数ある場合は、ハッシュマップまたはスイッチ/ケースのいずれかを使用します(Java 7では文字列でそれを実行でき、Java 6列挙型を使用する必要があります)読み取り専用チェックのさらに優れたソリューションは、guavaなどのフレームワークからのImmutableMapです。書き込みを許可していないため、読み取りは高度に最適化されています。
配列は通常、コレクションクラスよりも高速です。
PS。投稿でHashTableについて言及しました。 HashTableはHashMapよりもパフォーマンスがさらに悪い。 HashTableについてのあなたの言及はタイプミスだったと思います
「HashTableの方がはるかによく見えます」
例は奇妙です。重要な問題は、データが動的かどうかです。もしそうなら、そのようにプログラムを書くことはできません(配列の場合のように)。つまり、配列とハッシュ実装の比較は公平ではありません。ハッシュ実装は動的データに対して機能しますが、配列実装は機能しません。
静的データ(6つの固定オブジェクト)しかない場合、配列またはハッシュはデータホルダーとして機能します。静的オブジェクトを定義することもできます。