programing

Java Map이 컬렉션을 확장하지 않는 이유

prostudy 2022. 5. 4. 21:32
반응형

Java Map이 컬렉션을 확장하지 않는 이유

라는 사실에 놀랐다.Map<?,?>a가 아니다.Collection<?>.

나는 그것이 그렇게 선언된다면 많은 의미가 있을 것이라고 생각했다.

public interface Map<K,V> extends Collection<Map.Entry<K,V>>

결국 aMap<K,V>의 수집품이지 않은가?

그래서 그렇게 시행되지 않는 이유가 있을까?


클레투스에게 가장 권위 있는 대답을 해줘서 고맙지만, 나는 아직도 왜 그런지 궁금하다, 만약 당신이 이미 a를 볼 수 있다면.Map<K,V>로서Set<Map.Entries<K,V>>( 경유)entrySet()(), 대신 인터페이스만 확장하는 것이 아니다.

만약Mapa이다Collection, 요소들은 무엇인가?유일한 합리적인 대답은 "키-값 쌍"이다.

바로 그거야interface Map<K,V> extends Set<Map.Entry<K,V>>정말 좋을 거야!

그러나 이는 매우 제한적(특별히 유용하지는 않음)을 제공한다.Map추상화

하지만 만약 그렇다면 왜 그럴까?entrySet인터페이스에 의해 지정되었는가?어떻게든 유용할 것이다(그리고 나는 그 입장을 주장하기 쉽다고 생각한다!).

주어진 키 맵이 어떤 값에 매핑되는지 물어볼 수도 없고, 어떤 값에 매핑되는지 모르는 상태에서 해당 키의 항목을 삭제할 수도 없다.

내 말은 그게 다가 아니라는 거야.Map! 그것은 다른 모든 방법을 유지할 수 있고 유지해야 한다.entrySet, 그것은 지금 중복이다)!

Java Collections API Design FAQ:

맵이 수집을 확장하지 않는 이유

이건 계획적인 거였어.우리는 매핑이 집합이 아니고 집합이 매핑이 아니라고 느낀다.따라서 Map이 Collection 인터페이스(또는 그 반대)를 확장하는 것은 이치에 맞지 않는다.

지도가 집합인 경우 요소란?유일한 합리적인 답은 "키-값 쌍"이지만, 이것은 매우 제한적이고 특별히 유용하지 않은 지도 추상화를 제공한다.주어진 키 맵이 어떤 값에 매핑되는지 물어볼 수도 없고, 어떤 값에 매핑되는지 모르는 상태에서 해당 키의 항목을 삭제할 수도 없다.

맵을 확장하기 위해 컬렉션을 만들 수 있지만, 이에 따라 키가 무엇인가?라는 의문이 제기된다.정말 만족스러운 대답은 없고, 억지로 사람을 억지로 끌어내는 것은 부자연스러운 인터페이스로 이어진다.

지도는 집합(키, 값 또는 쌍의 집합)으로 볼 수 있으며, 이러한 사실은 지도(keySet, entrySet, value)의 세 가지 "수집 보기 작업"에 반영된다.원칙적으로 리스트를 요소에 대한 지도 매핑 지수로 볼 수 있지만, 이것은 리스트에서 요소를 삭제하면 삭제된 요소 이전의 모든 요소와 연관된 키가 변경되는 불쾌한 속성을 가지고 있다.그래서 리스트에 지도 보기 작업이 없는 겁니다.

업데이트: 나는 인용문이 대부분의 질문에 답한다고 생각한다.출품작의 집합이 특별히 유용한 추상화가 아니라는 점을 강조할 가치가 있다.예를 들면 다음과 같다.

Set<Map.Entry<String,String>>

다음을 허용한다.

set.add(entry("hello", "world"));
set.add(entry("hello", "world 2"));

(이른바 anentry()a를 생성하는 방법Map.Entry인스턴스)

Maps는 이를 위반할 수 있도록 고유한 키를 요구한다.또는 고유한 키를Set출품작 중에서, 그것은 사실 그렇지 않다.Set대체적으로A이다.Set한층 더 제한하여

논쟁의 여지없이 당신은 그 말을 할 수 있다.equals()/hashCode()에 대한 관계.Map.Entry순전히 열쇠를 쥐고 있었지만 그것조차도 문제가 있다.더 중요한 것은, 그것이 정말로 어떤 가치를 더하고 있는가?당신은 일단 당신이 코너 케이스를 보기 시작하면 이 추상화가 무너지는 것을 발견할지도 모른다.

