Самый краткий способ определения списка <Foo>Содержит элемент Где Foo.getBar () = "Baz"? - PullRequest
2 голосов
/ 15 сентября 2010

С учетом начального List<Foo>, какой самый краткий способ определить, имеет ли элемент Foo со свойством bar (доступ к которому getBar()) значение "Baz"? Лучший ответ, который я могу придумать, - это линейный поиск:

List<Foo> listFoo;
for(Foo f:listFoo) {
    if(f.getBar().equals("Baz")) {
        // contains value
    }
}

Я посмотрел в HashSet, но, похоже, нет способа использовать contains() без предварительного создания экземпляра Foo для передачи (в моем случае Foo дорого создавать). Я также посмотрел на HashMap, но, похоже, нет способа заполнить его, не просматривая список и не добавляя каждый элемент Foo по одному. Список небольшой, поэтому меня беспокоит не столько производительность, сколько ясность кода.

Большая часть моего опыта разработки связана с C # и Python, поэтому я привык к более кратким утверждениям, таким как:

// C#
List<Foo> listFoo;
bool contains = listFoo.Count(f => f.getBar=="Baz")>0;

или

# Python
# list_foo = [Foo(), ...]
contains = "Baz" in (f.bar for f in list_foo)

Есть ли у Java способ это осуществить?

Ответы [ 4 ]

4 голосов
/ 15 сентября 2010

Сама по себе Java не имеет. Также (как и фью) f.getBar == "Baz" не будет работать для сравнения строк, потому что строки являются объектами. Затем вы используете оператор ==, вы фактически сравниваете объекты (которые не равны, потому что они не находятся в одной и той же ячейке памяти и являются отдельными объектами). Метод equals - лучший способ для сравнения объектов. И, в частности, лучше использовать «Baz» .equals (f.getBar ()), поскольку это также позволяет избежать неприятных исключений NullPointerExceptions.

Теперь ответим на ваш вопрос. Я могу придумать способы сделать это, но это, вероятно, зависит от отношения родительского объекта Foo к дочернему объекту Bar. Всегда ли это будет один к одному или нет? Другими словами, может ли значение Bar "Baz" быть связано с несколькими объектами Foo?

Куда я иду с этим, это объект HashMap, о котором вы говорили ранее. Это связано с тем, что существуют методы containsKey и containsValue. Поскольку HashMap допускает дублирование значений, связанных с разными ключами, вы можете указать Bar в качестве значения и Foo в качестве ключа. Затем просто используйте myHashMap.containsValue («Baz»), чтобы определить, находится ли он в «списке». И поскольку это так, то вы всегда можете получить ключи (Foos), которые связаны с ним.

4 голосов
/ 15 сентября 2010

Java не поддерживает замыкания (пока), поэтому ваше решение является одним из самых коротких. Другим способом было бы использовать, например, google-collection Iterable, как замыкание Predicate:

boolean contains = Iterables.any(iterableCollection, new Predicate<Foo>() {
    @Override
    public boolean apply(Foo foo) {
       return foo != null && foo.getBar().equals("Baz");
    }
}
3 голосов
/ 15 сентября 2010

Вы можете эмулировать это только в Java, например, используя «объект функции».Но так как это немного неловко и многословно в Java, это стоит того, если у вас есть несколько разных предикатов для выбора элементов из списка:

interface Predicate<T> {
  boolean isTrueFor(T item);
}

Foo getFirst(List<Foo> listFoo, Predicate<Foo> pred) {
  for(Foo f:listFoo) {
    if(pred.isTrueFor(f)) {
      return f;
    }
  }
}

class FooPredicateBar implements Predicate<Foo> {
  private final String expected;
  FooPredicateBar(String expected) {
    this.expected = expected;
  }
  public boolean isTrueFor(Foo item) {
    return item != null && expected.equals(item.getBar());
  }
}
...
List<Foo> listFoo;
Foo theItem = getFirst(listFoo, new FooPredicateBar("Baz"));
2 голосов
/ 15 сентября 2010

Вы также можете использовать Apache Commons CollectionUtils :

 boolean contains = CollectionUtils.exists(listFoo, new Predicate() {
     public boolean evaluate(Object input) {
         return "Baz".equals(((Foo)input).getBar());
     }
 });
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...