2013-07-08 173 views
0

我有两个相同类型的arrayList,我想比较两个基于ValueList中的特定属性。 值列表比较两个ArrayList

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的结果,如果line_num存在于值列表A,但不是在值列表B,然后在结果字段中的值有-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++; 
}  

}

+2

为什么不能简单地用'列表#contains'?覆盖'ValueList#hashCode'和'ValueList#equals'。 – m0skit0

+0

如果一行包含在B中而不是A中,该怎么办?你会忽略这个吗?如果在A中有2个项目具有相同的line_num,而B中只有1个项目具有这样的line_num?如果B中有一个项目在A中有两个匹配的项目会怎么样? –

+0

@AdrianShum:如果一行在B中而不在A中,它将被忽略。line_num是唯一的,并且不会有重复。 –

回答

1

从一个角度算法点:

内循环开始前添加一个布尔变量found这等于false。然后,当你找到一个,你将它设置为true

循环结束后,您测试变量found,如果它为false,则加-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循环和两个索引(每个列表一个)。复杂度将从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++; 
    }  
} 
+0

我想按照你的建议(第二种方式),但问题是,当添加第二个对象时,它会重写第一个对象,并且第一个和第二个对象都是相同的。所以最后,如果我应该在结果中获得5个对象,那么所有5个对象将是相同的,并且将是最后一个对象 –

+0

@ user2236033我需要查看代码,可以将它发布到某处吗?你每次都在做“新的Result()”吗? –

+0

更新了原始帖子中的代码 –

1

如果ValueListline_numString则比较像这样:

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; 
    } 
+0

ValueList; line_num is int –

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

您应该检查清单1中的每一个值的第一个值,如果值不匹配,然后有一个条件,以检查是list.hasNext(),那么你可以处理没有找到状态决策确定我们已经检查了列表中的所有值。

1

您可以覆盖的方法等于在值列表:

@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); 
} 
1

当我问在评论,如果有什么包含在B中的行,但不成?你会忽略这个吗?如果在A中有2个项目具有相同的line_num,而B中只有1个项目具有这样的line_num?如果B中有一个项目在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())); 
    } 
}