Java,在对象列表中搜索?

时间:2011-03-03 23:22:45

标签: java list search arraylist

我有点迷失方向,让这一切发生得最快。我有一大堆具有基本变量属性的对象(带有getter / setter),我需要在此列表中进行搜索,以查找列表中与给定参数匹配的对象

我已经找到了如何进行常规列表搜索但是我需要,例如,搜索列表中每个对象调用getName()的结果的值,并获得与我的结果匹配的对象输入

下面的内容,第三个参数是方法调用的结果,第二个参数是我想要找到的。

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

感谢任何建议

6 个答案:

答案 0 :(得分:10)

查看binarySearch that takes a comparator

public static int binarySearch(List list,                                    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 ......)。

答案 1 :(得分:10)

如果你只是作为一次性操作需要找到其getName()是特定值的对象,那么可能没有多少魔法:循环遍历列表,在每个对象上调用getName(),对于那些匹配的人,将它们添加到结果列表中。

如果getName()是一项昂贵的操作,并且如果某个给定的对象肯定不会返回匹配值,那么还有其他一些先验的方法,那么显然你可以在循环中构建这个“过滤”。

如果您经常需要为给定的getName()获取对象,则保留[getName() - &gt; object - &gt;的结果的索引(例如在HashMap中)。比赛清单]。您需要决定如何以及是否需要将此“索引”与实际列表保持同步。

另请参阅另一个使用binarySearch()的建议,但要保持列表的维护。这样,插入比使用map和unsorted list更昂贵,但如果插入与查找相比不常见,那么它的优点是只需要维护一个结构。

答案 2 :(得分:9)

我知道匿名内部类不再是时尚,但是当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)]

答案 3 :(得分:2)

要以更具伸缩性的方式执行此操作,而不是简单地迭代/过滤对象,请查看类似问题的答案:How do you query object collections in Java (Criteria/SQL-like)?

答案 4 :(得分:1)

如果对象是不可变的(或者您至少知道它们的名称不会改变),您可以使用HashMap创建索引。

您必须填写地图并保持更新。

Map map = new HashMap();

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

然后您可以使用map.get("Some name");使用索引进行查找。

答案 5 :(得分:0)

我熟悉的一个库是Guava - 你可以编写它的Predicate来从Iterable中提取项目。没有必要对集合进行预先排序。 (这反过来意味着它是O(N),但它很方便。)