Java 8에 불변의 컬렉션이없는 이유는 무엇입니까?


130

Java 팀은 ​​Java 8의 기능적 프로그래밍에 대한 장벽을 제거하면서 엄청난 노력을 기울였습니다. 특히, java.util Collections의 변경은 변환을 매우 빠른 스트리밍 작업으로 체인화하는 데 큰 도움이됩니다. 컬렉션에 퍼스트 클래스 함수와 함수 메소드를 추가하는 일이 얼마나 좋은지 고려할 때 왜 불변 컬렉션이나 불변 컬렉션 인터페이스를 제공하지 못한 것일까 요?

기존 코드를 변경하지 않고 Java 팀은 ​​언제든지 변경 가능한 인터페이스와 동일한 변경 불가능한 인터페이스를 추가하고 "set"메소드를 빼고 기존 인터페이스를 다음과 같이 확장 할 수 있습니다.

                  ImmutableIterable
     ____________/       |
    /                    |
Iterable        ImmutableCollection
   |    _______/    /          \   \___________
   |   /           /            \              \
 Collection  ImmutableList  ImmutableSet  ImmutableMap  ...
    \  \  \_________|______________|__________   |
     \  \___________|____________  |          \  |
      \___________  |            \ |           \ |
                  List            Set           Map ...

물론 List.add () 및 Map.put ()과 같은 작업은 현재 주어진 키에 대해 부울 값 또는 이전 값을 반환하여 작업의 성공 또는 실패 여부를 나타냅니다. 변경 불가능한 콜렉션은 팩토리와 같은 메소드를 처리하고 추가 된 요소 (현재 서명과 호환되지 않는)가 포함 된 새 콜렉션을 리턴해야합니다. 그러나 ImmutableList.append () 또는 .addAt () 및 ImmutableMap.putEntry ()와 같은 다른 메소드 이름을 사용하면 문제를 해결할 수 있습니다. 불변의 컬렉션으로 작업하는 것의 이점에 의해, 그 결과의 자세한 표시가 그 이상이되고, 타입 시스템은 잘못된 메소드 호출의 에러를 방지합니다. 시간이 지남에 따라 이전 방법은 더 이상 사용되지 않을 수 있습니다.

불변 컬렉션의 승리 :

  • 단순성-기본 데이터가 변경되지 않은 경우 코드에 대한 추론이 더 간단합니다.
  • 문서화-메소드가 변경 불가능한 콜렉션 인터페이스를 사용하는 경우 메소드가 해당 콜렉션을 수정하지 않을 것임을 알고 있습니다. 메소드가 변경 불가능한 콜렉션을 리턴하면 수정할 수 없음을 알고 있습니다.
  • 동시성-불변 컬렉션은 스레드간에 안전하게 공유 할 수 있습니다.

불변성을 가정 한 언어를 맛본 사람이라면 서부로 거센 돌연변이로 돌아 가기가 매우 어렵습니다. Clojure의 컬렉션 (시퀀스 추상화)에는 Java 8 컬렉션이 제공하는 모든 기능과 불변성 (스트림 대신 동기화 된 링크 목록으로 인해 추가 메모리와 시간을 사용하더라도)이 이미 있습니다. 스칼라는 전체 작업 세트로 변경 가능하고 변경 불가능한 컬렉션을 모두 가지고 있으며, 이러한 작업이 열성적이지만 .iterator를 호출하면 게으른 견해를 갖게됩니다 (게으르게 평가하는 다른 방법이 있습니다). 불변의 컬렉션없이 Java가 어떻게 계속 경쟁 할 수 있는지 모르겠습니다.

누군가 내가 이것에 대한 역사 나 토론을 지적 할 수 있습니까? 분명히 어딘가에 공개됩니다.


9
이와 관련하여-Ayende는 최근 벤치 마크와 함께 C #의 컬렉션 및 변경 불가능한 컬렉션에 대해 블로그를 작성했습니다. ayende.com/blog/tags/performance-tl;dr- 불변성은 느립니다 .
Oded

20
당신을있는 그대로 만 가지고, 계층 구조와 나는 당신에게 ImmutableList을 줄 수있는 다음은 많은 것들을 깰 수 그것을 기대하지 않는 때에 변경 const컬렉션
래칫 괴물

