我有一个hazelcast Ilist,学生班包含5个属性,如(id,姓名,地址,号码,学校)。现在列表中有10k条记录,我怎样才能找到名字为tony且号码为的学生除了for循环之外,我很快就会知道。我知道如果它是一个Imap我可以使用谓词来过滤,但它是一个列表,我没有找到Ilist.Any帮助的谓词,非常感谢。
答案 0 :(得分:1)
不幸的是,没有办法用某种谓词或其他魔法来做到这一点。你必须做一个循环。但是,要加快速度,您应该在包含列表的成员上运行此搜索。但是,分区由列表的名称定义。您基本上可以自己编写一个小的“查询引擎”,以便在列表顶部使用Hazelcast谓词。
我创建了一个基本示例,但您最有可能优化它。
一个简单的学生班:
public class Student implements Serializable {
private long id;
private String name;
private String address;
private String number;
private String school;
public long getId() { return id; }
public void setId(long id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getAddress() { return address; }
public void setAddress(String address) { this.address = address; }
public String getNumber() { return number; }
public void setNumber(String number) { this.number = number; }
public String getSchool() { return school; }
public void setSchool(String school) { this.school = school; }
@Override
public String toString() {
return "Student{" + "id=" + id
+ ", name='" + name + '\''
+ ", address='" + address + '\''
+ ", number='" + number + '\''
+ ", school='" + school + '\'' + '}';
}
}
搜索执行者:
public class StudentSearch {
private final IExecutorService executorService;
public StudentSearch(HazelcastInstance hazelcastInstance) {
this.executorService =
hazelcastInstance.getExecutorService("student_search");
}
public Student findFirstByNameAndNumber(String listName,
String name,
String number)
throws Exception {
Predicate namePredicate = Predicates.equal("name", name);
Predicate numberPredicate = Predicates.equal("number", number);
Predicate predicate = Predicates.and(namePredicate, numberPredicate);
StudentSearchTask task = new StudentSearchTask(listName, predicate);
Future<Student> future = executorService.submitToKeyOwner(task, listName);
return future.get();
}
private static class StudentSearchTask
implements Callable<Student>,
DataSerializable,
HazelcastInstanceAware {
private HazelcastInstance hazelcastInstance;
private String listName;
private Predicate predicate;
public StudentSearchTask() {
}
public StudentSearchTask(String listName, Predicate predicate) {
this.listName = listName;
this.predicate = predicate;
}
@Override
public void setHazelcastInstance(HazelcastInstance hazelcastInstance) {
this.hazelcastInstance = hazelcastInstance;
}
@Override
public Student call() throws Exception {
IList<Student> list = hazelcastInstance.getList(listName);
Optional<Map.Entry<String, Student>> first =
list.stream()
.map(this::makeMapEntry)
.filter(predicate::apply)
.findFirst();
return first.orElse(makeMapEntry(null)).getValue();
}
@Override
public void writeData(ObjectDataOutput out) throws IOException {
out.writeUTF(listName);
out.writeObject(predicate);
}
@Override
public void readData(ObjectDataInput in) throws IOException {
listName = in.readUTF();
predicate = in.readObject();
}
private Map.Entry<String, Student> makeMapEntry(Student student) {
return new QueryEntry(listName, student);
}
}
// Used to query the list entries
private static class QueryEntry
implements Map.Entry<String, Student>,
Extractable {
private final String key;
private final Student value;
private QueryEntry(String key, Student value) {
this.key = key;
this.value = value;
}
@Override
public Object getAttributeValue(String attributeName)
throws QueryException {
if ("number".equals(attributeName)) {
return value.getNumber();
} else if ("name".equals(attributeName)) {
return value.getName();
}
return null;
}
@Override
public AttributeType getAttributeType(String attributeName)
throws QueryException {
return AttributeType.STRING;
}
@Override
public String getKey() {
return key;
}
@Override
public Student getValue() {
return value;
}
@Override
public Student setValue(Student value) {
throw new UnsupportedOperationException();
}
}
}
最后如何运行此代码:
List<Student> students = hz.getList(listName);
addStudents(students);
StudentSearch search = new StudentSearch(hz);
Student result = search
.findFirstByNameAndNumber(listName, "Tony", "001");
System.out.println(result);
我希望这有点帮助:)
答案 1 :(得分:0)
我无法获取对象中的id是什么,因为您需要查询id + name(因此id不是唯一的?)。如果您知道需要查询它们,请将它们存储在Set中(请提供更多信息)。
正如您所指出的,Set中没有谓词。恕我直言,这是因为无法将与Key无关的条目编入索引。如果没有可能添加索引(或者在密钥范围内扫描),谓词的概念就会崩溃,因为任何查询仍然会遍历整个集合。据我所知,你没有太多选择:
如果您使用套装必须有唯一条目,请不要
在这种情况下,请将其移至地图,将密钥用作任何人,例如您的对象 id 。如果可能有id,duplicates,你可以创建更复杂的键,如id + name,甚至哈希整个对象。一旦你必须放置一个新的对象,然后检查它是否已经存在,如果这样,你的自定义逻辑就会回落。 Map将为您提供所需的所有索引和谓词。
另一方面,如果由于某些不受你控制的原因,你必须使用套装...那么你可以通过多种方式做到这一点,但我会建议如下:
收听对Set的任何修改(或者如果是静态或一致性不是问题,请定期扫描该集
构建自定义索引
如何构建索引:
这实际上取决于您想要的性能,您可以接受的RAM影响以及不同的查询方式。 (假设您只有查询总是相同的,例如&#34;名称等于&#34;)。
MultiMap<String, String> index
// index.put(name, key)
通过添加,删除每个Set修改的条目来构建索引,在MultiMap中使用object.name作为键,并在multimap中将Set as值作为实际键。一旦您搜索了一个名称,您只需执行以下操作(伪伪代码)
MultiMap<String, String> index;
Map<String, your_object_class> your_set;
function getByName(String name)
{
List<String> name_key_set index.get( name );
List<your_object_class> out;
for(String key : name_key_set)
out.add(index.get(key));
return out;
}
IMO没有什么可以调用Set上的查询(将查询称为检索数据的聪明方式而不是强力迭代),因为任何此类系统都需要 key =&gt; value < / strong>条目。
有了更多信息,我们可以更好地帮助您:)