比较不同类型的对象列表的有效方法

时间:2014-11-18 10:45:13

标签: java collections comparator comparable

public class State{

String code;
int occurValue;
int name;

}

public class Equi{
String code;
int occurValue;
int macAddress;

}

有两类不同类型。 我有一个List<State>List<equi>。在这些列表中,如果code和happenValue相同,我需要将其移动到不同的List。 我怎么能实现这一点,谷歌搜索给了我很多选项线Comparable,Comparator。让我知道哪种方法最有效。 提前谢谢。

3 个答案:

答案 0 :(得分:0)

我会使用自己定义的方法来做到这一点,Boolean <compare(State state, Equi equi)>或类似的东西,给定的列表项作为参数。代码:

//You have to iterate the method with a for loop for example
//In different situations you need different iterating methods, for example you add 
//1 element to Equi:
//You compare all State element with the new Equi element, but just with that ONE
for (int i =0; i < stateList.size(); i++ {
  flag = compare(stateList.get(i),equiList.get(<indexOfNewElement>); // flag is a boolean value
  if (flag) {
    //moving metod and stuff...
  }
}
//this way you don't make unnecessary steps. It's one example, there are many other situation

Boolean compare(State state, Equi equi) { // You add List elements as parameters
  if (state.getCode().equals(equi.getCode())) { // I prefer to use getters, it depends on your code and preferences
    if (state.getOccurValue() == equi.getOccurValue()) { //same here
      return true; //If returns true, an other method move it.
    } else {
      return false;
    }
  } else { //if the first ones aren't equal needless to check the second values
    return false;
  }
}

通过这种方式,您可以使用此方法进行所有比较,但每次需要编写迭代器时。这意味着更多编码,但运行时间更少。例如,如果列表按ABC顺序按code排序,则可以避免使用标记或任何内容将“k *”与“a *”进行比较。

答案 1 :(得分:0)

这在很大程度上取决于您对“有效”的定义。

如果您对时间不感兴趣,可以创建双重foreach循环并将每个项目相互比较。 这是一种蛮力而非时间效率(因为它是O(n ^ 2)),但可以为您节省大量编程时间,可以花费更多有用的东西。同样适用于相当少量的项目(我建议<10.000),其中时间优化通常不会支付。

如果您希望它节省时间,您可以使用一些抽象的数据结构来帮助您。例如,如果“code”-field在每个集合中都是唯一的,则创建一个HashMap ,其中键指的是“code”,值是Equi referenct。然后,您可以迭代您的状态并查询HashMap以获得匹配的Equi。询问返回的Equi的discoverValue。您还可以引入第二个HashMap,其中happenValues作为键。 这应该为比较部分提供O(n)。

更强大的面向对象的方法你要创建一个接口IHasCodeAndOccurValue并让State和Equi实现它。然后在两个类中实现equals(IHasCodeAndOccurValue other)方法。您在每个List中插入两个数据集并调用stateList.retainAll(equiList)。这可能是最优雅的方法,并且 - 根据您选择的List实现 - 也可以在O(n)中运行。

如您所见,有几种方法可以优化此代码。在不知道细节的情况下,如何继续进行是纯粹的推测。

答案 2 :(得分:0)

如果列表中没有其他信息,那么最有效的算法是将一个列表中的每个元素与另一个列表中的每个元素进行比较:

for (State s : stateList) {
    for (equi e : equiList) {
        if (s.code.equals(e.code) && s.occurValue == e.occurValue) {
            // add to another list
        }
    }
}

这是O(n * m)(其中n是stateList的大小,m是equiList的大小)。

如果对两个列表进行排序,则可以使用更有效的算法。例如,在伪代码中:

for (int i = 0; i < stateList.size(); i++) {
    int j = 0;
    State s = stateList.get(i);
    while (equiList.get(j) is smaller than s) {
        j++;
    }
    equi e = equiList.get(j);
    if (s.code.equals(e.code) && s.occurValue == e.occurValue) {
        // add to another list
    }
}

这是O(m + n)。当然,要实现这一点,您必须编写比较函数(一个用于比较StateState,一个用于比较equiequi和一个用于比较Stateequi)。

顺便说一句,Java命名约定规定类以大写字母开头,因此它应该是Equi,而不是equi