12

不太清楚这个问题该怎么说。我想知道是否有一种方法可以检查自定义 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 类,允许快速搜索数组。这个速度很重要。

4

7 回答 7

14

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

您可能会发现这个问题及其答案很有帮助。与此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));
于 2010-02-25T17:32:22.553 回答
2

流和 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()例如,您可以通过切换到或通过插入after.findFirst()并行运行搜索来获得要匹配的名字。.parallel().stream(applicants)

于 2017-04-19T15:25:02.480 回答
1

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

于 2010-02-25T20:58:00.803 回答
0

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

于 2010-02-25T17:31:09.063 回答
0

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

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

于 2010-02-25T20:50:24.783 回答
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. 每个属性的数组,该数组又包含数据的索引

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

 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"]

并将对其执行 binarySearch 以查找“Reyes”,这将返回位置 2 处的元素,该元素又将返回 index = 1,即“Oscar”在原始数组中的位置。

这应该使事情保持在 O(log n) 以下

于 2010-02-27T01:19:54.887 回答
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

于 2010-02-27T02:17:42.503 回答