2016-06-13 4 views
4

Java doc은 메소드 값() 및 entrySet()의 리턴 값이 맵에 의해 뒷받침된다고 말합니다. 따라서지도의 변경 사항은 세트에 반영되며 그 반대의 경우도 마찬가지입니다. 나는 이것이 정적 인 사본에 일어나기를 원하지 않는다. 본질적으로, 나는 많은 동시 작업을 내 DS에서 수행하기를 원합니다. 그러나 어떤 경우에는 정적 스냅 샷을 반복하고 싶습니다. 나는 정적 스냅 샷을 반복하고 싶다. 정적 스냅 샷을 반복하는 것이 동시에 업데이트되는 버전에 비해 빠를 것이라고 가정하고있다.Java : ConcurrentHashMap의 정적 스냅 샷을 만드는 방법?

+1

단일 정적 스냅 샷을 여러 번 반복 할 계획입니까, 아니면 기본적으로 당신의 계획입니까? (최종 Map.Entry <..., ...> 항목 : takeStaticSnapshot (map)) {doStuff(); }'? (후자의 경우, 암시 적으로 맵을 반복하지 않고 정적 스냅 샷을 만들 수있는 방법이 없다고 생각하기 때문에 물어볼 것입니다. 그리고 * 어느 경우에도 그러한 스냅 샷은 원자 적이지 않을 것임을 알고 있어야합니다.) – ruakh

+0

"스냅 샷"을 정의하십시오. 모든 복사본이 수행됩니까, 또는 일관성/원자/특정 시점에 있어야합니까? – Thilo

+1

"정적 스냅 샷을 반복하는 것이 동시에 업데이트되는 버전과 비교할 때 더 빠를 것이라고 가정합니다." 나는 snapshotting의 결론/노력으로 점프하기 전에 그것을 프로파일 링 할 것이다. – Thilo

답변

1

복사하기 만하면 새 HashMap은 원본과 독립적입니다.

Set<K> keySetCopy = new HashSet<>(map.keySet()); 
List<V> valuesCopy = new ArrayList<>(map.values()); 

그러나이 한번의 concurrentStructure을 통해 전체 반복을 취할 것입니다 만 다음 정적 스냅 샷 될 것이라고 마음. 따라서 하나의 전체 반복과 동일한 시간이 필요합니다.

7

복사 만하면 변경되지 않습니다.

Set<K> keySetCopy = new HashSet<>(map.keySet()); 
List<V> valuesCopy = new ArrayList<>(map.values()); 

모든 컬렉션 구현에는 제공된 컬렉션의 전체 데이터를 원본에서 지원하지 않고 새로 생성 된 복사본으로 복사하는 복사본 생성자가 있습니다.

참고 : 실제지도 항목이 여전히 원본지도에 속하고 원래 항목의 변경 사항이 사본에 반영되므로 entrySet()과 함께 작동하지 않습니다. entrySet()이 필요한 경우 동일한 기술을 사용하여 전체지도를 먼저 복사해야합니다.

Set<Entry<K,V>> entrySetCopy = new HashMap<>(map).entrySet(); 

이들 모두는 생성자에서 전체 반복을 필요로하므로 정적 스냅 샷이어야합니다. 내 지식으로는이 제한을 피하는 방법이 없습니다.

+2

이것은 여전히 ​​원래의 ConcurrentHashMap에 대한 반복을 포함하므로 OP의 요구 사항을 충족시키지 못할 수 있습니다. – ruakh

+0

@SeanPatrickFlyod 감사합니다. 나는 또 다른 의심을 품었다. 말하자면, 나는 값이 클래스 A의 객체 인 ConcurrentHashMap CHM을가집니다. 따라서 CHM의 값은 타입 A 객체의 포인터 중 하나를 p로 호출합니다. 그래서 ArrayList AL에 CHM.values ​​()를 복사하면됩니다. AL은 p를 포함합니다. 이제 개체 p의 속성을 변경하면 참조하십시오. 그것은 CHM에서 나중에 액세스 할 때 반영됩니다. 권리? – PHcoDer

+1

예, 포함 된 개체가 공유되므로 원본지도와 스냅 샷 (모듈 간 크로스 스레드 전파)에 변경 내용이 표시됩니다. – Thilo

관련 문제