2013-07-08 169 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())); 
    } 
}