18
@Oded 불변성은 느리지 만 잠금입니다. 역사를 유지하는 것도 마찬가지입니다. 단순 / 수정은 많은 상황에서 속도가 가치가 있습니다. 작은 컬렉션의 경우 속도는 문제가되지 않습니다. Ayende의 분석은 기록, 잠금 또는 단순성이 필요하지 않으며 대규모 데이터 세트로 작업하고 있다는 가정을 기반으로합니다. 때때로 그것은 사실이지만, 항상 더 나은 것은 아닙니다. 트레이드 오프가 있습니다.
GlenPeterson

5
@GlenPeterson 그것이 바로 방어적인 사본 Collections.unmodifiable*()입니다. 그러나 그들이 불변 인 것으로 이것을 불변 인 것으로 취급하지 마십시오
ratchet freak

13
뭐라고? ImmutableList해당 다이어그램에서 함수가를 사용하면 사람들은 가변 List? 아니요, LSP를 매우 잘못 위반 한 것입니다.
Telastyn

답변:


113

변경 불가능한 컬렉션은 공유를 사용할 수 있어야합니다. 그렇지 않으면 모든 단일 작업이 완전히 다른 목록을 힙에 떨어 뜨립니다. Haskell과 같이 완전히 불변 인 언어는 적극적인 최적화 및 공유없이 놀라운 양의 쓰레기를 생성합니다. <50 개의 요소로만 사용할 수있는 컬렉션을 갖는 것은 표준 라이브러리에 넣을 가치가 없습니다.

더욱이, 불변 컬렉션은 종종 가변 컬렉션과 근본적으로 다른 구현을가집니다. 예를 들어 ArrayList, 효율적인 불변 ArrayList은 배열이 아닐 것입니다! Clojure는 32 IIRC를 사용하여 큰 분기 계수를 갖는 균형 트리로 구현해야합니다. 기능 업데이트를 추가하여 변경 가능한 컬렉션을 "불변"으로 만드는 것은 메모리 누수만큼 성능 버그입니다.

또한 Java에서는 공유가 불가능합니다. Java는 "최적화"를 공유하기 위해 너무 많은 제한 및 참조 평등에 대한 후크를 제공합니다. 목록의 요소를 수정할 수 있다면 아마도 그 목록의 다른 20 버전에서 요소를 수정했다는 것을 깨달을 것입니다.

이것은 또한 효율적인 불변성, 공유, 스트림 융합을 위해 매우 중요한 최적화의 거대한 클래스를 배제합니다. (FP 전도사들에게 좋은 슬로건을 만들었습니다)


21
내 예제는 불변 인터페이스에 대해 이야기했다 . Java 는 필요한 트레이드 오프를 만드는 인터페이스의 변경 가능 및 변경 불가능한 구현 모두를 제공 할 수 있습니다 . 가변 또는 불변을 선택하는 것은 프로그래머에게 달려 있습니다. 프로그래머는 언제 List vs. Set을 사용해야하는지 알아야합니다. 일반적으로 성능 문제가 발생할 때까지 변경 가능한 버전이 필요하지 않으며 빌더로만 필요할 수 있습니다. 어쨌든 불변의 인터페이스를 갖는 것이 그 자체로 승리 할 것입니다.
GlenPeterson

4
나는 당신의 대답을 다시 읽었으며 Java는 가변성 (예 : Java bean)의 근본적인 가정을 가지고 있으며 컬렉션은 빙산의 일각에 불과하며 그 팁을 조각하면 근본적인 문제를 해결할 수는 없다고 생각합니다. 유효한 포인트입니다. 이 답변을 수락하고 Scala 채택 속도를 높일 수 있습니다! :-)
GlenPeterson

