迭代和处理ArrayList

时间:2010-09-15 13:17:29

标签: java arraylist filtering

我有List个对象。我想迭代这个对象列表并根据条件处理一些对象子集,最后创建一个新的对象列表,其中一些已处理的对象被删除。

这样做的最佳方式是什么。?

示例:

实际对象:List<Cars>

  1. 遍历此列表并以相同的速度查找Cars
  2. 在较小的一组Cars中,要删除相同型号的那些。
  3. 最后消除后我得到了新的清单。

5 个答案:

答案 0 :(得分:7)

Google Guava libraries有:

Iterables.filter(cars, new Predicate<Car>() {
    @Override
    public boolean apply(Car car) {
         //return true or false depending on whether you 
         // want this car to remain in the list
    }
}

您还可以使用中间Set - 即

 cars = new ArrayList<Car>(new HashSet<Car>(cars));

您已正确实施hashCodeequals。如果这是您汽车的标识,则此选项可行。


您也可以使用迭代器:

for (Iterator<Car> it = cars.iterator(); it.hasNext();) {
    Car car = it.next();
    if (conditions here) {
         it.remove();
    }
}

顺便说一句,我知道上面的例子并没有完全解决你的问题 - 你仍然应该考虑在外部循环中迭代什么。

答案 1 :(得分:3)

如果您希望自定义等于比较,那么您应该定义Comparator<Car>,然后循环浏览汽车。

List<Car> originalList;
Comparator<Car> c = new CarSpeedComparator();
List<Car> result = carFilter(originalList, c);

/// Below is the filter method

public static List<Car> carFilter(List<Car> original, Comparator<Car> comp)
    List<Car> result = new ArrayList<Car>();
    // Process each car
    for (Car car: original) {
        boolean containsC = false;
        // now we check each car in the result
        // to see if we already have an equivalent car
        for (int i = 0; i < result.size(); i++) {
            // if the two cars are equivalent under the rules
            // then we already have that car in the list
            if (comp.compare(result.get(i), car) == 0) {
                containsC = true;
                break;
            }
        }
        // if the result does not contain an equivalent car,
        // add it to the list
        if (!containsC) result.add(car)
    }
    return result;
}

//// Implementation of one of the necessary comparators

public class CarSpeedComparator implements Comparator<Car> {
    public int compare(Car c1, Car c2) {
        return c1.getSpeed() - c2.getSpeed();
    }
}

结果列表只包含每个速度的一辆车。

答案 2 :(得分:1)

听起来你可能想先做的就是按速度索引列表中的汽车。完成后,可能更容易完成您正在寻找的其余处理。 GuavaMultimap对此有好处:

ImmutableListMultimap<Integer, Car> speedIndex = Multimaps.index(cars,
    new Function<Car, Integer>() {
      public Integer apply(Car from) {
        return from.getSpeed();
      }
    });

现在speedIndex将是一个多图,可让您执行以下操作:

for (Integer speed : speedIndex.keySet()) {
  ImmutableList<Car> carsWithSpeed = speedIndex.get(speed);
  // Do stuff
}

这使您可以对原始列表中具有相同速度的所有汽车进行分组。然后你可以对你想做的任何处理。您可能希望按型号对这组汽车编制索引,为您提供具有相同速度和型号的汽车分组。如果需要,您可以从原始列表中删除这些汽车。或者,如果您根本不想修改原始列表,只是获取已移除一组汽车的列表副本,您可以将要删除的每辆汽车添加到Set,然后获取副本那些车被移除了这样:

Set<Car> carsToRemove = ...;
List<Car> filteredList = Lists.newArrayList(Iterables.filter(cars,
    Predicates.not(Predicates.in(carsToRemove))));

答案 3 :(得分:0)

如果你在大名单上反复这样做,你会希望提高效率。保留一个对象列表,同时为每个车型保留单独的列表; Hashtable<String, List> models。这样,您已经为未来的类别完成了模型部分。它需要更多的内存,但显着的搜索时间更短。

答案 4 :(得分:0)

对我来说,看起来OP只需要一组独特的(模型,速度)对。如果是这样,这是一个简单的方法:

class Car {
    private final String model;
    private final int speed;

    public int hashCode(){
         return model.hashCode() + speed;
    }

    public boolean equals(Object obj){
         //check on null/different class omitted.
         Car other = (Car)obj;
         return this.model.equals(obj.model) && this.speed == other.speed;
    }
}

然后

 Set<Car> cars = new HashSet<Car>(originalListOfCars);