В C++ я могу использовать find_if
с предикатом для нахождения элемента в контейнере. Есть ли что-то как этот в Java? contains
метод на использовании наборов равняется и не может быть параметризован.
Вы можете использовать Предикат из Коллекций 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));
Вы также можете посмотреть эту ветку: Как лучше всего фильтровать коллекцию?
Используя lambdaj , вы можете легко фильтровать java-коллекцию в очень удобочитаемом виде. Например, следующее утверждение:
select(persons, having(on(Person.class).getAge(), greaterThan(30)));
выбирает всех людей в вашем списке, которым больше 30 лет.
Вы можете использовать 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);
Проблема в том, что использование такого метода, как find_if, должно упростить написание и чтение кода. Однако IMHO Java не поддается функциональной нотации, и в большинстве случаев яснее и проще просто написать естественный цикл. т.е. код короче и не требует знания библиотек, которые большинство людей не используют. Если бы эта функциональность была встроена и Java поддерживала замыкания (как , похоже, 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 может это изменить ....