web-dev-qa-db-ja.com

Java、オブジェクトのリスト内を検索しますか?

これを最速で実現する方法については、少し迷っています。基本的な変数属性(ゲッター/セッター付き)を持つオブジェクトの大きなリストがあり、このリストで検索を実行して、指定されたパラメーターに一致するリスト内のオブジェクトを見つける必要があります

通常のリスト検索の方法を見つけましたが、たとえば、リスト内の各オブジェクトに対してgetName()を呼び出した結果の値を検索し、入力に一致する結果を持つオブジェクトを取得する必要があります。

以下のようなもので、3番目の引数はメソッド呼び出しの結果で、2番目の引数は私が探しているものです。

   int index = Collections.binarySearch(myList, "value", getName());

アドバイスは大歓迎です

15
Rick

1回限りの操作で、getName()が特定の値であるオブジェクトを検索する必要がある場合は、おそらくそれほどマジックはありません。リストを循環して、各オブジェクトでgetName()を呼び出します。一致したら、それらを結果のリストに追加します。

GetName()が負荷の高い操作であり、特定のオブジェクトが確実に一致する値を返さない場合、事前に解決する他の方法がいくつかある場合は、循環しながらこの「フィルタリング」を組み込むことができます。

特定のgetName()のオブジェクトを頻繁にフェッチする必要がある場合は、[結果のgetName()-> object-> list ofmatches]のインデックス(HashMapなど)を保持します。この「インデックス」を実際のリストと同期させる方法と方法を決定する必要があります。

BinarySearch()を使用し、リストを維持するための他の命題も参照してください。このように、挿入はマップやソートされていないリストよりもコストがかかりますが、挿入がルックアップに比べて頻度が低い場合、1つの構造を維持するだけでよいという利点があります。

10
Neil Coffey

コンパレーターをとるbinarySearch を見てください:

public static int binarySearch(リストリスト、Tキー、コンパレータc)

だからあなたは次のようなことをするでしょう:

class FooComparator
    implements Comparator<Foo>
{
    public int compare(T a, T b)
    {
        return (a.getName().compareTo(b.getName());
    }
}

int index = Collections.binarySearch(myList, "value", new FooComparator());

最初にコースのリストをソートする必要があります(Collections.sortはComapratorも受け取ります...)。

10
TofuBeer

匿名の内部クラスがもはやファッションではないことは知っていますが、Java 8が到着しますが、次のようなものを作成できます。

1.-コレクションを反復する検索メソッドを作成し、オブジェクトが返されるかどうかを通知するオブジェクトを渡します。

2.-そのメソッドを呼び出して、条件付きの匿名内部クラスを作成します

3.-新しいリストを別の変数で取得します。

このようなもの:

result = search( aList, new Matcher(){ public boolean matches( Some some ) { 
  if( some.name().equals("a")) { 
     return true;
  }
}});

これが実用的なデモです:

import Java.util.*;
class LinearSearchDemo { 
  public static void main( String ... args ) { 
      List<Person> list = Arrays.asList(
                                  Person.create("Oscar", 0x20),
                                  Person.create("Reyes", 0x30),
                                  Person.create("Java", 0x10)
                          );

      List<Person> result = searchIn( list, 
              new Matcher<Person>() { 
                  public boolean matches( Person p ) { 
                      return p.getName().equals("Java");
              }});

      System.out.println( result );

      result = searchIn( list, 
              new Matcher<Person>() { 
                  public boolean matches( Person p ) { 
                      return p.getAge() > 16;
              }});

      System.out.println( result );

  }
  public static <T> List<T> searchIn( List<T> list , Matcher<T> m ) { 
      List<T> r = new ArrayList<T>();
      for( T t : list ) { 
          if( m.matches( t ) ) { 
              r.add( t );
          }
      }
      return r;
  }
}

class Person { 
  String name;
  int age;

  String getName(){ 
      return name;
  }
  int getAge() { 
      return age;
  }
  static Person create( String name, int age ) { 
      Person p = new Person();
      p.name = name;
      p.age = age;
      return p;
  }
  public String toString() { 
      return String.format("Person(%s,%s)", name, age );
  }    
}
interface Matcher<T> { 
  public boolean matches( T t );
}

出力:

[Person(Java,16)]
[Person(Oscar,32), Person(Reyes,48)]
9
OscarRyz

これをよりスケーラブルな方法で行うには、単にオブジェクトを反復/フィルタリングするのではなく、同様の質問に対するこの回答を参照してください。 Java(Criteria/SQL-のように)?

2
npgall

オブジェクトが不変の場合(または、少なくとも名前が変更されないことがわかっている場合)、HashMapを使用してインデックスを作成できます。

あなたはマップを埋め、それを更新しておく必要があります。

_Map map = new HashMap();

map.put(myObject.getName(), myObject);
... repeat for each object ...
_

次に、map.get("Some name");を使用して、インデックスを使用してルックアップを実行できます。

1
Matthew Willis

私がよく知っているライブラリの1つはGuavaです-その Predicate を作成して、Iterableから項目を取り出すことができます。コレクションを事前に並べ替える必要はありません。 (つまり、O(N)ですが便利です。)

0
Vance Maverick