8
불변 컬렉션에 공통 부품을 공유하는 기능이 필요하다는 것은 확실하지 않습니다. Java에서 가장 일반적인 불변의 유형, 불변의 문자 모음은 공유를 허용하는 데 사용되지만 더 이상은 아닙니다. 유용하게 중요한 것은 신속하게 데이터를 복사 할 수있는 기능입니다 StringStringBuffer, 새로운 불변으로 데이터를 복사 한 다음 조작하고 String. 세트 및리스트와 함께 이러한 패턴을 사용하는 것은 약간 변경된 인스턴스의 생성을 용이하게하도록 설계된 불변 유형을 사용하는 것만 큼 좋지만 여전히 더 나을 수 있습니다.
supercat

3
공유를 사용하여 Java에서 불변 콜렉션을 만드는 것은 전적으로 가능합니다. 컬렉션에 저장된 항목은 참조 이며 해당 참조는 변경 될 수 있습니다. 이러한 동작은 HashMap 및 TreeSet과 같은 기존 컬렉션을 이미 중단하지만 Java로 구현됩니다. 여러 컬렉션에 동일한 개체에 대한 참조가 포함되어 있으면 개체를 수정하면 모든 컬렉션에서 볼 때 변경 사항이 표시 될 것으로 예상됩니다.
솔로몬 오프의 비밀

4
jozefg, 구조 공유를 사용하여 JVM에서 효율적인 불변 콜렉션을 구현하는 것이 전적으로 가능합니다. Scala와 Clojure는 표준 라이브러리의 일부로 두 가지 구현 모두 Phil Bagwell의 HAMT (Hash Array Mapped Trie)를 기반으로합니다. BALANCED 트리로 불변 데이터 구조를 구현하는 Clojure에 대한 귀하의 진술은 완전히 잘못되었습니다.
sesm

77

변경 가능한 컬렉션은 변경 불가능한 컬렉션의 하위 유형이 아닙니다. 대신, 변경 가능 및 변경 불가능한 컬렉션은 읽기 가능한 컬렉션의 하위 항목입니다. 불행히도 "읽기", "읽기 전용"및 "불변"이라는 개념은 서로 다른 세 가지 의미를 갖지만 희미 해 보입니다.

  • 읽을 수있는 컬렉션 기본 클래스 또는 인터페이스 유형은 항목을 읽을 수 있으며 컬렉션을 수정하는 직접적인 수단을 제공하지는 않지만 참조를받는 코드가 수정을 허용하는 방식으로 코드를 캐스팅하거나 조작 할 수는 없다고 보장하지는 않습니다.

  • 읽기 전용 컬렉션 인터페이스에는 새로운 멤버가 포함되어 있지 않지만 컬렉션을 변경하거나 무언가에 대한 참조를받는 방식으로 참조를 조작 할 방법이 없음을 약속하는 클래스 만 구현해야합니다. 그렇게 할 수 있습니다. 그러나 컬렉션이 내부를 참조하는 다른 것으로 수정되지 않을 것이라고 약속하지는 않습니다. 읽기 전용 컬렉션 인터페이스는 변경 가능한 클래스에 의한 구현을 막을 수는 없지만 구현에서 파생 된 모든 구현 또는 클래스를 지정할 수 있습니다.이를 통해 돌연변이는 "불법적 인"구현 또는 구현의 파생물로 간주됩니다. .

  • 변경 불가능한 콜렉션은 참조가 존재하는 한 항상 동일한 데이터를 보유하는 콜렉션입니다. 특정 요청에 응답하여 항상 동일한 데이터를 반환하지 않는 변경 불가능한 인터페이스의 구현이 손상되었습니다.

강력하게 관련 가변 및 불변의 수집 구현하거나 동일한 "읽기"유형에서 파생하고 읽을 수있는 형식을 가지고 두 가지 유형의 포함이 때로는 유용하다 AsImmutable, AsMutableAsNewMutable방법을. 이러한 디자인은 컬렉션에서 데이터를 유지하려는 코드가 호출 할 수 있도록합니다 AsImmutable. 이 메소드는 콜렉션이 변경 가능한 경우 방어 사본을 작성하지만 이미 변경 불가능한 사본은 건너 뜁니다.


