Фильтрация - один из способов сделать это, как обсуждалось в других ответах.
Хотя фильтрация не масштабируется. На первый взгляд сложность может показаться равной O ( n ) (то есть уже не масштабируемой, если число объектов в коллекции будет расти), но на самом деле, потому что требуется один или более тестов. для применения к каждому объекту в зависимости от запроса, более точная временная сложность составляет O ( nt ), где t - количество тестов, которые нужно применить к каждому объекту.
Таким образом, производительность будет снижаться при добавлении в коллекцию дополнительных объектов и / или по мере увеличения количества тестов в запросе.
Есть еще один способ сделать это, используя индексацию и теорию множеств.
Один из подходов заключается в построении индексов в полях внутри объектов, хранящихся в вашей коллекции, которые вы впоследствии будете проверять в своем запросе.
Допустим, у вас есть коллекция Car
объектов, и у каждого Car
объекта есть поле color
. Скажите, что ваш запрос эквивалентен "SELECT * FROM cars WHERE Car.color = 'blue'
". Вы можете построить индекс для Car.color
, который в основном будет выглядеть так:
'blue' -> {Car{name=blue_car_1, color='blue'}, Car{name=blue_car_2, color='blue'}}
'red' -> {Car{name=red_car_1, color='red'}, Car{name=red_car_2, color='red'}}
Затем с учетом запроса WHERE Car.color = 'blue'
набор синих автомобилей может быть найден за O ( 1 ) сложность времени. Если в вашем запросе были дополнительные тесты, вы могли бы протестировать каждый автомобиль в этом наборе кандидатов , чтобы проверить, соответствует ли он остальным тестам в вашем запросе. Поскольку набор кандидатов, вероятно, будет значительно меньше, чем вся коллекция, временная сложность будет меньше, чем O ( n ) (в инженерном смысле см. Комментарии ниже). Производительность не ухудшается так сильно , когда дополнительные объекты добавляются в коллекцию. Но это все еще не идеально, читайте дальше.
Другой подход, который я бы назвал постоянный индекс запроса . Для объяснения: при обычной итерации и фильтрации коллекция повторяется, и каждый объект проверяется на соответствие запросу. Таким образом, фильтрация подобна выполнению запроса к коллекции. Постоянный индекс запроса был бы наоборот, где коллекция вместо этого запускается поверх запроса, но только один раз для каждого объекта в коллекции, даже если коллекция может запрашиваться любое количество раз.
Индекс постоянного запроса был бы похож на регистрацию запроса с некоторой интеллектуальной коллекцией , так что, когда объекты добавляются и удаляются из коллекции, коллекция автоматически проверяет каждый объект против всех постоянных запросов, которые были зарегистрированы с ним. Если объект соответствует постоянному запросу, то коллекция может добавить / удалить его в / из набора, предназначенного для хранения объектов, соответствующих этому запросу. Впоследствии объекты, соответствующие любому из зарегистрированных запросов, могут быть получены за O ( 1 ) по времени.
Приведенная выше информация взята из CQEngine (механизм сбора запросов) . По сути, это механизм запросов NoSQL для извлечения объектов из Java-коллекций с использованием SQL-подобных запросов без дополнительных затрат на итерацию всей коллекции. Он построен на основе идей, приведенных выше, плюс еще немного. Отказ от ответственности: я автор. Это с открытым исходным кодом и в Maven Central. Если вы найдете это полезным, пожалуйста, проголосуйте за этот ответ!