Development Tip

Enum.values ​​() 대 EnumSet.allOf ().

yourdevel 2020. 12. 15. 19:52
반응형

Enum.values ​​() 대 EnumSet.allOf (). 어느 것이 더 바람직합니까?


나는 후드 아래를 살펴 보았고 EnumSet.allOf특히 64 미만의 값을 가진 열거 형의 경우 매우 효율적으로 보입니다.

기본적으로 모든 세트는 가능한 모든 열거 형 값의 단일 배열을 공유하며 유일한 다른 정보는의 경우 allOf한 번에 설정 되는 비트 마스크입니다 .

반면에 Enum.values ​​()는 약간의 마술처럼 보입니다. 또한 컬렉션이 아닌 배열을 반환하므로 많은 경우 컬렉션을 예상하는 모든 위치에서 사용할 수 있도록 Arrays.asList ()로 데코 레이팅되어야합니다.

그래서, EnumSet.allOf더 선호되어야 Enum.values합니까?

더 구체적으로, 어떤 형식의 for반복자를 사용해야하는지 :

for ( final MyEnum val: MyEnum.values( ) );

또는

for ( final MyEnum val: EnumSet.allOf( MyEnum.class ) );

어느 것이 더 효율적인지 내 질문에 대한 답을 얻지 못했기 때문에 내 자신의 테스트를 수행하기로 결정했습니다.

나는 반복을 통해 테스트 한 values(), Arrays.asList( values() )EnumSet.allOf( ). 다른 열거 형 크기에 대해이 테스트를 10,000,000 번 반복했습니다. 테스트 결과는 다음과 같습니다.

oneValueEnum_testValues         1.328
oneValueEnum_testList           1.687
oneValueEnum_testEnumSet        0.578

TwoValuesEnum_testValues        1.360
TwoValuesEnum_testList          1.906
TwoValuesEnum_testEnumSet       0.797

ThreeValuesEnum_testValues      1.343
ThreeValuesEnum_testList        2.141
ThreeValuesEnum_testEnumSet     1.000

FourValuesEnum_testValues       1.375
FourValuesEnum_testList         2.359
FourValuesEnum_testEnumSet      1.219

TenValuesEnum_testValues        1.453
TenValuesEnum_testList          3.531
TenValuesEnum_testEnumSet       2.485

TwentyValuesEnum_testValues     1.656
TwentyValuesEnum_testList       5.578
TwentyValuesEnum_testEnumSet    4.750

FortyValuesEnum_testValues      2.016
FortyValuesEnum_testList        9.703
FortyValuesEnum_testEnumSet     9.266

다음은 명령 줄에서 실행 된 테스트의 결과입니다. Eclipse에서 이러한 테스트를 실행했을 때 testValues. 기본적으로 EnumSet작은 열거 형 보다 작았습니다 . 성능 향상은 for ( val : array )루프 의 배열 반복기 최적화에서 비롯된다고 생각합니다 .

반면에, 바로 당신이 주변에 통과 java.util.Collection이 필요로 Arrays.asList( )까지 푼다 EnumSet.allOf특히 내가 어떤 주어진 코드베이스의 대부분이 될 것으로 판단 작은 열거를 위해.

그래서 나는 당신이 사용해야한다고 말하고 싶습니다.

for ( final MyEnum val: MyEnum.values( ) )

그러나

Iterables.filter(
    EnumSet.allOf( MyEnum.class ),
    new Predicate< MyEnum >( ) {...}
)

그리고 절대적으로 필요한 Arrays.asList( MyEnum.values( ) )에서만 사용하십시오 java.util.List.


가장 간단하고 명확한 접근 방식을 사용해야합니다. 대부분의 상황에서 성능을 고려해서는 안됩니다.

IMHO : 두 옵션 모두 개체를 만드는 것만 큼 잘 수행되지 않습니다. 첫 번째 경우에 하나, 두 번째 경우에 세 개. 성능상의 이유로 모든 값을 보유하는 상수를 생성 할 수 있습니다.


도 있습니다 Class.getEnumConstants()

내부적으로는 리플렉션을 통해 모든 values()enum 유형의 메서드를 호출 합니다 .


values()방금 가능한 모든 열거 값을 반복하려는 경우 방법은 더 명확하고 성능이 좋은 것입니다. 값은 클래스에 의해 캐시됩니다 (참조 Class.getEnumConstants()).

If you need a subset of values, you should use an EnumSet. Start with allOf() or noneOf() and add or remove values or use just of() as you need.


Not that I went through the entire implementation, but it seems to me that EnumSet.allOf() is basically using the same infrastructure as .values(). So I'd expect EnumSet.allOf() requires some (probably negligible) additional steps (see http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6276988).

It seems clear to me that the intended use of foreach is for(MyEnum val : MyEnum.values()) why do it differently? You will only confuse the maintenance programmer.

I mean, if you need a collection, you should get one. If you want to use a foreach, arrays are good enough. I'd even prefer arrays if pressed! Why wrap anything with anything, if what you got (array) is good enough? Simple things are normally faster.

In anyways, Peter Lawrey is right. Don't bother about the performance of this.. It's fast enough, and chances are there are million other bottlenecks that render that tiny theoretical performance difference as totally irrelevant (Don't see his "object creation" point though. To me the first example seems to be 100% OK).


EnumSet is not built with the intention to iterate over it's values. Rather it is implemented with the idea for it to represent a BitMap or BitMask efficiently (or reasonably efficient). The javadoc on EnumSet also states:

Enum sets are represented internally as bit vectors. This representation is extremely compact and efficient. The space and time performance of this class should be good enough to allow its use as a high-quality, typesafe alternative to traditional int-based "bit flags." Even bulk operations (such as containsAll and retainAll) should run very quickly if their argument is also an enum set.

Because only one single bit can represent a certain Enum value, it is also implemented as a Set and not as a List.

Now, it is probably also true that you can accomplish the same, and faster, using C-style bit masks (x^2), however it offers a more intuitive coding style and type safe use using enums, and it expands easily beyond the size of what an int or long can contain.

As such you can test that all bits are set as follows:

public class App {
  enum T {A,B}
  public static void main(String [] args) {
    EnumSet<T> t = EnumSet.of(T.A);
    t.containsAll(EnumSet.allOf(T.class));
  }
}

ReferenceURL : https://stackoverflow.com/questions/2464950/enum-values-vs-enumset-allof-which-one-is-more-preferable

반응형