1
좋은 대답입니다. 불변 컬렉션은 스레드 안전성과 시간이 지남에 따라 추론 할 수있는 방법과 관련하여 매우 강력한 보증을 제공 할 수 있습니다. 읽기 / 읽기 전용 컬렉션은 그렇지 않습니다. 실제로 liskov의 대체 원칙을 따르기 위해 읽기 전용 및 불변은 아마도 최종 클래스와 개인 멤버가있는 추상 기본 유형이어야하며 파생 클래스가 유형에 의해 주어진 보증을 파괴 할 수 없도록해야합니다. 또는 컬렉션을 감싸거나 (읽기 전용) 항상 방어적인 복사본 (Immutable)을 가져 오는 완전 콘크리트 유형이어야합니다. 이것이 구아바 ImmutableList가하는 방식입니다.
Laurent Bourgault-Roy

1
@ LaurentBourgault-Roy : 봉인 된 유형과 상속 가능한 불변 유형 모두에 이점이 있습니다. 불법 파생 클래스가 불변을 깰 수 없도록하려면 봉인 형식은 상속되지 않는 클래스가 아무것도 제공하지 않는 반면에 봉인 형식은 보호합니다. 반면에, 데이터에 대해 알고있는 코드는 데이터 에 대해 전혀 모르는 형식보다 훨씬 더 간결하게 저장하기 위해 보유 할 수 있습니다. 예를 들어, int메소드 getLength()와로 시퀀스를 캡슐화하는 ReadableIndexedIntSequence 유형을 고려하십시오 getItemAt(int).
supercat

1
@ LaurentBourgault-Roy :가 주어지면 ReadableIndexedIntSequence모든 항목을 배열에 복사하여 배열 지원 불변 유형의 인스턴스를 생성 할 수 있지만 특정 구현이 단순히 길이와 ((long)index*index)>>24각 항목에 대해 16777216을 반환했다고 가정합니다 . 그것은 합법적 인 불변의 정수 시퀀스이지만, 배열에 복사하는 것은 시간과 메모리를 낭비하는 것입니다.
supercat

1
난 전적으로 동의합니다. 내 솔루션은 정확성을 제공 하지만 (최대 한 포인트까지) 큰 데이터 세트로 성능을 얻으려면 처음부터 불변성을위한 지속적인 구조와 디자인이 있어야합니다. 작은 컬렉션의 경우 때때로 불변의 사본을 가져 와서 벗어날 수 있습니다. 스칼라는 다양한 프로그램을 분석 한 결과 90 %의 목록이 10 개 이하의 항목임을 발견했습니다.
Laurent Bourgault-Roy

1
@ LaurentBourgault-Roy : 근본적인 문제는 사람들이 깨진 구현 또는 파생 클래스를 생성하지 않도록 신뢰하는지 여부입니다. 만약 그렇다면 인터페이스 /베이스 클래스가 변경 가능 / asImmutable 메소드를 제공하는 경우 성능을 여러 단계로 향상시킬 수 있습니다 (예 : asImmutable위에서 정의 된 시퀀스의 인스턴스 호출 비용과 구성 비용 비교) 불변의 배열 지원 카피]. 그러한 목적으로 정의 된 인터페이스를 갖는 것이 임시 접근 방식을 사용하는 것보다 낫다고 생각합니다. IMHO, 가장 큰 이유
supercat

15

Java Collections Framework는 java.util.Collections 클래스 에서 6 개의 정적 메소드를 통해 콜렉션의 읽기 전용 버전을 작성하는 기능을 제공합니다 .

누군가가 원래 질문에 대한 의견에서 지적했듯이 컬렉션을 수정할 수는 없지만 (컬렉션에서 멤버를 추가하거나 제거 할 수는 없음) 컬렉션이 참조하는 실제 객체 때문에 반환 된 컬렉션은 불변으로 간주되지 않을 수 있습니다 객체 유형이 허용하는 경우 수정할 수 있습니다.

그러나이 문제는 코드가 단일 개체를 반환하는지 또는 수정할 수없는 개체 컬렉션을 반환하는지에 관계없이 유지됩니다. 유형이 객체를 변경하도록 허용하는 경우 해당 유형의 디자인에서 결정이 내려졌으며 JCF 변경으로 인해 어떻게 변경되는지 알 수 없습니다. 불변성이 중요한 경우, 컬렉션의 멤버는 불변 타입이어야합니다.


