简体   繁体   English

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

[英]Is there something like find_if in Java?

In C++, I can use find_if with a predicate to find an element in a container. 在C ++中,我可以使用带有谓词的find_if来查找容器中的元素。 Is there something like that in Java? Java中有类似的东西吗? The contains method on collections uses equals and can not be parameterized. 集合上的contains方法使用equals,不能参数化。

You can use Predicate from Google Collections . 您可以使用Google集合中的 谓词 Here is the tutorial and an example from it: 这是教程和它的一个例子:

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

You can also look at this thread: What is the best way to filter a Collection? 您还可以查看此主题: 过滤集合的最佳方法是什么?

You can use CollectionUtils.select from Apache Commons. 您可以使用Apache Commons中的CollectionUtils.select

For example, the following C++ code 例如,以下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;

can be written in Java as, 可以用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));

Please note that, unlike in C++ example, this would create a new list of the elements satisfying the specified predicate. 请注意,与C ++示例不同,这将创建满足指定谓词的元素的新列表。

EDIT : 编辑:

As Matthew Flaschen has suggested in a comment below, CollectionUtils.find is even closer to what you need. 正如Matthew Flaschen在下面的评论中所建议的, CollectionUtils.find更接近您的需求。 So, with find , the above code can be rewritten as: 因此,使用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);

The problem is that using a method like find_if should make the code simpler to write and easier to read. 问题是使用像find_if这样的方法应该使代码更易于编写和更容易阅读。 However, IMHO Java does not lend itself to functional notation and most of the time it is clearer and simpler to just write a natural loop. 但是,恕我直言Java并不适用于功能表示法,大多数情况下,编写自然循环更清晰,更简单。 ie the code is shorter and doesn't require knowledge of libraries most people don't use. 即代码较短,不需要大多数人不使用的图书馆知识。 If this functionality was built in and Java supported Closures (as it appears Java 7 will) then using predicates and functional methods would make more sense. 如果内置了这个功能并且Java支持的Closures(就像Java 7那样),那么使用谓词和函数方法会更有意义。

One measure of complexity is to count the number of symbols (counting open/close brackets as one) Using this measure of complexity, most predicate based solutions have more symbols and are possibly more complex and difficult for developers to read/maintain. 复杂性的一个衡量标准是计算符号的数量(将开放/关闭括号统计为一个)使用这种复杂性度量,大多数基于谓词的解决方案具有更多符号,并且可能更复杂且难以使开发人员读取/维护。

In the example given by @Roman, there are 15 symbols. 在@Roman给出的例子中,有15个符号。 In the loop example, there are 10 symbols. 在循环示例中,有10个符号。

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

In the example by @Mario Fuscom, there is 9 symbols, in the following example there is 9 symbols. 在@Mario Fuscom的示例中,有9个符号,在以下示例中,有9个符号。 However, no non-standard functions are required and anyone who knows Java can read/maintain it. 但是,不需要任何非标准函数,任何知道Java的人都可以读取/维护它。

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

Taking the last example from @Rahul G - I hate Unicorns, there are 13 symbols. 以@Rahul G的最后一个例子 - 我讨厌Unicorns,有13个符号。 In the loop example, there are 8 symbols. 在循环示例中,有8个符号。

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

Functional programming may make more sense to you because that is your development background, but this doesn't mean it is the natural or simplest way to express this in Java. 函数式编程可能对您更有意义,因为这是您的开发背景,但这并不意味着它是用Java表达它的自然或最简单的方法。 Java 7 may change this.... Java 7可能会改变这个....

By using lambdaj you can easily filter a java collection in a very readable way. 通过使用lambdaj,您可以以一种非常易读的方式轻松过滤java集合。 For example the following statement: 例如以下声明:

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

selects all the persons in your list having more than 30 years. 选择列表中超过30年的所有人。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM