SparseArray を使ってみた

今までHashMapを使っていたのだけど、SparseArray のが早いよってlintに言われてたので、少し調べた。
SparseArray は、HashMapと同じような使い方をするが、Keyとなるのがintで、データ件数が100件を超える辺りから早くなるらしい。
詳しいことは
http://thinking-megane.blogspot.jp/2012/06/androidsparsearray.html
にあるので、要点だけ言うと

  • getに関してはHashMapに譲るが、putが早く、put,get合わせると、総合的にSparseArrayが早い

しかも

  • GCの発生頻度が低く、HashMapより優れている

1件のデータに関して1回のput,getというのは乱暴であるが、GC的な観点からいうとSparseArrayの方がいいだろう。
というわけで、書きなおした。(ついでに Utils クラスに移動させた。)


/**
* エリア情報、パス情報を読み込む
*
* @param resources
* @param iPhase
* 面数
*/
public static SparseArray loadPathXML(Resources res, int iPhase) {
// depth が何を表すか
final int S_PHASE = 2;
final int S_PHASE_INFORMATION = 3;
final int S_PATHS = 4;
final int S_PATH = 5;

// 階層構造
SparseArray phaseArray = new SparseArray();

try {
XmlPullParser parser = res.getXml(R.xml.paths);
try {
parser.setInput(res.openRawResource(R.xml.paths), null);
} catch (NotFoundException e) {
Log.e("XML_ERROR 1", e.getMessage());
} catch (XmlPullParserException e) {
Log.e("XML_ERROR 2", e.getMessage());
}

// 階層構造の深さ
int depth = 0;

// mPhaseMap は以下から構成される
int phaseNumber = 0;
Map phaseInformation = null;

// phaseInformation は以下から構成される
String phaseMapName = null;
String phaseMap = null;
String start = null;
String paths = null;

// paths は以下から構成される
String pathsNumber = null;
Map pathsInformation = null;

// pathInformation は以下から構成される
int path = 0;
SparseArray pathInformation = null;

loop: for (int e = parser.getEventType(); e != XmlPullParser.END_DOCUMENT; e = parser
.next()) {
// keyword = new Keyword();

if (e == XmlPullParser.START_DOCUMENT) {
// ドキュメント開始
Log.d("XML:DOC", "START");
} else if (e == XmlPullParser.TEXT) {
// エレメントに囲まれている部分
String text = parser.getText();
Log.d("XML:TEXT", "depth=" + depth + " text=" + text);
switch (depth) {
case S_PHASE: {
break;
}
case S_PHASE_INFORMATION: {
if (phaseMapName != null) {
phaseInformation.put(phaseMapName, text);
phaseMapName = null;
} else if (phaseMap != null) {
phaseInformation.put(phaseMap, text);
phaseMap = null;
} else if (start != null) {
ArrayList arr = Utils.split(",", text);
int x = Integer.valueOf(arr.get(0));
int y = Integer.valueOf(arr.get(1));
phaseInformation.put(start, new Point(x, y));
start = null;
} else if (paths != null) {
phaseInformation.put(paths, text);
paths = null;
}
break;
}
case S_PATHS: {
pathsInformation.put(pathsNumber, text);
break;
}
case S_PATH: {
ArrayList arr = Utils.split(",", text);
int x = Integer.valueOf(arr.get(0));
int y = Integer.valueOf(arr.get(1));
pathInformation.put(path, new Point(x, y));
break;
}
}
} else if (e == XmlPullParser.START_TAG) {
// エレメントの開始
depth++;
Log.d("XML:ELEM", "START " + depth);
// エレメント名
Log.d("XML:ELEM_NAME", parser.getName());

for (int a = 0; a < parser.getAttributeCount(); a++) {
// 属性情報
Log.d("XML:ELEM_ATTR", parser.getAttributeName(a)
+ " = " + parser.getAttributeValue(a));
switch (depth) {
case S_PHASE: {
if (parser.getName().equals("item")
&& parser.getAttributeName(a)
.equals("name")) {
phaseNumber = Integer.valueOf(parser
.getAttributeValue(a));
phaseInformation = new HashMap();
}
break;
}
case S_PHASE_INFORMATION: {
if (parser.getAttributeValue(a).equals("mapName")) {
phaseMapName = parser.getAttributeValue(a);
} else if (parser.getAttributeValue(a)
.equals("map")) {
phaseMap = parser.getAttributeValue(a);
} else if (parser.getAttributeValue(a).equals(
"start")) {
start = parser.getAttributeValue(a);
} else if (parser.getAttributeValue(a).equals(
"paths")) {
pathsNumber = parser.getAttributeValue(a);
pathsInformation = new HashMap();
}
break;
}
case S_PATHS: {
paths = parser.getAttributeValue(a);
pathInformation = new SparseArray();
break;
}
case S_PATH: {
// parser.getAttributeName(a); // name
path = Integer.valueOf(parser.getAttributeValue(a));
break;
}
}
}
} else if (e == XmlPullParser.END_TAG) {
// エレメントの終了
Log.d("XML:ELEM", "END " + depth);
switch (depth) {
case S_PHASE: {
if (phaseNumber == iPhase) {
phaseArray.put(phaseNumber, phaseInformation);
break loop;
}
phaseInformation = null;
break;
}
case S_PHASE_INFORMATION: {
if (paths != null) {
phaseInformation.put(paths, pathsInformation);
paths = null;
pathsInformation = null;
}
break;
}
case S_PATHS: {
pathsInformation.put(pathsNumber, pathInformation);
pathsNumber = null;
pathInformation = null;
break;
}
case S_PATH: {
break;
}
}
depth--;
}
}
} catch (NotFoundException e) {
Log.e("XML", e.getClass().getName() + ": " + e.getMessage());
} catch (XmlPullParserException e) {
Log.d("XML", e.getClass().getName() + ": " + e.getMessage());
for (StackTraceElement s : e.getStackTrace()) {
Log.d("TRACE", s.toString());
}
} catch (IOException e) {
Log.d("XML", e.getClass().getName() + ": " + e.getMessage());
}

return phaseArray;
}