在Java中有类似find_if的东西吗?

时间:2010-04-05 09:26:35

标签: java collections

在C ++中,我可以使用带有谓词的find_if来查找容器中的元素。 Java中有类似的东西吗?集合上的contains方法使用等于且无法参数化。

5 个答案:

答案 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));

您还可以查看此主题:What is the best way to filter a Collection?

答案 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);