불변 컬렉션과 수정할 수 없는 컬렉션
Collections Framework 개요부터:
컬렉션( 「」등).
add
,remove
★★★★★★★★★★★★★★★★★」clear
)는 수정 불능이라고 불립니다.수정할 수 없는 컬렉션은 수정할 수 있습니다.이 에서는 이 을 보증합니다.
Collection
오브젝트는 불변이라고 합니다.불변하지 않는 컬렉션은 변경할 수 있습니다.
나는 그 차이를 이해할 수 없다.
여기서 수정할 수 없는 것과 불변의 것의 차이점은 무엇입니까?
수정할 수 없는 컬렉션은 다른 코드가 여전히 액세스할 수 있는 수정 가능한 컬렉션의 래퍼입니다.따라서 수정할 수 없는 컬렉션에 대한 참조만 있는 경우 변경할 수 없지만 내용이 변경되지 않을 수 있습니다.
불변의 컬렉션은 그 어떤 것도 컬렉션을 더 이상 변경할 수 없음을 보증합니다.수정 가능한 컬렉션을 랩하는 경우 다른 코드가 수정 가능한 컬렉션에 액세스하지 않도록 합니다.컬렉션에 참조가 포함되어 있는 오브젝트는 어떤 코드도 변경할 수 없지만 오브젝트 자체는 여전히 변경할 수 있으며, 이 경우 의 불변의 컬렉션을 생성할 수 있습니다.StringBuilder
그 물체들을 "거짓말"하지는 않습니다.
기본적으로는 다른 코드가 뒤에서 컬렉션을 변경할 수 있는지 여부에 따라 달라집니다.
으로는 ★★★★★★★★★★★★★★.unModifiable
수집은 보기이므로 간접적으로 수정 가능한 다른 참조에서 여전히 '수정'될 수 있습니다.또한 annother 컬렉션의 읽기 전용 뷰로서 소스 컬렉션이 변경되면 UnModifyable Collection은 항상 최신 값으로 표시됩니다.
, <고객명>님immutable
컬렉션은 다른 컬렉션의 읽기 전용 복사본으로 취급할 수 있으며 수정할 수 없습니다.이 경우 소스 컬렉션이 변경되면 불변의 컬렉션은 변경을 반영하지 않습니다.
다음은 이 차이를 시각화하는 테스트 사례입니다.
@Test
public void testList() {
List<String> modifiableList = new ArrayList<String>();
modifiableList.add("a");
System.out.println("modifiableList:"+modifiableList);
System.out.println("--");
//unModifiableList
assertEquals(1, modifiableList.size());
List<String> unModifiableList=Collections.unmodifiableList(
modifiableList);
modifiableList.add("b");
boolean exceptionThrown=false;
try {
unModifiableList.add("b");
fail("add supported for unModifiableList!!");
} catch (UnsupportedOperationException e) {
exceptionThrown=true;
System.out.println("unModifiableList.add() not supported");
}
assertTrue(exceptionThrown);
System.out.println("modifiableList:"+modifiableList);
System.out.println("unModifiableList:"+unModifiableList);
assertEquals(2, modifiableList.size());
assertEquals(2, unModifiableList.size());
System.out.println("--");
//immutableList
List<String> immutableList=Collections.unmodifiableList(
new ArrayList<String>(modifiableList));
modifiableList.add("c");
exceptionThrown=false;
try {
immutableList.add("c");
fail("add supported for immutableList!!");
} catch (UnsupportedOperationException e) {
exceptionThrown=true;
System.out.println("immutableList.add() not supported");
}
assertTrue(exceptionThrown);
System.out.println("modifiableList:"+modifiableList);
System.out.println("unModifiableList:"+unModifiableList);
System.out.println("immutableList:"+immutableList);
System.out.println("--");
assertEquals(3, modifiableList.size());
assertEquals(3, unModifiableList.size());
assertEquals(2, immutableList.size());
}
산출량
modifiableList:[a]
--
unModifiableList.add() not supported
modifiableList:[a, b]
unModifiableList:[a, b]
--
immutableList.add() not supported
modifiableList:[a, b, c]
unModifiableList:[a, b, c]
immutableList:[a, b]
--
가장 큰 차이점은 가변 컬렉션의 소유자가 컬렉션에 대한 액세스를 다른 코드에 제공하려고 할 수 있지만 다른 코드가 컬렉션을 수정할 수 없도록 하는 인터페이스를 통해 해당 액세스를 제공할 수 있다는 것입니다(그 기능은 소유 코드에 예약되어 있습니다.따라서 컬렉션은 불변하지 않지만 특정 사용자는 컬렉션을 변경할 수 없습니다.
Oracle의 Java Collection Wrapper 튜토리얼에는 다음과 같은 내용이 있습니다(강조 추가).
변경할 수 없는 래퍼에는 주로 다음 두 가지 용도가 있습니다.
- 컬렉션은 일단 구축되면 불변으로 한다.이 경우 백업 컬렉션에 대한 참조를 유지하지 않는 것이 좋습니다.이것은 절대적으로 불변성을 보장한다.
- 특정 클라이언트가 데이터 구조에 대한 읽기 전용 액세스를 허용합니다. 백업 컬렉션에 대한 참조는 유지하되 래퍼에 대한 참조는 전달합니다. 이렇게 하면 사용자가 전체 액세스를 유지하는 동안 클라이언트는 볼 수 있지만 수정할 수 없습니다.
Java™ 튜토리얼을 인용하려면:
랩된 컬렉션에 기능을 추가하는 동기화 래퍼와는 달리 변경할 수 없는 래퍼는 기능을 빼앗습니다.특히 컬렉션을 변경하는 모든 작업을 대행 수신하여 Unsupported Operation을 실행함으로써 컬렉션을 변경할 수 없게 됩니다.예외입니다.변경할 수 없는 래퍼에는 주로 다음 두 가지 용도가 있습니다.
컬렉션은 일단 구축되면 불변으로 한다.이 경우 백업 컬렉션에 대한 참조를 유지하지 않는 것이 좋습니다.이것은 절대적으로 불변성을 보장한다.
특정 클라이언트가 데이터 구조에 대한 읽기 전용 액세스를 허용합니다.백업 컬렉션에 대한 참조는 유지하되 래퍼에 대한 참조는 전달합니다.이렇게 하면 사용자가 전체 액세스를 유지하는 동안 클라이언트는 볼 수 있지만 수정할 수 없습니다.
(내 것을 제외)
이게 진짜 요약이 되네요.
JDK를 Unmodifiable*
vs guavaImmutable*
퍼포먼스에도 차이가 있습니다.불변 컬렉션은 일반 컬렉션 주위에 래퍼가 아닌 경우(JDK 실장은 래퍼) 고속으로 메모리 효율이 향상됩니다.guava 팀을 예로 들겠습니다.
JDK는 Collections.unmodify XXX 메서드를 제공하지만 이러한 메서드는 다음과 같습니다.
<...>
- 비효율적: 데이터 구조에는 동시 수정 검사, 해시 테이블의 여유 공간 등을 포함한 가변 컬렉션의 오버헤드가 여전히 남아 있습니다.
// normal list
List list1 = new ArrayList();
list1.add(1);
// unmodifiable list
List list2 = Collections.unmodifiableList(list1);
// immutable list
List list3 = Collections.unmodifiableList(new ArrayList<>(list1));
list1.add(2);
list1.add(3);
System.out.println(list1);
System.out.println(list2);
System.out.println(list3);
출력:
[1, 2, 3]
[1, 2, 3]
[1]
객체는 구성된 후 상태를 변경할 수 없는 경우 불변으로 간주됩니다.컬렉션의 불변 인스턴스를 만든 후에는 해당 인스턴스에 대한 참조가 존재하는 한 동일한 데이터가 유지됩니다.
불변의 컬렉션의 장점 중 하나는 자동으로 스레드 세이프가 된다는 것입니다.불변의 객체를 포함하는 컬렉션은 구성 후 자동으로 스레드 세이프됩니다.이러한 컬렉션을 작성한 후 여러 스레드에 전달하면 모든 스레드가 일관된 보기를 볼 수 있습니다.
그러나 불변의 객체의 집합은 불변의 객체의 집합과 같지 않습니다.포함된 요소가 변경 가능한 경우 수집이 일관되지 않게 동작하거나 해당 내용이 변경되는 것처럼 보일 수 있습니다.
간단히 말하면, 불변성을 조금 더하면 불변성을 얻을 수 있습니다.그리고 불변의 무언가에 약간의 불변성을 더하면 불변성을 얻을 수 있습니다.
변경할 수 없는 것과 변경할 수 없는 것은 다릅니다.
불변의 컬렉션은 Collections.unmodifyable...와 동일하게 동작합니다.포장지단, 이러한 컬렉션은 래퍼가 아닙니다.데이터를 변경하려고 하면 예외가 발생하는 클래스에서 구현되는 데이터 구조입니다.
목록을 생성하여 Collections.unmodifyableList 메서드에 전달하면 수정할 수 없는 보기가 나타납니다.기본 목록은 여전히 수정할 수 있으며, 수정 내용은 반환된 목록을 통해 볼 수 있으므로 실제로 불변경은 없습니다.
이 동작을 나타내려면 목록을 생성하여 Collections.unmodifyableList에 전달합니다.수정할 수 없는 목록에 직접 추가하려고 하면 Unsupported Operation이 발생합니다.예외가 느려집니다.
그러나 원래 목록을 변경하면 오류가 생성되지 않고 수정 불가능한 목록이 수정되었습니다.
이 경우 컬렉션을 작성한 후 불변으로 만들려면 백업 컬렉션에 대한 참조를 유지하지 않는 것이 좋습니다.이것은 절대적으로 불변성을 보장한다.
또한 특정 클라이언트가 데이터 구조에 대한 읽기 전용 액세스를 허용합니다.백업 컬렉션에 대한 참조를 유지할 수 있지만 래퍼에 대한 참조를 배포할 수 있습니다.이렇게 하면 사용자가 전체 액세스를 유지하는 동안 클라이언트는 볼 수 있지만 수정할 수 없습니다.
따라서 불변의 컬렉션에는 불변의 객체가 포함될 수 있으며, 불변의 객체가 포함될 경우 컬렉션은 불변의 것도 스레드 세이프도 아닙니다.
위에서 설명한 바와 같이 수정 불가능한 컬렉션은 변경할 수 없기 때문에 수정 불가능한 컬렉션에 다른 오브젝트에 의해 참조되는 기본 위임 컬렉션이 있고 해당 오브젝트에 의해 변경되는 경우 변경할 수 없기 때문에 변경할 수 없습니다.
불변의 것에 대해서는 잘 정의되어 있지 않습니다.단, 일반적으로 오브젝트는 "변경되지 않는다"는 의미이지만 재귀적으로 정의해야 합니다.예를 들어 인스턴스 변수가 모두 프리미티브이고 메서드가 모두 인수를 포함하지 않고 프리미티브를 반환하는 클래스에서 불변성을 정의할 수 있습니다.그런 다음 메서드는 인스턴스 변수를 불변하게 하고 모든 메서드에 불변의 값을 반환하는 인수를 포함할 수 있도록 합니다.메서드는 시간이 지남에 따라 동일한 값을 반환하도록 보장해야 합니다.
그렇게 할 수 있다고 가정하면 스레드 세이프라는 개념도 있습니다.또, 불변(또는 시간에 따라 변화하지 않음)은 스레드 세이프도 의미한다고 생각할 수 있습니다.그러나 그것은 사실이 아니며 내가 여기서 말하고 있는 다른 답변에서는 아직 언급되지 않은 요점이다.항상 같은 결과를 반환하지만 스레드 세이프가 아닌 불변의 개체를 구성할 수 있습니다.이를 확인하기 위해 시간이 지남에 따라 추가 및 삭제를 유지함으로써 불변의 컬렉션을 구축한다고 가정합니다.여기서 불변의 컬렉션은 내부 컬렉션(시간에 따라 변경될 수 있음)을 확인한 후 컬렉션 작성 후 추가 또는 삭제된 요소를 내부적으로 추가 및 삭제함으로써 해당 요소를 반환합니다.컬렉션은 항상 동일한 요소를 반환하지만 값이 변경되지 않는다는 이유만으로 스레드 안전하지는 않습니다.
이제 불변의 오브젝트를 스레드 세이프가 되어 변경되지 않는 오브젝트로 정의할 수 있습니다.일반적으로 이러한 클래스로 이어지는 불변의 클래스 작성에 관한 가이드라인이 있습니다만, 예를 들어 위의 "스냅샷" 컬렉션 예에서 설명한 바와 같이 스레드 안전에 주의를 기울여야 하는 불변의 클래스를 작성하는 방법이 있을 수 있습니다.
Java™ 튜토리얼에는 다음과 같이 표시됩니다.
랩된 컬렉션에 기능을 추가하는 동기화 래퍼와는 달리 변경할 수 없는 래퍼는 기능을 빼앗습니다.특히 컬렉션을 변경하는 모든 작업을 대행 수신하여 Unsupported Operation을 실행함으로써 컬렉션을 변경할 수 없게 됩니다.예외.변경할 수 없는 래퍼에는 주로 다음 두 가지 용도가 있습니다.
컬렉션은 일단 구축되면 불변으로 한다.이 경우 백업 컬렉션에 대한 참조를 유지하지 않는 것이 좋습니다.이것은 절대적으로 불변성을 보장한다.
특정 클라이언트가 데이터 구조에 대한 읽기 전용 액세스를 허용합니다.백업 컬렉션에 대한 참조는 유지하되 래퍼에 대한 참조는 전달합니다.이렇게 하면 사용자가 전체 액세스를 유지하는 동안 클라이언트는 볼 수 있지만 수정할 수 없습니다.
그 차이를 이해하기에 충분한 설명이라고 생각합니다.
수정 불가와 불변의 컬렉션
수정 가능한 맵 만들기
Map<String, String> modifiableMap = new HashMap();
modifiableMap.put(“1”,”one”);
modifiableMap.put(“2”,”two”);
modifiableMap.put(“3”,”three”);
modifyableMap에서 unmodifyMap을 만듭니다.
Map<String,String> unmodifiableMap = Collections.unmodifiableMap(modifiableMap);
unmodifiableMap.put(“4”,”Four”) ==>Exception
modifiableMap.put(“4”,”Four”); ==>Allowed, this will also reflect now in the unmodifiableMap , because unmodifiableMap() returns a wrapper around modifiableMap.
unmutableMap out of modifyableMap을 만듭니다.
Map<String,String> immutableMap = Collections.immutableMap(modifiableMap);
immutableMap.put(“5”,”Five”) ==>Exception
modifiableMap.put(“5”,”Five”); ==>Allowed, BUT this will NOT reflect now in the immutableMap, because immutableMap() returns a copy of the modifiableMap.
원본 개체를 변경하여 수정할 수 없는 컬렉션(개체)을 변경할 수 있습니다.참조를 사용하여 가능합니다.
Java는 수정할 수 없는 맵을 작성하기 위한 몇 가지 방법을 제공합니다.
Collections.unmodifiableMap()
- 자바 9
Map.of()
,Map.ofEntries()
언급URL : https://stackoverflow.com/questions/8892350/immutable-vs-unmodifiable-collection
'IT이야기' 카테고리의 다른 글
fgets() 입력에서 말미의 줄바꿈 문자를 제거하는 중 (0) | 2022.05.31 |
---|---|
기존 HTML의 데이터를 사용하여 Vue 뷰 모델 로드 (0) | 2022.05.31 |
Vuej 및 Vuex가 업데이트된 어레이를 렌더링하지 않음 (0) | 2022.05.31 |
GCC 치명적 오류: stdio.h: 해당 파일 또는 디렉토리가 없습니다. (0) | 2022.05.31 |
구성 요소가 렌더링하기 전에 vuex에 저장소를 채우는 방법 (0) | 2022.05.30 |