Java 中的谓词搜索

发布于 2024-08-22 13:02:28 字数 679 浏览 6 评论 0原文

不太确定如何表达这个问题。 我想知道是否有一种方法可以检查自定义 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,etc

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

Not quite sure how to word this question.
I am wondering if there is a method to check certain parts of a custom java class to see if it matches a certain criteria.
Such as this

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

And then when an array of instances of that class are created say,

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");

Is it possible to do a search over the instances of the class for person with

midddlename.equals("bob") && surname.equals("rush")

I am not really looking for a solution that is if(surname.equals("bob")) then else,etc

But more a in-built java class that allows for rapid searching over the array.
the speed of this is very important.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

忘你却要生生世世 2024-08-29 13:02:28

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

您可能会找到此问题及其答案有帮助。与此 developer.com 相同文章。

例如使用谷歌收藏:

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));

There isn't built in support, but Apache Collections and Google Collections both provide Predicate support over collections.

You may find this question and its answers helpful. Same with this developer.com article.

e.g. Using 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));
黎歌 2024-08-29 13:02:28

流和 lambda

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

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");

Optional<Name> result = Arrays.stream(applicants)
    .filter(name -> name.middlename.equals("bob") && name.surname.equals("rush"))
    .findAny();
    
result.ifPresent(name -> System.out.println(name));

这里有很多可用的选项。您可以通过将 .findAny() 切换为 .findFirst() 来获取要匹配的名字,或者通过插入 .parallel() 并行运行搜索例如,.stream(applicants) 之后的 code>。

Streams and lambda

Java 8 added lambda expressions and the stream API, so support is built-in now.

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");

Optional<Name> result = Arrays.stream(applicants)
    .filter(name -> name.middlename.equals("bob") && name.surname.equals("rush"))
    .findAny();
    
result.ifPresent(name -> System.out.println(name));

There are lots of options available here. You can get the first name to match by switching .findAny() to .findFirst() or run the search in parallel by inserting .parallel() after .stream(applicants), for example.

故事↓在人 2024-08-29 13:02:28

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

Searching through an array and "speed is very important" don't really go together. Unless if your array will be very small then searching through an array will never be quick. This is the equivalent of a full table scan in a database, performance no matter how you go about it will be poor. The key to finding things quickly is to use an indexed structure. You can still have an array if you absolutely need it but the searching should be done using another data structure. Check out a Hash or Tree based collection since they organize data in a way that make it very fast to retrieve. TreeSet, TreeMap, HashSet, HashMap, etc. Hashes index data on a hashed key, Trees are similar but also store their data in a sorted order.

蓬勃野心 2024-08-29 13:02:28

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

If you need to search based on the object equality over array check apache common ArrayUtils, You basically have to override your equals and hascode for name object and use it, but if you want to use custom search criteria, I guess you have to implement your own way and there is no built in java language support

妄断弥空 2024-08-29 13:02:28

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

分析您的代码。然后优化。

Use an in memory database like Apache Derby or hsqldb. Take advantage of JDBC, JPA, or Hibernate, which can all do what you want.

Profile your code. Then optimize.

残月升风 2024-08-29 13:02:28

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

当搜索一个值时,这个内部数据结构将使用二分搜索返回索引。

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

像下面想象的 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. 每个属性的数组,这反过来将具有数据的索引

例如,如果你有以下数组:

 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) 以下

The faster way I can think of, is to create a data structure which mirrors this objects property values and hold the internal index for each value has.

When a value is searched, this internal data structure will return the index using binary search.

The only requirement is your object must register and update this structure.

Something like the following imaginary UML/Python like code:

 // 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

Oops

I hope this is understandable.

The point is, if you really what to have this really fast, you have to hold the indexes by property

  1. An array for the data
  2. An array for each property, which in turn would have the index of data

For instance if you have the following array:

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

They would have the positions:

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

And you'll have two ( in this case ) separate arrays which after being sorted would be:

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

and

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

When you search for a given attribute, you take the corresponding array, for instance, if you wan to search the last name "Reyes" you'll take "lastName" array

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

And will perform binarySearch on it for "Reyes" which will return the element at position 2, which in turn will return the index = 1 whih is the position "Oscar" has in the original array.

This should keep things under O(log n)

奢望 2024-08-29 13:02:28

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

该类不随 JDK 6 一起提供,但可能随 JDK 7 一起提供(正在讨论中)。同时您可以将它用作库 - 从以下位置下载 JSR166y 包:
http://gee.cs.oswego.edu/dl/concurrency-interest/< /a>

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

这听起来可能很复杂,但事实确实如此(如果您只是在研究高性能多线程算法)。有一个 Groovy 项目试图围绕并行数组包装一个更用户友好的 API,因此您可能也想看看它:http://gpars.codehaus.org/http://gpars. codehaus.org/Parallelizer

Look at ParallelArray class, it satisfies your requirements, but you need to learn a bit of functional programming concepts to use it efficiently.

The class does not come with JDK 6, but might come with JDK 7 (under discussion). Meanwhile you can use it as a library - download the JSR166y package from:
http://gee.cs.oswego.edu/dl/concurrency-interest/

See this tutorial for detailed explanation:
http://www.ibm.com/developerworks/java/library/j-jtp03048.html

It might sound complicated and it is (if you arew just digging in high performance multi-threaded algorithms). There is a Groovy project which tries to wrap a more user-friendly API around Parallel Array, so you might want to ttake a look at it as well: http://gpars.codehaus.org/ , http://gpars.codehaus.org/Parallelizer

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文