【问题标题】:Iterating and processing an ArrayList迭代和处理 ArrayList
【发布时间】:2011-04-12 16:31:37
【问题描述】:

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

最好的方法是什么?

例子:

实际对象:List<Cars>

  1. 遍历这个列表,以同样的速度找到Cars
  2. 在较小的Cars集合中,相同型号的将被淘汰。
  3. 终于在淘汰后得到了新名单。

【问题讨论】:

  • 那么同一个型号可以有两种不同的速度吗?
  • 你能在你的例子中举一个具体的例子吗?如何过滤:Civic 50 |思域 75 |凯美瑞50 |思域 50 |凯美瑞 75

标签: java arraylist filtering


【解决方案1】:

如果您希望进行自定义 equals 比较,那么您应该定义一个 Comparator<Car>,然后循环遍历 Cars。

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

结果列表将只包含每种速度的一辆汽车。

【讨论】:

  • 但我的处理将针对一组对象进行
  • @user,所以,您要删除列表中与另一辆车速度相同的所有汽车吗?
【解决方案2】:

在我看来,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);

【讨论】:

    【解决方案3】:

    谷歌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();
        }
    }
    

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

    【讨论】:

    • 我建议参考 Guava 而不是 google-collections。它现在基本上已经过时了。
    • 我也打算对此表示赞同,但如果您仔细阅读,我认为这实际上与 OP 试图做的事情没有太大关系。您的第一个和第三个建议适用于可以独立于其他元素应用于每个元素的过滤决策; OP的示例不适合。第二个建议依赖于一个可能不正确的条件。
    • 好吧,谓词/外部迭代中的另一个迭代,如果他必须与列表的其他成员进行比较应该这样做。 O(n^2),但是..
    【解决方案4】:

    听起来您可能想做的首先是按速度索引列表中的汽车。完成此操作后,进行所需的其余处理可能会更容易。 Guava's Multimaps 对此有好处:

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

    【讨论】:

      【解决方案5】:

      如果您在大型列表中反复执行此操作,您会希望提高效率。保留对象列表,但也要为每个型号的汽车保留单独的列表; Hashtable&lt;String, List&gt; models。这样,您已经为将来的排序完成了模型部分。它需要更多的内存,但搜索的时间明显更少。

      【讨论】:

        猜你喜欢
        • 2011-02-18
        • 2016-08-23
        • 2016-02-29
        • 2014-12-21
        • 2021-09-26
        • 1970-01-01
        • 2012-10-08
        • 2013-04-30
        • 2015-11-13
        相关资源
        最近更新 更多