주목할 필요가 있다.HashSet실제로 구현되는 것은HashMap다른 길이 아니다.이것은 순전히 실행 세부사항이지만 그럼에도 불구하고 흥미롭다.

의 주된 이유.entrySet()존재한다는 것은 키를 가로지른 다음 키를 조회할 필요가 없도록 통과를 단순화하는 것이다....라는 것을 명백한 증거로 받아들이지 마라.Map~이어야 한다Set출품작(임호) 중에서.

질문을 상당히 직접적으로 다루는 여러 해답을 얻었지만, 조금 뒤로 물러서서 질문을 좀 더 전반적으로 보는 것이 유용할 것 같다.즉, 자바 도서관이 어떻게 작성되는지를 구체적으로 보지 않고, 왜 그렇게 작성되는지를 살펴보는 것이다.

여기서 문제는 상속이 단지 하나의 공통성만을 본떠 만든다는 것이다.둘 다 '집합 비슷한' 것처럼 보이는 두 가지를 꼽으면 아마도 공통점이 있는 8~10가지를 꼽을 수 있을 것이다.만약 여러분이 다른 한 쌍의 "집합 비슷한" 것들을 고른다면, 그것들은 또한 8에서 10가지 공통점이 될 겁니다. 하지만 그것들은 첫 번째 한 쌍과 같은 8에서 10가지 공통점이 될 수 없을 겁니다.

십여 가지나 다른 "집합 비슷한" 것들을 보면, 사실상 모든 것들은 적어도 한 가지 다른 것들과 공통적으로 8 내지 10가지 정도의 특징을 가지고 있을 것이다. 하지만 그것들 하나하나가 공유되는 것을 보면, 사실상 아무것도 남기지 않는 것이다.

이것은 상속(특히 단일 상속)이 단지 잘 모델화되지 않는 상황이다.어떤 것이 진짜 수집품인지 아닌지는 명확한 구분선은 없지만, 의미 있는 수집 클래스를 정의하고 싶다면, 그 중 몇 개는 빼놓아야 한다.이들 중 몇 개만 제외할 경우 수집 클래스는 매우 드문 인터페이스만 제공할 수 있다.더 빼놓으면 좀 더 풍부한 인터페이스를 줄 수 있을 것이다.

어떤 이들은 또한 기본적으로 "이 유형의 수집은 운영 X를 지원하지만 X를 정의하는 기본 클래스에서 파생되어 사용할 수 없지만 파생 클래스의 X를 사용하려고 하면 실패한다(예: 예외를 발생시킴).

그것은 여전히 한가지 문제를 남긴다: 어느 것을 빼먹었든, 어느 것을 넣었든 간에, 여러분은 어떤 수업과 어떤 수업 사이에 어떤 수업인지, 어떤 수업인지에 대해 엄격한 선을 그어야만 할 것이다.그 선을 어느 곳에 그어도 꽤 비슷한 어떤 것 사이에 분명하고 다소 인위적인 분열이 남게 될 것이다.

그런지 주관적인 것 같아.

C#에서, 나는 생각한다.Dictionary컬렉션을 확장하거나 최소한 구현:

public class Dictionary<TKey, TValue> : IDictionary<TKey, TValue>, 
    ICollection<KeyValuePair<TKey, TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>, 
    IDictionary, ICollection, IEnumerable, ISerializable, IDeserializationCallback

파로 스몰탁에서도:

Collection subclass: #Set
Set subclass: #Dictionary

그러나 일부 방법으로는 비대칭성이 있다.예를 들어.collect:연결(입력 항목과 동일)을 수행하는 동안do:값을 매기다그들은 다른 방법을 제공한다.keysAndValuesDo:사전을 조목조목 반복하다 Add:협회는 필요하지만remove:"유효한" 상태:

remove: anObject
self shouldNotImplement 

그래서 그것은 분명히 할 수 있지만, 계급 계층 구조와 관련된 다른 문제들로 이어진다.

더 좋은 것은 주관적이다.

클리투스의 대답은 좋지만 의미론적 접근법을 추가하고 싶다.두 가지를 모두 결합하는 것은 말이 되지 않기 때문에, 수집 인터페이스를 통해 키-값-페어를 추가하는 경우를 생각해 보십시오.지도 인터페이스는 키와 관련된 하나의 값만 허용한다.그러나 동일한 키로 기존 항목을 자동으로 제거하면 컬렉션은 이전과 동일한 크기를 추가한 후 컬렉션에 대해 매우 예상치 못한 크기를 갖게 된다.

