Извлечение элементов из списка на основе типа свойства объекта - PullRequest
3 голосов
/ 22 января 2010

Часто у меня есть список объектов. У каждого объекта есть свойства. Я хочу извлечь подмножество списка, где определенное свойство имеет предопределенное значение.

Пример:

У меня есть список объектов пользователя. У пользователя есть homeTown. Я хочу извлечь всех пользователей из моего списка, указав "Springfield" в качестве homeTown.

Обычно я вижу, что это выполняется следующим образом:

Список пользователей = getTheUsers ();

Список returnList = new ArrayList ();

для (пользователь: пользователи) {

   if ("springfield".equalsIgnoreCase(user.getHomeTown()) 

        returnList.add(user); 

}

Я не особенно доволен этим решением. Да, это работает, но это кажется таким медленным. Должно быть нелинейное решение.

Предложения

Ответы [ 5 ]

1 голос
/ 22 января 2010

Что ж, эта операция носит линейный характер, если вы не сделаете что-то экстремальное, например, индексирование коллекции на основе свойств, которые вы ожидаете исследовать таким образом.Если не считать этого, вам просто нужно посмотреть на каждый объект в коллекции.

Но могут быть некоторые вещи, которые вы можете сделать, чтобы улучшить читабельность.Например, Groovy предоставляет метод each () для коллекций.Это позволит вам сделать что-то вроде этого ...

def returnList = new ArrayList();
users.each() {
    if ("springfield".equalsIgnoreCase(it.getHomeTown()) 
        returnList.add(user); 
};
1 голос
/ 22 января 2010

Вам понадобится индивидуальное решение для этого. Создайте пользовательскую коллекцию так, чтобы она реализовала интерфейс List, и добавьте все элементы из исходного списка в этот список.

Внутри этого пользовательского класса List вам необходимо поддерживать несколько коллекций Map всех атрибутов, которые могут помочь вам при поиске значений по мере необходимости. Чтобы заполнить эту Карту, вам нужно будет использовать самоанализ, чтобы найти список всех полей и их значений.

Этот пользовательский объект должен будет реализовать некоторые методы как List findAllBy(String propertyName, String propertyValue);, которые будут использовать вышеуказанную хеш-карту для поиска этих значений.

Это не простое прямое решение. Более того, вам нужно учитывать вложенные атрибуты, такие как «user.address.city». Сделать этот пользовательский список неизменным очень поможет.

Однако даже если вы перебираете список из 1000 объектов в List, все равно это будет быстрее, поэтому вам лучше перебирать List для того, что вам нужно.

0 голосов
/ 03 июля 2012

В итоге я использовал предикаты. Его читаемость выглядит как предложение Дрю.

Что касается производительности, я обнаружил незначительное улучшение скорости для небольших (<100 элементов) списков. Для больших списков (5k-10k) я нашел улучшения на 20-30%. Средние списки имели преимущества, но не такие большие, как большие списки. Я не тестировал супер большие списки, но мое тестирование показало, что список больше, чем лучше результаты по сравнению с процессом foreach. </p>

0 голосов
/ 22 января 2010

Если вы действительно заинтересованы в производительности, я бы также предложил специальное решение . Мое предложение было бы создать Дерево списков , в котором вы можете сортировать элементы.

Если вас не интересует порядок элементов в вашем списке (а большинство людей обычно этого не делают), вы также можете использовать TreeMap (или HashMap) и использовать homeTown в качестве ключа и список всех записей в качестве значения. , Если вы добавляете новые элементы, просто найдите список принадлежности на карте и добавьте его (если это первый элемент, конечно, сначала нужно создать список). Если вы хотите удалить элемент, просто сделайте то же самое.

В случае, если вам нужен список всех пользователей с заданным homeTown, вам просто нужно просмотреть этот список на карте и вернуть его (копирование элементов не требуется), я не уверен на 100% в реализации Map в Java, но полный метод должен быть в постоянном времени (наихудший логарифмический, в зависимости от реализации Map).

0 голосов
/ 22 января 2010

Как я выяснил, если вы используете список, вы должны выполнить итерацию. Будь то для каждого, лямбда или FindAll - это все еще повторяется. Неважно, как ты одеваешь утку, это все равно утка. Насколько я знаю, есть HashTables, Dictionaries и DataTables, для поиска которых не требуется итерация. Я не уверен, каковы реализации Java-эквивалента, но, возможно, это даст вам другие идеи.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...