4
래퍼에 래핑 된 항목이 이미 변경 불가능한지 여부에 대한 표시가 포함되어 immutableList있고 전달 된 사본의 사본 주위에 읽기 전용 랩퍼를 리턴하는 팩토리 메소드 가 포함되어 있으면 수정 불가능한 콜렉션의 디자인이 크게 향상되었을 것 입니다. 목록 전달 된리스트를 제외하고는 이미 불변이었다 . 그런 식으로 사용자 정의 형식을 만드는 것은 쉽지만 한 가지 문제는 다음과 같습니다. joesCollections.immutableList메서드가 반환 한 객체를 복사 할 필요가 없다는 것을 인식 할 방법이 없습니다 fredsCollections.immutableList.
supercat

8

이것은 매우 좋은 질문입니다. 나는 자바로 작성된 모든 코드 중 매일, 매일 24 시간 내내 전 세계 수백만 대의 컴퓨터에서 실행되는 아이디어를 즐긴다. 함수에 의해 반환됩니다. (그리고 이러한 컬렉션을 생성 한 후 밀리 초 동안 가비지 수집합니다.)

자바 프로그래머 unmodifiableCollection()의 일부는 Collections클래스 의 메소드 패밀리 가 있음을 알고 있지만 그중에서도 많은 사람들이 그것을 귀찮게하지 않습니다.

그리고 나는 그들을 비난 할 수 없습니다 : 읽기 쓰기 인 척하지만 UnsupportedOperationException'쓰기'메소드 중 하나를 호출하는 실수를 저지르면 던질 것입니다.

지금과 같은 인터페이스 Collection누락 될 것이다 add(), remove()그리고 clear()방법은 "ImmutableCollection"인터페이스되지 않을 것; "UnmodifiableCollection"인터페이스가됩니다. 사실, 불변성은 인터페이스의 특성이 아니라 구현의 특성이기 때문에 "ImmutableCollection"인터페이스는 절대 존재할 수 없습니다. 잘 모르겠습니다. 설명하겠습니다.

누군가 당신에게 그러한 읽기 전용 콜렉션 인터페이스를 건네 준다고 가정 해보십시오. 다른 스레드로 전달하는 것이 안전합니까? 그것이 정말로 불변 컬렉션을 나타내는 것을 알고 있다면, 그 대답은 "예"입니다. 불행히도 인터페이스이기 때문에 구현 방법을 알지 못하므로 대답은 아니요 여야합니다 . 알다시피, 실제로 변경할 수있는 컬렉션에 대한 수정 불가능한 (당신에게)보기 일 수 있습니다. (당신이 얻는 것과 같이 Collections.unmodifiableCollection()) 다른 스레드가 수정하는 동안 그것을 읽으려고하면 손상된 데이터를 읽습니다.

따라서 본질적으로 설명한 것은 "불변"이 아니라 "수정 불가능"콜렉션 인터페이스 세트입니다. "수정 불가능"은 그러한 인터페이스에 대한 참조를 가진 사람이 기본 컬렉션을 수정하지 못하고 기본 컬렉션이 반드시 변경 불가능하기 때문이 아니라 인터페이스에 수정 방법이 없기 때문에 단순히 방지된다는 것을 이해하는 것이 중요합니다. 기본 컬렉션은 변경 가능할 수 있습니다. 당신은 그것에 대한 지식과 통제력이 없습니다.

불변의 컬렉션을 가지려면 인터페이스가 아닌 클래스 여야합니다 !

이러한 불변 콜렉션 클래스는 최종적이어야하므로, 그러한 콜렉션에 대한 참조가 제공 될 때 자신이나 참조를 가진 다른 사람에 관계없이 불변 콜렉션으로 작동한다는 것을 알고 있습니다. 그것으로하십시오.

따라서 자바 (또는 다른 선언적 명령 언어)로 완전한 컬렉션 집합을 가지려면 다음이 필요합니다.

  1. 수정 불가능한 콜렉션 인터페이스 세트 .

  2. 수정 불가능한 인터페이스 를 확장하는 변경 가능한 콜렉션 인터페이스 세트 .

  3. 변경 가능한 인터페이스를 구현하는 변경 가능한 콜렉션 클래스 세트 와 확장 할 수없는 인터페이스도 있습니다.

  4. 수정 불가능한 인터페이스를 구현하지만 불변성을 보장하기 위해 대부분 클래스로 전달 되는 불변 콜렉션 클래스 세트 .