자바 컬렉션이 망가졌다.관계 인터페이스가 누락되어 있다.따라서, 지도가 관계를 확장하면 집합이 확장된다.관계(멀티맵이라고도 함)는 고유한 이름-값 쌍을 가지고 있다.지도("기능"이라고 함)는 물론 가치에 매핑되는 고유한 이름(또는 키)을 가지고 있다.시퀀스는 맵을 확장한다(각 키가 0보다 큰 정수임).가방(또는 멀티셋)은 맵을 확장한다(각 키는 요소이고 각 값은 백에 요소가 나타나는 횟수임).

이 구조물은 다양한 "집합" 범위의 교차점, 결합 등을 허용한다.따라서 계층 구조는 다음과 같아야 한다.

                                Set

                                 |

                              Relation

                                 |

                                Map

                                / \

                             Bag Sequence

Sun/Orace/Java ppl - 다음 번에는 바로 가져오십시오.고마워요.

Map<K,V>연장해서는 안 된다Set<Map.Entry<K,V>>이후:

  • 다른 것을 추가할 는 없다.Map.Entrys 동일한 키를 가진Map그렇지만
  • 다른 항목을 추가할 수 있음Map.Entrys 동일한 키를 가진Set<Map.Entry>.

각각의 데이터 구조를 보면 그 이유를 쉽게 짐작할 수 있다.Map의 일부가 아니다Collection각각Collection단일 값을 에 저장하다.Map키 값 쌍 저장그래서 메소드는Collection인터페이스가 에 호환되지 않음Map접점예를 들어Collection우리는 가지고 있다.add(Object o). 이러한 구현은 무엇에 해당될 것인가?Map. 그런 방법을 가지고 있다는 것은 말이 안 된다.Map대신 우리는put(key,value)에 있어서의 방법.Map.

같은 논거가 있다.addAll()remove()그리고removeAll()방법들그래서 가장 큰 이유는 데이터가 저장되는 방식의 차이 때문이다.Map그리고Collection. 또한 당신이 기억한다면.Collection인터페이스 구현Iterable인터페이스(즉, 모든 인터페이스와.iterator()메소드는 에 저장된 값을 반복할 수 있는 반복기를 반환해야 한다.Collection이제 그러한 방법은 무엇에 대한 보상을 할 것인가?Map 핵심 반복기 또는 가치 반복기?이것도 말이 안 된다.

우리가 키와 가치관을 반복할 수 있는 방법이 있다.Map그리고 그것이 그것의 일부분이다.Collection골격

바로 그거야interface Map<K,V> extends Set<Map.Entry<K,V>>정말 좋을 거야!

사실 그랬다면implements Map<K,V>, Set<Map.Entry<K,V>>그럼 난 동의하는 편해그것은 심지어 자연스러워 보인다.그런데 그게 잘 안 되잖아?가지고 있다고 가정해 보자.HashMap implements Map<K,V>, Set<Map.Entry<K,V>LinkedHashMap implements Map<K,V>, Set<Map.Entry<K,V>다가 ...을... 그건 다 좋은데, 만약 네가 그랬다면.entrySet(), 아무도 그 방법의 구현을 잊지 않을 것이고, 당신은 어떤 지도에 대해서도 entrySet를 얻을 수 있다는 것을 확신할 수 있지만, 만약 당신이 구현자가 두 가지 인터페이스를 모두 구현하기를 원한다면...

내가 갖고 싶지 않은 이유interface Map<K,V> extends Set<Map.Entry<K,V>>단순히, 더 많은 방법이 있을 것이기 때문이다.그리고 결국, 그것들은 다른 것들이야, 그렇지?또 아주 현실적으로, 만약 내가 때린다면map.IDE에서는 보고 싶지 않다..remove(Object obj)그리고.remove(Map.Entry<K,V> entry)할 수 없기 때문에hit ctrl+space, r, return그리고 끝장을 내라.

솔직하고 심플하다.집합은 하나의 개체만을 기대하는 인터페이스인 반면, 지도에는 두 개만 필요하다.

Collection(Object o);
Map<Object,Object>

참조URL: https://stackoverflow.com/questions/2651819/why-doesnt-java-map-extend-collection

반응형