2017-02-24 303 views
4

我需要迭代所有枚舉值,檢查它們是否用於構造int(稱爲input),如果是,則將它們添加到Set(稱爲usefulEnums)。我可以使用Stream API或迭代所有枚舉來完成此任務。使用Arrays.stream()比使用迭代values()數組的傳統方法有什麼好處?在數組上迭代使用Arrays.stream()是否有任何性能優勢?

enum TestEnum { VALUE1, VALUE2, VALUE3 }; 

    Set<TestEnum> usefulEnums = new HashSet<>(); 

    Arrays.stream(TestEnum.values()) 
      .filter(t -> (input & t.getValue()) != 0) 
      .forEach(usefulEnums::add); 

    for (TestEnum t : TestEnum.values()) { 
     if ((input & t.getValue()) != 0) { 
      usefulEnums.add(t); 
     } 
    } 

回答

2

這麼短的操作for loop將是快(毫微秒更快),但對我來說流操作more verbose,它告訴正是被這裏完成。這就像對角讀書一樣。

你也可以直接收集到HashSet

Arrays.stream(TestEnum.values()) 
     .filter(t -> (input & t.getValue()) != 0) 
     .collect(Collectors.toCollection(HashSet::new)); 
從霍爾格

寶貴意見像往常一樣讓這甚至更好:

EnumSet<TestEnum> filtered = EnumSet.allOf(TestEnum.class).stream() 
      .filter(t -> (input & t.getValue()) != 0) 
      .collect(Collectors.toCollection(() -> EnumSet.noneOf(TestEnum.class))); 
+0

完美!謝謝:) – user1071840

+1

在通常情況下,你只需要一個'Set',而不是'HashSet',具體的'Collectors.toSet()'是最好的。 –

+1

@ Solomonoff的祕密:當元素是枚舉常量時,比如'TestEnum',最好使用'Collectors.toCollection(() - > EnumSet.noneOf(TestEnum.class))'代替,儘管獲取所有與謂詞匹配的'enum'常量具有更簡單的直接解決方案... – Holger

3

如果你關心效率,你應該考慮:

Set<TestEnum> usefulEnums = EnumSet.allOf(TestEnum.class); 
usefulEnums.removeIf(t -> (input & t.getValue()) == 0); 

請注意,當您必須迭代所有enum類型的常量,使用EnumSet.allOf(EnumType.class).stream()可以避免完全創建數組EnumType.values(),但是,大多數enum類型沒有足夠的常量來實現此功能。此外,無論如何,JVM的優化器可能會刪除臨時陣列創建。

但對於這個特定的任務,其中結果應該是一個Set<TestEnum>,使用EnumSet代替HashSet甚至可能改善與Set工作的後續操作。創建一個包含所有常量並刪除不需要的常量(如上述解決方案)的方法,意味着只需使用0b111初始化long,然後清除不匹配元素的位。

+1

'意思是隻用0b111'初始化長整數,除非你有超過64個條目,當使用'JumboEnumSet'的時候。關於'EnumSet.allOf'的好點# – Eugene

+1

@Eugene:well'0b111'顯然是指三個常量的問題。如果'enum'具有'64'常量,那麼它應該是'0b1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111',如果它更多,就會有'long []'數組,但是,如果沒有更大的TestEnum []'可能會變成引人注目,使得EnumSet的優勢更大。 – Holger

+0

@Holger你能解釋一下'是否意味着只用0b111'來初始化一個long? – user1071840

相關問題