在C ++中,我可以使用带有谓词的find_if
来查找容器中的元素。 Java中有类似的东西吗?集合上的contains
方法使用等于且无法参数化。
答案 0 :(得分:11)
您可以使用Predicate中的Google Collections。以下是tutorial及其中的示例:
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));
答案 1 :(得分:2)
您可以使用Apache Commons的CollectionUtils.select。
例如,以下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 ++示例不同,这将创建满足指定谓词的元素的新列表。
编辑:
正如Matthew Flaschen在下面的评论中所建议的,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);
答案 2 :(得分:1)
问题是使用像find_if这样的方法应该使代码更易于编写和更容易阅读。但是,恕我直言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的最后一个例子 - 我讨厌Unicorns,有13个符号。在循环示例中,有8个符号。
Integer firstOdd = null;
for(int i: myList)
if(i % 2 == 1) {
firstOdd = i;
break;
}
函数式编程可能对您更有意义,因为这是您的开发背景,但这并不意味着它是用Java表达它的自然或最简单的方法。 Java 7可能会改变这个....
答案 3 :(得分:0)
通过使用lambdaj,您可以以一种非常易读的方式轻松过滤java集合。例如,以下声明:
select(persons, having(on(Person.class).getAge(), greaterThan(30)));
选择列表中超过30年的所有人。
答案 4 :(得分:0)
在Java 8中,我们有removeIf()
,它使用某些谓词从集合中删除元素。但是我们没有像find_if
这样的东西。但是我们可以使用流API来实现这一点。
List<Integer> list = Arrays.asList(20,35,50,654);
int result = list.stream().filter(i-> i%2!=0).findFirst().orElse(0).intValue();
System.out.println(result);