11

まず第一に、私が間違っている場合は私を訂正してください。ArrayList<CustomType>Forループを使用せずにアイテムのインデックス(つまり文字列値)を検索したい。

POJO:

id;
name;

コード:

ArrayList<POJO> list = new ArrayList<POJO>;

//Lots of data added to these list...

次に、以下の種類のforループを使用せずに、arraylistから特定の名前のIDを見つけたいと思います。

String id = null;
// TODO Auto-generated method stub
for (int i = 0; i < list.size(); i++) {
    if("ABCD".equalsIgnoreCase(list.get(i).getName())) {
        id = list.get(i).getId();
        break;
    }
}

理想的には、Forループを実装したくないのは、リスト内に500以上のデータがあり、Forループを使用してインデックスを見つけるのはこれを行うのに適した方法ではないためです。

4

6 に答える 6

12

を使用できますlist.indexOf()が、それを機能させるには、とをオーバーライドする必要がequalsありhasCodeますPOJO

デフォルトでは、2つのオブジェクトが同じ参照を持っている場合、それらは等しいと見なされます。equalsあなたはあなたのケースのために働くために上書きすることができます:

public boolean equals(Object o) {
  if (!(o instanceof POJO)) {
    return false;
  }
  POJO other = (POJO) o;
  return name.equalsIgnoreCase(other.getName());
}

等しいをオーバーライドすると、をオーバーライドすることをお勧めしますhashCode。例えば:

public int hashCode() {
  return name.hashCode();
}
于 2012-11-12T09:48:46.983 に答える
4

この方法で要素を見つけると、複雑さがBIG-O(n)になります。マップを作成すると、より良い結果が得られると思います。

HashMapより良い選択でしょう。-複雑さはO(1)になります。

于 2012-11-12T09:48:39.533 に答える
3

親切で迅速な対応をありがとうございました。しかし、ヨアヒムザウアーに感謝します。500要素が多くないことは間違いありません。このループは、コードのパフォーマンスに実際の影響を与えない可能性があります(非効率的ですが)。5000要素まで試してみても、パフォーマンスに悪影響はありません。

改めてありがとうございました。コメントありがとうございます。ヨアヒムザウアー

于 2012-11-13T13:40:09.127 に答える
2

文字列値を検索する必要がある場合は、のHashMap代わりにを使用する必要がありArrayListます。

于 2012-11-12T09:48:37.173 に答える
2

-を使用できますが、List.indexOf()-もオーバーライドする必要がありますPOJO.equals()(また、規則の一部として-もhashCode()

それでも、結果は次のようになることに注意してください。代わりに、並べ替えられた配列()を使用し、または/O(n)を使用することもできます。POJO[]Arrays.binarySearch()SetMap

配列を使用する場合-また、それが実装されbinarySearch()ていることを確認する必要がありますPOJOComparable<POJO>


静的データ(リストは頻繁に/まったく変更されない)の場合、配列であり、big-O表記の観点から binarySearch()は「悪い」ものですが、実際には、特に比較的短いリストの場合は、はるかに高速であることがよくあります。big-O表記に関しては、ハッシュベースのソリューションは平均的なケースアクセスを提供します。HashSet
O(1)

于 2012-11-12T09:49:03.640 に答える
0

この質問に答えるために、私はJMHでベンチマークを開始しました。

当然のことながら、古典的なループはそれを行うための効率的な方法です。

17576個の要素を含むものを使用しましたDATA_ARRAYが、検索された要素はインデックス7733にあります。

クラシックループの使用-0,030±0.001ms/ op:

int i = 0;
for (String str : DATA_ARRAYLIST) {
    if (str.equals("lll")) break;
    i++;
}

indexOfを使用し、equalsメソッドをオーバーライドします:0,030±0.002 ms / op

MY_DATA_ARRAYLIST.indexOf("lll");

データ範囲の使用:0,082±0,003 ms / op

OptionalInt integer = IntStream.range(0, DATA_ARRAYLIST.size())
            .filter(i -> DATA_ARRAYLIST.get(i).equals("lll"))
            .findFirst();

ストリームで検出した後のindexOfの使用:0,074±0,008 ms / op

String result = DATA_ARRAYLIST.stream().filter(e -> e.equals("lll")).findFirst().get();
DATA_ARRAYLIST.indexOf(result);

parallelStreamで検出した後にindexOfを使用する:0,087±0,023 ms / op

String result = DATA_ARRAYLIST.parallelStream().filter(e -> e.equals("lll")).findFirst().get();
DATA_ARRAYLIST.indexOf(result);

ただし、検索された要素が最後のインデックスにある場合:

  • クラシックループ:0,066±0,002 ms / op
  • パラレルストリーム:0,121±0,023 ms / op
  • ストリーム:0,161±0.024 ms / op

そして、456 976個の要素がある場合:

  • クラシックループ:2,172±0,297 ms / op
  • パラレルストリーム:3,145±0,380 ms / op
  • ストリーム:6,081±0,097 ms / op

ご覧のとおり、Loopを打ち負かすのは本当に難しいです!

于 2020-08-20T17:46:19.767 に答える