위의 모든 것을 재미있게 구현했으며 프로젝트에서 사용하고 있으며 매력처럼 작동합니다.

그들이 자바 런타임의 일부가 아닌 이유는 아마도 이것이 너무 많거나 너무 복잡하고 이해하기 어렵다고 생각했기 때문일 것입니다.

개인적으로, 나는 위에서 설명한 것이 충분하지 않다고 생각합니다. 구조상 불변성을 위한 가변 인터페이스 및 클래스 세트가 더 필요한 것 같습니다 . 접두사 "StructurallyImmutable"이 너무 길기 때문에 간단히 "Rigid"라고 할 수 있습니다.


좋은 지적입니다. 두 가지 세부 사항 : 1. 변경 불가능한 콜렉션에는 특정 메소드 서명이 필요합니다 (특히 목록을 예로 사용) List<T> add(T t).-모든 "mutator"메소드는 변경 사항을 반영하는 새 콜렉션을 리턴해야합니다. 2. 더 좋든 나쁘 든 인터페이스는 종종 서명 외에 계약 을 나타냅니다 . 직렬화가 그러한 인터페이스 중 하나입니다. 마찬가지로, 필적은 올바르게 구현하는 것이 필요 compareTo()제대로 작동 이상적와 호환 될 수있는 방법을 equals()하고 hashCode().
GlenPeterson

아, 나는 복사에 의한 변경 불변성을 염두에 두지 않았다. 위에서 쓴 것은 실제로 같은 방법이없는 일반 단순 불변 컬렉션을 나타냅니다 add(). 그러나 mutator 메소드가 불변 클래스에 추가되면 불변 클래스 반환해야한다고 가정합니다 . 따라서 거기에 숨어있는 문제가 있다면 그것을 볼 수 없습니다.
Mike Nakis 2016 년

구현이 공개되어 있습니까? 나는이 달 전에 물어야했다. 어쨌든, 내 위치 : github.com/GlenKPeterson/UncleJim
GlenPeterson

4
Suppose someone hands you such a read-only collection interface; is it safe to pass it to another thread?누군가가 변경 가능한 콜렉션 인터페이스의 인스턴스를 전달한다고 가정하십시오. 메소드를 호출해도 안전합니까? 구현이 영원히 반복되지 않거나 예외를 던지거나 인터페이스 계약을 완전히 무시하지 않는다는 것을 모릅니다. 불변 컬렉션에 특별히 이중 표준이있는 이유는 무엇입니까?
Doval

1
변경 가능한 인터페이스에 대한 당신의 추론이 잘못되었습니다. 변경 불가능한 인터페이스의 변경 가능한 구현을 작성한 다음 중단됩니다. 확실한. 그러나 계약을 위반하는 것은 귀하의 잘못입니다. 그만해 SortedSet부적합한 구현으로 세트를 서브 클래 싱 함으로써 a를 깨는 것과 다르지 않습니다 . 또는 일관되지 않은 전달 Comparable. 원한다면 거의 모든 것이 깨질 수 있습니다. 이것이 바로 @Doval이 "이중 표준"으로 의미 한 것 같습니다.
maaartinus

2

불변 콜렉션은 서로에 비해 깊이 재귀적일 수 있으며, 오브젝트 동등성이 secureHash에 의한 경우 비합리적으로 비효율적이지 않을 수 있습니다. 이것을 머클 숲이라고합니다. 컬렉션별로 또는 정렬 된 맵을위한 (자체 균형 이진) AVL 트리와 같이 일부에있을 수 있습니다.

이 컬렉션의 모든 Java 객체에 고유 ID 또는 해시 할 비트 스트링이 없으면 컬렉션 자체를 고유하게 해시 할 수 없습니다.

