0

我有两个相同类型的 arrayList,我想根据 ValueList 中的特定属性比较两者。价值清单

ValueList A contains
1,10,5,
2,20,3
3,40,5,
4,60,8

ValueList B contains
2,20,3
3,40,5

我想比较基于 line_num 的列表并创建另一个 arraylist Result,如果 line_num 存在于 ValueList A 但不在 ValueList B 中,则 Result 中的 value 字段必须具有-1。结果应该是这样的;

Result
10,-1
20,3
40,5,
60,-1

我无法编写“未找到”条件。有人可以帮我吗?

我的代码

List<Result> result= new ArrayList<Result>();
for(ValueList data1: valueListA) {
    for (ValueList data2: valueListB) {
        Result inter = new Result();
        if(data1.getLine_num==data2.getLine_num) {
            inter.setKey(data1.getKey());
            inter.setValue(data1.getValue());
            result.add(inter);
        }
    }
}

更新的代码有效:

public static  List<Result> result;= new ArrayList<Result>();
    ....

  int i1 = 0,int i2 = 0;
  Result inter = new Result();
  while (i1 < valueListA.size() && i2 < valueListB.size()) {
  ValueList data1 = valueListA.get(i1);
  ValueList data2 = valueListB.get(i2);
  if (data1.getLine_num == data2.getLine_num) {
  // Add the result.      
  result= new ArrayList<Result>();

  inter.setValue(data1.getValue());
  inter.setKey(data1-getKey())
  result.add(inter);
  i1++;
  i2++;
 } else if (data1.getLine_num < data2.getLine_num) {
 result= new ArrayList<Result>();
  // Add -1 because the data was not in valueListB.
   inter.setValue(data1.getValue());
  inter.setKey(-1);
  result.add(inter);
  i1++;
  } else {
   i2++;
 }      

}

4

6 回答 6

1

你可以重写ValueList中的equals方法:

 @Override
    public boolean equals(Object obj) {
         if (obj == null)
            return false;
         if (obj == this)
            return true;
         if (!(obj instanceof ValueList))
            return false;

         ValueList other= (ValueList) obj;

         return other.getLineNum() == this.getLineNum();
    }

然后:

List<Result> result= new ArrayList<Result>();
for(ValueList data1: valueListA) {
    Result inter= new Result();
    if (valueListB.contains(data1)) {
         inter.setKey(data1.getKey());
    } else {
         inter.setKey("-1" /* or -1 */);
    }
    inter.setValue(data1.getValue());
    result.add(inter);
}
于 2013-07-08T09:15:40.150 回答
1

如果ValueList line_num是,String那么像这样比较:

if(data1.getLine_num.equals(data2.getLine_num)) 

否则,equals()在类中实现方法ValueList并进行比较:

if (data1.equals(data2)) 

public class ValueList {
    ....

    @Override
    public boolean equals(Object o) {
         if (!(o instanceof ValueList)) 
             return false;

         ValueList other= (ValueList)o;

         if (this.line_num != other.line_num)
            return false;

         ....
         return true;
    }
于 2013-07-08T09:05:16.377 回答
1

从算法的角度来看:

在内部循环开始之前添加一个found等于的布尔变量。false然后,当您找到一个时,将其设置为true.

在循环之后,您测试变量found,如果它为假,则添加 -1。

List<Result> result= new ArrayList<Result>();
for(ValueList data1: valueListA){
    boolean found = false;
    for (ValueList data2: valueListB){
        Result inter= new Result();
        if(data1.getLine_num==data2.getLine_num){
           inter.setKey(data1.getKey());
           inter.setValue(data1.getValue());
           result.add(inter);
           found = true;
           break;
        }
    }
    if (!found) {
       result.add(...)
    }
}

但是,Java 允许更好的解决方案,请参阅其他答案。

但是,如果列表按照您的示例进行排序,您就有更好的算法。您可以使用单个 while 循环和 2 个索引(每个列表一个)。复杂度将从 O(N*M) 下降到 O(N+M)。

int i1 = 0;
int i2 = 0;
while (i1 < valueListA.size() && i2 < valueListB.size()) {
   ValueList data1 = valueListA[i1];
   ValueList data2 = valueListB[i2];
   if (data1.getLine_num == data2.getLine_num) {
      // Add the result.
      i1++;
      i2++;
   } else if (data1.getLine_num < data2.getLine_num) {
      // Add -1 because the data was not in valueListB.
      i1++;
   } else {
      i2++;
   }      
}
于 2013-07-08T09:08:35.143 回答
1

正如我在评论中所问的那样,如果 B 中包含一行而不是 A 怎么办?你会简单地忽略它吗?如果您在 A 中有 2 个项目具有相同的 line_num,而 B 中只有 1 个项目具有这样的 line_num,该怎么办?如果 B 中有 2 个匹配项与 A 中的一个项目相匹配怎么办?

你必须清楚你想要做什么。

从您的代码看来,只要列表 B 中有匹配的“line_num”,您就会在结果列表中插入“key+value”作为结果。

如果是这样,使用包含 bList 中所有行号的 Set 是最简单和最合理的。

Set<Integer> bLineNums =new HashSet<Integer>();
for (ValueList v : bList) {
  bLineNums.add(v.getLineNum());
}

设置好之后,一切都很简单,在伪代码中,它看起来像这样:

for (ValueList a : aList) {
  if (bLineNums.contains(a.getLineNum)) {
    result.add(new Result(a.getKey(), a.getValue()));
  }
}
于 2013-07-08T09:40:32.980 回答
0

您的ValueList数据可能应该equals()通过比较getKey()值来正确定义其方法。然后你可以使用

List<Result> result= new ArrayList<Result>();
for (ValueList data1: valueListA){
    Result inter = new Result();
    inter.setKey(data1.getKey());
    if (valueListB.contains(data1)) {
        inter.setValue(data1.getValue());
    } else {
        inter.setValue(-1);
    }
    result.add(inter);
}
于 2013-07-08T09:08:31.317 回答
0

您应该检查列表 1 中的第一个值和每个值,如果一个值不匹配,那么有一个要检查的条件是 list.hasNext() 那么您可以处理未找到的条件,确保我们已经检查了所有列表中的值。

于 2013-07-08T09:11:24.737 回答