Java, поиск в списке объектов?

Я немного потерял способ сделать это быстрее. У меня есть большой список объектов, которые имеют базовые атрибуты переменной (с помощью геттеров/сеттеров), и мне нужно выполнить поиск в этом списке, чтобы найти объекты в списке, которые соответствуют заданному параметру

Я нашел, как выполнять обычный поиск по списку, но мне нужно, например, найти значение результата выполнения вызова getName() для каждого объекта в списке и получить объекты, которые имеют результат, соответствующий моему вход.

Что-то вроде ниже, где третий аргумент является результатом вызова метода, а второй - тем, что я пытаюсь найти.

   int index = Collections.binarySearch(myList, "value", getName());

Любые советы приветствуются

Ответ 1

Если вы просто как одноразовая операция должны найти объект (ы), чье getName() является конкретным значением, то, вероятно, не так много возможностей: цикл через список, вызов getName() для каждого объекта, и для тех, которые соответствуют, добавьте их в список результатов.

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

Если вам часто нужно извлекать объекты для данного getName(), сохраните индекс (например, в HashMap) из [результата getName() → object → список совпадений]. Вам нужно будет решить, как и если вам нужно сохранить этот "индекс" в синхронизации с фактическим списком.

См. также другое предложение использовать binarySearch(), но чтобы сохранить список. Таким образом, вставки дороже, чем с картой и несортированным списком, но если вставки нечасты по сравнению с поисковыми запросами, то у этого есть преимущество только в том, чтобы поддерживать одну структуру.

Ответ 2

Взгляните на binarySearch, который принимает компаратор:

public static int binarySearch (список списка,                                  T,                                  Компаратор c)

Итак, вы бы сделали что-то вроде:

class FooComparator
    implements Comparator<Foo>
{
    public int compare(T a, T b)
    {
        return (a.getName().compareTo(b.getName());
    }
}

int index = Collections.binarySearch(myList, "value", new FooComparator());

Вам нужно будет сначала отсортировать список курсов (Collections.sort также принимает Comaprator...).

Ответ 3

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

1.- Создайте метод поиска, который выполняет итерацию коллекции и передает объект, который сообщает вам, должен ли ваш объект быть возвращен или нет.

2.- Вызовите этот метод и создайте анонимный внутренний класс с критериями

3.- Получить новый список в отдельной переменной.

Что-то вроде этого:

result = search( aList, new Matcher(){ public boolean matches( Some some ) { 
  if( some.name().equals("a")) { 
     return true;
  }
}});

Вот рабочая демонстрация:

import java.util.*;
class LinearSearchDemo { 
  public static void main( String ... args ) { 
      List<Person> list = Arrays.asList(
                                  Person.create("Oscar", 0x20),
                                  Person.create("Reyes", 0x30),
                                  Person.create("Java", 0x10)
                          );

      List<Person> result = searchIn( list, 
              new Matcher<Person>() { 
                  public boolean matches( Person p ) { 
                      return p.getName().equals("Java");
              }});

      System.out.println( result );

      result = searchIn( list, 
              new Matcher<Person>() { 
                  public boolean matches( Person p ) { 
                      return p.getAge() > 16;
              }});

      System.out.println( result );

  }
  public static <T> List<T> searchIn( List<T> list , Matcher<T> m ) { 
      List<T> r = new ArrayList<T>();
      for( T t : list ) { 
          if( m.matches( t ) ) { 
              r.add( t );
          }
      }
      return r;
  }
}

class Person { 
  String name;
  int age;

  String getName(){ 
      return name;
  }
  int getAge() { 
      return age;
  }
  static Person create( String name, int age ) { 
      Person p = new Person();
      p.name = name;
      p.age = age;
      return p;
  }
  public String toString() { 
      return String.format("Person(%s,%s)", name, age );
  }    
}
interface Matcher<T> { 
  public boolean matches( T t );
}

Вывод:

[Person(Java,16)]
[Person(Oscar,32), Person(Reyes,48)]

Ответ 5

Если объекты неизменяемы (или вы хотя бы знаете, что их имена не изменяются), вы можете создать индекс с помощью HashMap.

Вам нужно будет заполнить карту и сохранить ее.

Map map = new HashMap();

map.put(myObject.getName(), myObject);
... repeat for each object ...

Затем вы можете использовать map.get("Some name"); для поиска с помощью вашего индекса.

Ответ 6

Одна библиотека, с которой я знаком, - это Guava - вы можете создать Predicate, чтобы вытащить элементы из Iterable. Нет необходимости в предварительной сортировке коллекции. (Это означает, в свою очередь, что O (N), но это удобно.)