예 : 4x1.6ghz 랩톱에서 500K HashMap ops 또는 3M ops와 비교하여 1 해시주기 (최대 55 바이트)에 해당하는 가장 작은 크기의 초당 200K sha256을 실행할 수 있습니다. 초당 200K / log (collectionSize) 새 컬렉션은 데이터 무결성과 익명의 글로벌 확장 성이 중요한 일부에 충분히 빠릅니다.


-3

공연. 특성상 컬렉션은 매우 클 수 있습니다. 단일 요소를 삽입하는 대신 1001 개의 요소를 사용하여 1000 개의 요소를 새 구조에 복사하는 것은 매우 끔찍합니다.

동시성. 여러 개의 스레드가 실행중인 경우 스레드가 시작될 때 12 시간 전에 전달 된 버전이 아닌 현재 버전의 콜렉션을 가져 오려고 할 수 있습니다.

저장. 다중 스레드 환경에서 변경 불가능한 오브젝트를 사용하면 수명주기의 다른 지점에서 수십 개의 "동일한"오브젝트 사본을 만들 수 있습니다. Calendar 또는 Date 객체에는 중요하지 않지만 10,000 개의 위젯 모음이 있으면 사용자가 죽습니다.


12
변경 불가능한 콜렉션은 Java와 같이 광범위한 변경 가능성으로 인해 공유 할 수없는 경우 복사 만 필요합니다. 일반적으로 불변 컬렉션은 잠금이 필요하지 않기 때문에 동시성이 더 쉽습니다. 가시성을 위해 항상 변경 불가능한 컬렉션에 대한 변경 가능한 참조를 가질 수 있습니다 (OCaml에서 일반적). 공유를 통해 업데이트는 기본적으로 무료입니다. 변경 가능한 구조보다 대수적으로 더 많은 할당을 수행 할 수 있지만 업데이트시 만료 된 많은 하위 오브젝트를 즉시 해제하거나 재사용 할 수 있으므로 메모리 오버 헤드가 더 높은 것은 아닙니다.
Jon Purdy

4
커플 문제. Clojure와 Scala의 컬렉션은 모두 변경할 수 없지만 경량 사본을 지원합니다. 요소 1001을 추가한다는 것은 33 개 미만의 요소를 복사하고 몇 가지 새로운 포인터를 만드는 것을 의미합니다. 스레드간에 변경 가능한 컬렉션을 공유하면 변경시 모든 종류의 동기화 문제가 발생합니다. "remove ()"와 같은 작업은 악몽입니다. 또한 변경 불가능한 콜렉션을 변경 가능하게 빌드 한 다음 변경 불가능한 버전으로 한 번 복사하여 스레드간에 공유 할 수 있습니다.
GlenPeterson

4
불변성에 대한 논쟁으로 동시성을 사용하는 것은 드문 일입니다. 복제도 마찬가지입니다.
Tom Hawtin-tackline

4
여기서 아래로 내려가는 투표에 대해 약간 혼란스러워했습니다. OP는 불변 컬렉션을 구현하지 않은 이유를 물었고 질문에 대한 답변을 제공했습니다. 아마도 패션을 의식하는 사람들 중 유일하게 받아 들일 수있는 대답은 "실수했기 때문"입니다. 실제로 실제로는 우수한 BigDecimal 클래스를 사용하여 큰 코드 덩어리를 리팩터링 해야하는 경험이 있습니다. 순수를 수정하기 위해 두 배 더하기 약간의 엉망으로 인한 불변성으로 인해 불완전한 성능으로 인해 순수하지 않기 때문입니다.
제임스 앤더슨

3
@JamesAnderson : 당신의 대답에 대한 나의 문제 : "성능"-당신은 실제 불변 컬렉션은 항상 당신이 묘사 한 문제를 피하기 위해 어떤 형태의 공유와 재사용을 구현한다고 말할 수 있습니다. "Concurrency"-인수가 "변경 가능을 원하면 변경할 수없는 개체가 작동하지 않습니다"로 요약됩니다. "동일한 최신 버전"이라는 개념이 있다면, 그 자체로, 또는 그 소유물을 변경해야합니다. 그리고 "Storage"에서, 변경 가능성이 때때로 바람직하지 않다고 말하는 것 같습니다.
jhominal
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.