Есть ли что-то вроде find_if в Java? - PullRequest
8 голосов
/ 05 апреля 2010

В C ++ я могу использовать find_if с предикатом, чтобы найти элемент в контейнере. Есть ли что-то подобное в Java? Метод contains для коллекций использует equals и не может быть параметризован.

Ответы [ 4 ]

11 голосов
/ 05 апреля 2010

Вы можете использовать Предикат из Коллекции Google . Вот учебник и пример из него:

final Predicate<Car> expensiveCar = new Predicate<Car>() {
   public boolean apply(Car car) {
      return car.price > 50000;
   }
}

List<Car> cars = Lists.newArrayList();
cars.add(new Car("Ford Taurus", 20000));
cars.add(new Car("Tesla", 90000));
cars.add(new Car("Toyota Camry", 25000));
cars.add(new Car("McClaren F1", 600000));

final List<Car> premiumCars =
   Lists.immutableList(Iterables.filter(cars, expensiveCar));

Вы также можете посмотреть эту ветку: Каков наилучший способ фильтрации коллекции?

2 голосов
/ 05 апреля 2010

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

Например, следующий код C ++

  bool isOdd (int i) {
    return i % 2 != 0;
  }
  ...
  vector<int> myvector;
  vector<int>::iterator it;

  myvector.push_back(10);
  myvector.push_back(25);
  myvector.push_back(40);
  myvector.push_back(55);

  it = find_if (myvector.begin(), myvector.end(), isOdd);
  cout << "The first odd value is " << *it << endl;

может быть написано на Java как

List<Integer> myList = Arrays.asList(10, 25, 40, 55);
List<Integer> oddNums = (List<Integer>) CollectionUtils.select(myList,
  new Predicate<Integer>() {
    public boolean apply(Integer i) {
      return i % 2 != 0;
    }
  }
);
System.out.println("The first odd value is "+oddNums.get(0));

Обратите внимание, что, в отличие от примера C ++, это создаст новый список элементов, удовлетворяющих указанному предикату.

РЕДАКТИРОВАТЬ:

Как предложил Мэтью Фляшен в комментарии ниже, CollectionUtils.find еще ближе к тому, что вам нужно. Таким образом, с find приведенный выше код можно переписать так:

List<Integer> myList = Arrays.asList(10, 25, 40, 55);
Integer firstOdd = (Integer) CollectionUtils.find(myList,
  new Predicate<Integer>() {
    public boolean apply(Integer i) {
      return i % 2 == 1;
    }
  }
);
System.out.println("The first odd value is "+firstOdd);
1 голос
/ 10 апреля 2010

Проблема в том, что использование метода вроде find_if должно сделать код более простым для написания и более легким для чтения. Тем не менее, IMHO, Java не поддается функциональной нотации, и в большинстве случаев проще и проще написать естественный цикл. то есть код короче и не требует знания библиотек, которые большинство людей не используют. Если эта функциональность была встроена и Java поддерживает Closures (как Похоже, Java 7 будет), тогда использование предикатов и функциональных методов имело бы больше смысла.

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

В примере, приведенном @Roman, есть 15 символов. В примере цикла есть 10 символов.

List<Car> premiumCars = new ArrayList();
for(Car car: cars)
   if(car.price > 50000)
      premiumCars.add(car);

В примере @Mario Fuscom 9 символов, в следующем 9 символов. Однако не требуется никаких нестандартных функций, и любой, кто знает Java, может читать / поддерживать его.

List peopleOver30 = new ArrayList();
for(Person person: people)
   if(person.age > 30)
      peopleOver30.add(person);

Взяв последний пример из @Rahul G - я ненавижу единорогов, там 13 символов. В примере цикла есть 8 символов.

Integer firstOdd = null;
for(int i: myList) 
    if(i % 2 == 1) {
       firstOdd = i;
       break;
    } 

Функциональное программирование может иметь больше смысла для вас, потому что это ваш опыт разработки, но это не значит, что это естественный или самый простой способ выразить это в Java. Java 7 может изменить это ....

0 голосов
/ 10 апреля 2010

Используя lambdaj , вы можете легко фильтровать коллекцию java очень читабельным способом.Например, следующее утверждение:

select(persons, having(on(Person.class).getAge(), greaterThan(30)));

выбирает всех людей в вашем списке, которым более 30 лет.

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