Java中的谓词搜索

时间:2010-02-25 17:27:54

标签: java search arrays rules predicates

不太确定如何说出这个问题。 我想知道是否有一种方法来检查自定义java类的某些部分,看它是否符合某个标准。 比如这个

public Name(String forename, String middlename, String surname)

然后当创建该类的实例数组时,说

Name[] applicants = new Name[4];

applicants[0] = new Name("john","bob", "rush");
applicants[1] = new Name("joe","bob", "rushden");
applicants[2] = new Name("jack","bob", "rushden");
applicants[3] = new Name("jake","bob", "rushden");

是否可以对具有

的人进行类的实例搜索
midddlename.equals("bob") && surname.equals("rush")

我并不是在寻找if(surname.equals("bob")) then else等解决方案

但更多的内置java类允许快速搜索数组。 速度非常重要。

7 个答案:

答案 0 :(得分:14)

没有内置支持,但Apache CollectionsGoogle Collections都提供Predicate对集合的支持。

您可能会发现this question及其答案很有帮助。与此developer.com文章相同。

e.g。使用Google Collections:

final Predicate<name> bobRushPredicate = new Predicate<name>() {
   public boolean apply(name n) {
      return "bob".equals(n.getMiddlename()) && "rush".equal(n.getSurname());
   }
}

final List<name> results = Iterables.filter(applicants, bobRushPredicate));

答案 1 :(得分:1)

通过数组搜索和“速度非常重要”并不是真的在一起。除非您的阵列非常小,否则搜索数组将永远不会很快。这相当于数据库中的全表扫描,性能无论你如何去做都会很差。快速查找内容的关键是使用索引结构。如果你绝对需要它,你仍然可以有一个数组,但搜索应该使用另一种数据结构。检查基于哈希或树的集合,因为它们以一种使检索速度非常快的方式组织数据。 TreeSet,TreeMap,HashSet,HashMap等。散列键上的哈希索引数据,树类似,但也按排序顺序存储它们的数据。

答案 2 :(得分:0)

如果你需要基于数组检查apache common ArrayUtils上的对象相等进行搜索,你基本上必须覆盖你的equals和hascode for name对象并使用它,但是如果你想使用自定义搜索条件,我猜你必须以自己的方式实现,并且没有内置的java语言支持

答案 3 :(得分:0)

使用内存数据库,例如Apache Derbyhsqldb。利用JDBC,JPA或Hibernate,它们都可以满足您的需求。

描述您的代码。然后优化。

答案 4 :(得分:0)

我能想到的更快的方法是创建一个数据结构,它反映这个对象的属性值并保存每个值的内部索引。

搜索值时,此内部数据结构将使用二进制搜索返回索引。

唯一的要求是您的对象必须注册并更新此结构。

类似于以下虚构的UML / Python代码:

 // Holds the index number of a given value
 // for instance, name="Oscar" may be at index 42...
 IndexValuePair
     index : Int
     value : String 

     +_ new( value: String, index: Int ) 
          return IndexValuePair( value, index )

 ValuePairComparator --> Comparator 

     + compareTo( a: IndexValuePair, b: IndexValuePair ) : Int 

         return a.value.compareTo( b.value )

 SearchStructure
     - data = Object[] // The original array which contains your applicants
      // a list of arrays each one containing the property value, and the index on "data" where that value appears 
     - dataIndexes =  List(IndexValuePair)[String] // Map<List<IndexValuePair>> 
     - dataIndexexInitialized = false

     // Add an object to this structure
     + addObject( o: Object ) 
          if( ! dataIndexesInitialized, 
              initIndexesWith( o )
          )

          index = data.add( o ) // returns the index at which "o" was inserted
          addToIndexes( o, index ) 

     // Register all the properties values of the given object 
     // along with the index where they appear in the original array 
     - addToIndexes( object: Object, index: Int ) 
           forEach( property in Object , 
              list = dataIndexes[property]
              list.add( IndexValuePair.new( property.value, index ) ) 
           )
     // Create empty array for each property .. 
     - initIndexesWith( object : Object ) 
          forEach( property in object , 
                comparator = ValuePairComparator()
                list = List<IndexValuePair>()
                list.setComparator(  ) 
                dataIndexes[property] =  list
          )
          dataIndexesInitialized = true 


     // Search an object using the given criteria ( a Map<String, String> = key=value ) 
     + search( criteria: String[String] ) : List<Object>

        result = Set<Object>()

        // let's say criteria has:
        // ["name":"Oscar", "lastName"="Reyes"]
       forEach( key in criteria, 
            list = dataIndexes[key]  // "name", "lastname" ..etc. 
            valuePair = list.binarySearch( criteria[key] ) // first Oscar, later Reyes 
            result.add( data[valuePair.index] )
       ) 

       return result

