2016-01-08 113 views
1

我想比較兩個不同的列表並刪除重複項。但是,這兩個列表有兩種不同的對象類型,只有通用屬性是應用程序名稱。迭代在第一次迭代後退出

下面是代碼,

public List<TvAppsType> getAvailableAppsTypesByCompanyIdSecond(int comapnyId) { 
    // put apps to the model that belong to the given company id 
    TVAppService tvAppService = new TVAppService(); 
    List<ThreatviewApp> apps = new CopyOnWriteArrayList<ThreatviewApp>(); 
    apps = tvAppService.getAllAppsforCompanyId(comapnyId); 

    // get list of app types 
    TvAppTypeService types = new TvAppTypeService(); 
    List<TvAppsType> apptypes = new CopyOnWriteArrayList<TvAppsType>(); 
    apptypes = types.getAppTypes(); 
    // add the items to collection for removing 
    for(TvAppsType app : apptypes){ 
     System.out.println("-----------------------"); 
     System.out.println("app : " + app.getAppType_name()); 
    } 

    Iterator<TvAppsType> itertypes = apptypes.iterator(); 
    Iterator<ThreatviewApp> it = apps.iterator(); 
    while (itertypes.hasNext()) { 
     TvAppsType apptype = itertypes.next(); 
     while (it.hasNext()) { 
      ThreatviewApp tvapp = it.next(); 
      if (tvapp.getApp_name().trim().equals(apptype.getAppType_name().trim())) { 
       itertypes.remove(); 
      } 
     } 
    } 

    for(TvAppsType app : apptypes){ 
     System.out.println("-----------------------"); 
     System.out.println("app : " + app.getAppType_name()); 
    } 

    return apptypes; 
} 

問題是這樣的工作只有在第一次迭代中,我懷疑是表被修改後,迭代行爲是不確定的。

void remove()從此迭代器(可選操作)返回的最後一個元素 中刪除底層集合。此方法可以是 每次調用next()時只調用一次。如果除了通過調用此方法之外的任何其他方式正在修改基礎集合,而迭代器的行爲是 未指定。

由於我試圖修改列表運行時,我用CopyOnWriteArrayList bascically,我跟着這篇文章article

爲什麼後第一個迭代停止了嗎?如何解決這個問題並刪除所有重複項?

+0

這可能是更有效的兩個列表映射到一個HashMap中'<字符串,對象>'。之後,地圖的值列表將不會包含重複項(並且可以通過檢查類來分隔)。插入地圖的順序決定了哪個列表最好保留。 (這是針對O(m * n)的O(m + n)。) – laune

回答

0

如果您想在apps列表上多次迭代,您必須重置內部循環的迭代器。否則,inner while循環只會遍歷apps列表一次,之後it.hasNext()將爲false。

Iterator<TvAppsType> itertypes = apptypes.iterator(); 
while (itertypes.hasNext()) { 
    TvAppsType apptype = itertypes.next(); 
    Iterator<ThreatviewApp> it = apps.iterator(); // the inner iterator must be 
                // initialized in each iteration 
                // of the outer loop 
    while (it.hasNext()) { 
     ... 
+0

感謝您的答案,但我們修改'Iterator itertypes = apptypes.iterator();'。所以我們不需要重置這個迭代器? – newday

+1

@mankadanka你只能在'apptypes'上迭代一次,所以你不必重置那個迭代器。你只需確保你不會多次嘗試刪除相同的元素(如cybersam提到的)。 – Eran

+0

謝謝先生! – newday

1

除了@伊蘭的回答,你還有另一個問題。一旦你刪除了一個TvAppsType(在while循環中),你不應該再次嘗試刪除同一個對象。另外,儘快退出內部循環會加速你的算法。

因此,內循環應該是這樣的:

while (it.hasNext()) { 
     ThreatviewApp tvapp = it.next(); 
     if (tvapp.getApp_name().trim().equals(apptype.getAppType_name().trim())) { 
      itertypes.remove(); 
      break; 
     } 
    } 
+0

這對我無效 – newday

+1

這不是一個完整的解決方案 - 它是@ Erin答案的一個改進。 – cybersam