不太确定如何说出这个问题。
我想知道是否有一种方法来检查自定义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类允许快速搜索数组。
速度非常重要。
没有内置的支持,但是 Apache集合 和 Google Collections 两者都提供Predicate对集合的支持。
你可能会发现 这个问题 它的答案很有帮助。与此相同 developer.com 文章。
例如使用Google收藏集:
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));
搜索数组和“速度非常重要”并不是真的在一起。除非您的阵列非常小,否则搜索数组将永远不会很快。这相当于数据库中的全表扫描,性能无论你怎么做都会很差。快速查找内容的关键是使用索引结构。如果你绝对需要它,你仍然可以拥有一个数组,但是应该使用另一种数据结构进行搜索。检查基于哈希或树的集合,因为它们以一种使检索速度非常快的方式组织数据。 TreeSet,TreeMap,HashSet,HashMap等。散列密钥上的哈希索引数据,树类似,但也按排序顺序存储它们的数据。
如果需要在数组检查的基础上搜索对象相等 apache common ArrayUtils
,你基本上必须覆盖你的equals和hascode对name对象并使用它,但如果你想使用自定义搜索条件,我想你必须实现自己的方式,并没有内置的java语言支持
使用内存数据库之类的 Apache Derby 要么 HSQLDB。利用JDBC,JPA或Hibernate,它们都可以满足您的需求。
描述您的代码。然后优化。
我能想到的更快的方法是创建一个数据结构,它反映这个对象的属性值并保存每个值的内部索引。
搜索值时,此内部数据结构将使用二进制搜索返回索引。
唯一的要求是您的对象必须注册并更新此结构。
类似于以下想象的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
哎呀
我希望这是可以理解的。
关键是,如果你真的要快得多,你必须按属性保存索引
- 数据的数组
- 每个属性的数组,反过来又具有数据索引
例如,如果您有以下数组:
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"]
当你搜索一个给定的属性时,你拿相应的数组,例如,如果你想搜索姓氏“雷耶斯”你将采取“lastName”数组
["154=3", "G=2", "Reyes=1", "Z=0"]
并将对其执行“Reyes”的binarySearch,它将返回位置2处的元素,这反过来将返回索引= 1,这是“Oscar”在原始数组中的位置。
这应该保持O(log n)
查看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
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)
, 例如。