糟糕

我希望这是可以理解的。

关键是,如果你真的要快得多,你必须按属性

保存索引
  1. 数据数组
  2. 每个属性的数组,而该数组又具有数据索引
  3. 例如,如果您有以下数组:

     a = [ Object(name="Mike", lastName="Z" )
           Object(name="Oscar", lastName="Reyes" ) , 
           Object(name="Rahul", lastName="G" ) , 
           Object(name="Pie", lastName="154" )  ]
    

    他们将拥有这些职位:

    0 = Mike ... 
    1 = Oscar ...
    2 = Rahul ...
    3 = Pie ...
    

    你将有两个(在这种情况下)单独的数组,在排序后将是:

    nameArray =  ["Mike=0", "Oscar=1", "Pie=3", "Rahul=2"]
    

    lastNameArray =   ["154=3", "G=2", "Reyes=1", "Z=0"]
    

    当你搜索一个给定的属性时,你会得到相应的数组,例如,如果你要搜索姓氏“Reyes”你将采用“lastName”数组

     ["154=3", "G=2", "Reyes=1", "Z=0"]
    

    并将对其执行“Reyes”的二进制搜索,它将返回位置2的元素,这反过来将返回索引= 1,这是“Oscar”在原始数组中的位置。

    这应该保持在O(log n)

    之下

答案 5 :(得分:0)

查看ParallelArray类,它满足您的要求,但您需要学习一些函数式编程概念才能有效地使用它。

该类不附带JDK 6,但可能附带JDK 7(正在讨论中)。同时您可以将它用作库 - 从以下位置下载JSR166y软件包: http://gee.cs.oswego.edu/dl/concurrency-interest/

有关详细说明,请参阅本教程: http://www.ibm.com/developerworks/java/library/j-jtp03048.html

听起来可能很复杂(如果你只是在挖掘高性能的多线程算法)。有一个Groovy项目试图围绕Parallel Array包装一个更加用户友好的API,所以你可能也想看看它:http://gpars.codehaus.org/http://gpars.codehaus.org/Parallelizer

答案 6 :(得分:0)

Java 8添加了lambda表达式和流API,因此现在内置了支持。

.findAny()

这里有很多选择。您可以通过将.findFirst()切换为.parallel()来获得要匹配的名字,或者通过在.stream(applicants)之后插入import java.util.ArrayList; import java.util.List; import java.util.Scanner; public class Kalkulator { public static void main(final String... args) { System.out.println("enter any number of doubles, whitespace delimited. enter a non-double token to quit"); final List<Double> doubles = new ArrayList<>(); try (final Scanner dane = new Scanner(System.in)) { while (dane.hasNextDouble()) { final double input = dane.nextDouble(); doubles.add(input); System.out.println(String.format("Read [%f]", input)); } } System.out.println(String.format("finished reading user input. %d doubles read.", doubles.size())); System.out.println(String.format("Largest input: %f", doubles.stream().reduce(Math::max).orElse(0D))); System.out.println(String.format("Smallest input: %f", doubles.stream().mapToDouble(d -> d).min().orElse(0D))); } } 来并行运行搜索。