2017-01-17 13 views
1

반복마다 새로운 객체를 생성하지 않는 EnumMap을 반복하는 방법이 있습니까? 엔트리 세트의 iterator는 매번 새로운 엔트리를 리턴한다. 내가 볼 수있는 유일한 방법은 당신의 코드는 않습니다,반복마다 새 객체 생성을 발생시키지 않는 EnumMap을 반복합니다.

for(K k: map.keySet()) 
    foo(k, map.get(k)); 

이이

public Map.Entry<K,V> next() { 
     if (!hasNext()) 
      throw new NoSuchElementException(); 
     lastReturnedEntry = new Entry(index++); 
     return lastReturnedEntry; 
    } 
+0

그리고 나만의 해결책은 무엇이 좋을까요? – RealSkeptic

+1

'for (V value : map.values ​​()) foo (value);'는 어떨까요? 값을 검색하는 것 이외의 다른 용도로 키를 사용하는 것 같지 않습니다. – VGR

+0

@ VGR 공정한 포인트. 나도 열쇠가 필요해. – hawk

답변

2

우선, iterator가 두 개의 객체로 구성된 튜플을 반환하도록하려는 것 같습니다.

자바에서는 이것을 다른 객체로 래핑하는 유일한 방법이 있습니다. (작성 당시에는 그렇습니다.) 따라서 이터레이터는 키와 값 이외의 객체를 반환해야합니다. 이 객체는 next() 호출이 반환되기 전에 생성되어야합니다. 염두에 제약 조건으로

세 가지 그럴듯한 경로가 데리고있다 :

  1. put()에이 항목 개체를 만듭니다.
  2. entrySet()에 첫 번째 반복에서 항목 개체를 만듭니다 (이후에 캐시합니다).
  3. 모든 반복마다 entrySet()에 새 항목 개체를 만듭니다.

내장 된 EnumMap은 구현이 가장 간단하고 항목을 반복 할 필요가 없을 때 가장 경제적 인 이유 때문에 옵션 3을 선택했습니다. 단점은 두 번 이상 반복해야하는 경우 다른 솔루션보다 많은 개체를 생성한다는 것입니다.

옵션 1은 구현하기가 간단하지만 액세스하려는 적이없는 경우에도 맵에 항목을 추가 할 때마다 명백한 오버 헤드가 있습니다.

마지막으로, 옵션 2는 약간의 코드 복잡성과 반복을 반복하고 더 많은 요소를 추가 할 때 몇 가지 중요한 경우를 포함하지만 이론상 최고의 메모리 프로파일을 제공합니다.

여러 반복의 메모리 오버 헤드가 응용 프로그램에서 문제가되는 것으로 판명되면 옵션 2를 쉽게 구현할 수 있지만 대부분의 경우이 차이가 눈에 띄게 될 것입니다.

p.s.: 관용적 인 해결책에서 빠져 나와 약간 미친 영역으로 들어갈 수 있다면 모든 항목에 동일한 Map.Entry 인스턴스를 다시 사용할 수 있습니다. 이것은 분명히 우리가 Map.Entry에서 기대하는 것과 모순 될 것입니다. 그러나 그것은 당신에게 가장 작은 메모리 할당 오버 헤드를 제공하고 간단한 반복 시나리오에서 벗어날 수 있습니다. 빠른 제품으로 끝날지라도 누구나 추측 할 수 있습니다. 측정해야합니다.

0

첫째는 EntrySet에서 다음 반복자의 구현이 EnumMap에 대해 구체적이고 명확히하기 위해 때마다 개체를 만들 수 없습니다. 기존 개체에 참조 만 가져옵니다.

for (Map.Entry<K, V> entry : map.entrySet()) { 
    // use entry.getKey() and entry.getValue() 
} 

또는 자바 8 버전 :

map.forEach((k, v) -> {...}); 
+0

저는 여기서 EnumMap에 관해 아주 구체적으로 말하고 있습니다. entrySet 반복자는 다음과 같습니다. public Map.Entry next() { if (! hasNext()) throw new NoSuchElementException(); lastReturnedEntry = 새 항목 (색인 ++); return lastReturnedEntry; } – hawk

1

나는 반사적으로 객체 생성에 대한 우려의이 수준의 정당성을 의심

예, 더 나은 방법이있다. 그러나 객체 생성을 피하는 것이 정말로 중요하다면 열거 형 상수의 배열을 유지하고 각각에 대해 map.contains(...)을 테스트 할 수 있습니다. 성능을 비교하는 방법을 보려면이 테스트를 수행해야합니다.

+0

예 개체 생성이 문제인지 여부는 문제가되지 않습니다. 열거 형 배열을 유지하는 데 의존하지 않고이 작업을 수행하는 관용적 인 방법을 찾고 있습니다. – hawk

+0

왜 열거 형 배열을 주변에 두어야합니까? – marstran

+0

@marstran 상수의'int' 서수를 취하는'EnumMap # contains (...)'형식이 없기 때문에. –