2016-04-03 79 views
2

好吧,這一直困擾着我,也許我失去了一些東西。Java枚舉新列表創建不按預期方式工作

我有一個枚舉類型列表,我試圖刪除重複項。在下面的代碼中,我無法創建一個新列表,因爲列表在迭代過程中被清空。

任何人都可以發現問題。

List<UserRole> newList = new ArrayList<UserRole>(); 

for (UserRole userRole: originalList) 
{   
     boolean found = false; 

     logger.trace("size of new list: check1 = "+newList.size()); <-- size resets to 0 

     for (UserRole newRole: newList) 
     { 
      logger.trace("check "+userRole.name()+ " with "+newRole.name()); 
      if (StringUtils.equals(newRole.name(),userRole.name())) 
      { 
       found = true; 
       break; 
      } 
     } 

     if (!found) 
     {    
      newList.add(userRole); 
      logger.trace("size of new list check2= "+newList.size()); 
     } 
} 
return newList; 

的UserRole的枚舉類看起來像

public enum UserRole { 

SYSADMIN, 
ADMIN, 
STUDENT, 
TEACHER, 
PRINCIPAL; 

public String value() { 
    return name(); 
} 

public static UserRole fromValue(String v) { 
    return valueOf(v); 
} 

} 

跟蹤日誌

20:20:22.291 TRACE 44 removeDuplicates - size of new list check1 = 0 
20:20:22.291 TRACE 57 removeDuplicates - checking duplicate passed for role = SYSADMIN 
20:20:22.291 TRACE 59 removeDuplicates - size of new list check2 = 1 
20:20:22.295 TRACE 44 removeDuplicates - size of new list check1 = 0 
20:20:22.295 TRACE 57 removeDuplicates - checking duplicate passed for role = SYSADMIN 
20:20:22.295 TRACE 59 removeDuplicates - size of new list check2 = 1 
20:20:22.296 TRACE 44 removeDuplicates - size of new list check1 = 0 
20:20:22.296 TRACE 57 removeDuplicates - checking duplicate passed for role = SYSADMIN 
20:20:22.296 TRACE 59 removeDuplicates - size of new list check2 = 1 
20:20:22.298 TRACE 44 removeDuplicates - size of new list check1 = 0 
20:20:22.298 TRACE 57 removeDuplicates - checking duplicate passed for role = SYSADMIN 
20:20:22.298 TRACE 59 removeDuplicates - size of new list check2 = 1 
+1

此代碼的工作。問題必須在別處。 http://ideone.com/T2WryH –

回答

1

不是一個錯誤 - 對我的作品#8>點

我複製你的代碼放到一個簡單的測試類 - 你瞧! - 它的工作原理!

我不得不假設一些你沒有顯示的代碼,這是調用removeDuplicates(List<UserRole> originalList)的上下文,它產生了你給出的日誌輸出。由於我沒有看到你所遇到的問題,我只能認爲你的問題在於調用者,而不是方法。其中,如果我是正確的,解釋了爲什麼你找不到的問題的方法 - 這將是該方法的調用。

如果這個「看看那裏」的建議是不足以讓你走向解決方案,請編輯幷包含調用代碼。

PS - 要解決這個另一種方法是使用一套理論算法,如:

public static List<UserRole> removeDupesBySetTheory(final List<UserRole> originalList) 
{ 
    final Set<UserRole> holdingSet = new HashSet<>(); 

    holdingSet.addAll(originalList); 

    final List<UserRole> newList = new ArrayList<>(); 

    newList.addAll(holdingSet); 

    return newList; 
} 

,這將給你你以不同的方式想要的結果 - 這是否也表明了問題?如果是這樣,那麼我realllly建議你專注於調用者,而不是被調用者。如果你得到不同的結果,那麼你是正確的看着你的方法內部(儘管你的代碼爲我工作)。

PPS - 如果你想removeDupesBySetTheory保留原始表的相對順序,然後用final Set<UserRole> holdingSet = new LinkedHashSet<>();

+1

'EnumSet'會比'HashSet'好得多。如果需要原始訂單,請使用'LinkedHashSet'。 – Andreas

+0

謝謝......指出我的調用代碼。所有的答案都很有幫助,但是你給了我一個提示。 –

+0

感謝@Andreas(和其他人)讓我想起了EnumSet選項 - 我總是忘記了這種特殊化(和EnumMap一起)。也許現在它會堅持下去。太糟糕了,我們沒有'LinkedEnumSet',所以我們可以直接使用它,即使當需要原始順序(sans dupes)(和'LinkedEnumMap')時也是如此。 – Stevel

0

我真的不能夠重現您的具體問題,但如果你只是想刪除重複您可以使用Set而不是List

Set<UserRole> mySet = EnumSet.noneOf(UserRole.class); 

mySet.add(UserRole.SYSADMIN); 
mySet.add(UserRole.SYSADMIN); 
mySet.add(UserRole.SYSADMIN); 
mySet.add(UserRole.TEACHER); 

System.out.println(mySet); 

隨着輸出:

[SYSADMIN, TEACHER] 
+1

'EnumSet'會比'HashSet'更好。 – Andreas

+1

我不同意。我會使用'LinkedHashSet'來保留訂單。 –

+1

@PaulBoddington如果訂單很重要,我同意。對於枚舉它很少,但情況往往是這種情況,這取決於。 ;-) – Andreas

2

顯示代碼並復位在每次迭代的新列表。

但是,您不應該使用enum值的List。改爲使用EnumSet

作爲Set,它會自動防止重複。

不同於ListLinkedHashSet,其中順序是插入順序,和HashSet,其中順序是任意的,EnumSet將命令與其中枚舉值被定義的序列。

此外,EnumSet緊湊,具有非常不錯的輔助方法與枚舉工作:

  • EnumSet.copyOf(originalList)簡單的方法做你想要什麼
  • EnumSet.allOf(UserRole.class)
  • EnumSet.noneOf(UserRole.class)
  • EnumSet.of(UserRole.STUDENT, UserRole.TEACHER)
  • EnumSet.complementOf(EnumSet.of(UserRole.SYSADMIN))個所有枚舉,除了SYSADMIN
+0

謝謝......學習了關於EnumSet的新內容。 –