2016-12-29 2 views
1

У меня есть список лесных деревьев, класс ученика содержит 5 свойств, таких как (id, name, address, number, school). Теперь в списке есть 10k записей, как я могу найти ученика чье имя - тони, а число - 001 быстро, за исключением цикла. Я знаю, если это Imap, я могу использовать предикат для фильтрации, но это список, я не нашел предиката для Ilist.Any help, спасибо большое ,быстро найти запись в списке лесного каштана

ответ

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

Я надеюсь, что это помогает немного :)

+0

Хороший пример @noctarius. Это должно получиться в документации SO. –

0

Я не могу получить идентификатор в объекте, поскольку вам нужно запросить имя id + (поэтому id не предназначен для уникальности?). Почему вы храните их в наборе, если знаете, что вам нужно будет запросить их (просьба дать больше информации).

Как вы указали, в Set нет предикатов. ИМХО это потому, что записи, не связанные с ключом, не могут быть проиндексированы. Без возможности объявления индекса (или в режиме leas range-scan on key) понятие предикатов рушится, так как любой запрос будет по-прежнему повторяться по всему набору. Насколько я вижу, у вас не так много вариантов:

Если вы используете набор, необходимо иметь уникальные записи, не надо!

В этом случае переместите его на карту, используйте ключ как любой, например, ваш объект id. Если может быть id, duplicates, вы можете сделать более сложный ключ, такой как id + name или даже хэш всего объекта. После того, как вы должны поместить новый объект, сделайте ключ и проверьте, присутствует ли он, если он возвращается к вашей пользовательской логике. Карта предоставит вам все индексы и предикаты, которые вы можете пожелать.

С другой стороны, если по каким-то причинам, которые не находятся под вашим контролем, вы должны использовать множество ... то вы можете сделать это во многих отношениях, но я предлагаю следующим образом:

  1. Listen на любой модификация Set (или, если статический или консистенция не является проблемой сканирования периодически множества

  2. Создайте свой пользовательский индекс

Как построить индекс:

Это действительно зависит от характеристик, которые вы хотите, от воздействия оперативной памяти, которое вы можете принять и как могут быть разные запросы.(Предположим, что вы только запросы всегда одинаковы, например, «имя равно»).

MultiMap<String, String> index 
// index.put(name, key) 

Вы структурировать индекс путем добавления, удаления записей на каждой модификации Set, используя в своем Multimap в object.name как ключ и фактический ключ в Комплексе в качестве значения в Multimap. После того, как вы будете искать для дать имя вы просто сделать как следует (псевдо-псевдо-код)

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 (со ссылкой на запрос, как умный способ для извлечения данных а не итерации грубой силы), поскольку любая такая система потребует ключ => значение записей.

С дополнительной информацией мы можем помочь вам лучше :)

Смежные вопросы