Java 如何使用guava对内存中的列表/地图进行过滤/查询
我有复杂的物体Java 如何使用guava对内存中的列表/地图进行过滤/查询,java,collections,guava,Java,Collections,Guava,我有复杂的物体 class Person{ Integer id; String fname; String lname; //..... there are more attributes List<Address> addresses; } class Address{ String street1; String street2;
class Person{
Integer id;
String fname;
String lname;
//..... there are more attributes
List<Address> addresses;
}
class Address{
String street1;
String street2;
String city;
String state;
String zip;
}
班级人员{
整数id;
字符串fname;
字符串名称;
//……还有更多的属性
列出地址;
}
班级地址{
弦街1号;
弦街2号;
字符串城市;
字符串状态;
拉链;
}
我有大约30000个Person对象,每个对象至少有200-500个子对象(地址)。现在我在内存中有了所有这些,我有了不同的场景(20-30个场景),其中我必须根据场景中可用的过滤器查询/过滤对象。例如
- scen1->获取所有具有lname='zoik'的对象
- scen2->获取所有具有lname='smark'和address.street1=“xyz”的对象
- scen3->获取所有具有lname='smark'和address.street1=“xyz”和address.street1=“pqr”的对象(记住每个对象都有多个地址,所以我需要同时具有满足上述条件的地址的对象。)
- scen4->获取所有具有fname=“smith”和lname=“smark”和address.city=“Los Angeles”的对象
请建议在这种情况下使用番石榴的最佳方法?您应该使用
Iterables.filter(Iterable,Predicate)
与Predicate
s结合使用
例如:
public class PersonLastNameEqualsPredicate implements Predicate<Person> {
private String personName;
public PersonNameEqualsPredicate (String personName) {this.personName= personName;}
public boolean apply(Person p) { return this.personName.equals(p.getLName()); }
}
public class PersonStreet1EqualsPredicate implements Predicate<Person> {
private String street1Name;
public PersonStreet1EqualsPredicate (String street1Name) {this.street1Name = street1Name;}
public boolean apply(Person p) {
for (Address a: p.getAddresses()) {
if (street1Name.equals(a.getStreet1()) return true;
}
return false;
}
}
// Extra predicates as you need them
公共类PersonLastNameEqualsPredicate实现谓词{
私有字符串personName;
公共PersonNameEqualsPredicate(字符串personName){this.personName=personName;}
公共布尔应用(Person p){返回this.personName.equals(p.getLName());}
}
公共类PersonStreet1EqualsPredicate实现谓词{
私有字符串street1Name;
public PersonStreet1EqualsPredicate(字符串street1Name){this.street1Name=street1Name;}
公共布尔应用(个人p){
对于(地址a:p.getAddresses()){
if(street1Name.equals(a.getStreet1())返回true;
}
返回false;
}
}
//根据需要添加额外的谓词
每个场景项需要一个谓词。然后需要根据需要调整它们:
一,
Predicate peopleNamedZoik=新的PersonLastNamePredicate(“zoik”);
二,
谓词peopleNamedMarkandLivingXYZStreet=谓词和(新PersonLastNamePredicate(“smark”)、新PersonStreet1EqualPredicate(“xyz”);
三,
在这里,您应该调整街道谓词,以立即检查所有街道名称是否包含您的所有期望值
那么这仅仅是一个问题
一,
列出myLongPersonList=。。。;
Iterable zoikPeople=Iterables.filter(myLongPersonList,peopleNamedZoik);
二,
列出myLongPersonList=。。。;
Iterable zoikPeople=Iterables.filter(myLongPersonList,PeopleNamedMarkandLivingXYzStreet);
等等。谢谢你的回答。只有一个问题,在应用谓词时,我不想每次应用谓词时都迭代到30K对象。有什么方法可以在第一次迭代时构建映射/索引,然后在处理它们时查询这些对象?类似于步骤1:构建索引或映射步骤2:myFilteredObjects=someListOrMap.get(场景定义)我对番石榴不太熟悉,所以可能会对它有很多期望:D,请随意纠正我。thax很多。过早优化?你确定你在乎吗?30000不是很多迭代,特别是如果他们已经在memory@rst:您得到了一个lazy iterable,因此在那一刻,实际上还没有迭代任何内容。然后您可以使用o使用临时集合来实际迭代和存储它们。最好使用guava的静态构造函数,如List.newArrayList(Iterable),因为它们支持获取iterables。为什么不构建复杂谓词?
Predicate<Person> peopleNamedZoik = new PersonLastNamePredicate("zoik");
Predicate<Person> peopleNamedSmarkAndLivingInXyzStreet = Predicates.and(new PersonLastNamePredicate("smark"), new PersonStreet1EqualsPredicate("xyz"));
List<Person> myLongPersonList = ...;
Iterable<Person> zoikPeople = Iterables.filter(myLongPersonList, peopleNamedZoik);
List<Person> myLongPersonList = ...;
Iterable<Person> zoikPeople = Iterables.filter(myLongPersonList, peopleNamedSmarkAndLivingInXyzStreet);