Java의 Collection 인터페이스를 사용해야 할 이유가 있습니까?


11

해당 인터페이스의 특정 구현에 묶이지 않도록 사용 가능한 가장 일반적인 인터페이스를 사용해야한다는 주장을 들었습니다. 이 로직이 java.util.Collection 과 같은 인터페이스에 적용됩니까 ?

나는 오히려 다음과 같은 것을 보게 될 것이다.

List<Foo> getFoos()

또는

Set<Foo> getFoos()

대신에

Collection<Foo> getFoos()

마지막 경우, 어떤 종류의 데이터 세트를 처리하는지 알 수 없지만 처음 두 경우에는 순서와 고유성에 대해 몇 가지 가정을 할 수 있습니다. 합니까 java.util.Collection으로는 세트 목록 모두에 대한 논리적 부모 인의 유용성의 외부 있나요?

코드 검토를 수행 할 때 Collection 을 채택한 코드를 발견 한 경우 사용법이 정당화되는지 여부와보다 구체적인 인터페이스로 대체하기 위해 어떤 제안을 하시겠습니까?


3
java.security.cert에서 하나의 리턴 유형이 있음을 알았 Collection<List<?>>습니까? 코딩 공포에 대해 이야기하십시오!
Macneil

1
@ Macneil 나는 어떤 클래스를 언급하는지 모르지만 그러한 반환 유형은 실제로 합리적 일 수 있습니다. 그것은 본질적으로 당신이 가지고 있음을 알려줍니다 모음 (즉, 물건을 잔뜩 포함 되어 있지 않습니다 의 합리적인 순서) 목록 (즉, 일 포함 의 합리적인 순서) 객체 (누구의 유형 우리는 정적에 대한 알 수없는, 즉 항목을 이유가 무엇이든). 나에게 비합리적으로 보이지 않습니다.
Zero3

답변:


13

추상화는 구현보다 오래 산다

일반적으로 디자인이 추상화 될수록 유용 할 가능성이 더 길어집니다. 따라서 Collection은 하위 인터페이스보다 추상적이므로 Collection을 기반으로하는 API 디자인은 List를 기반으로하는 것보다 유용하게 유지 될 가능성이 높습니다.

그러나 가장 중요한 원칙은 가장 적절한 추상화 를 사용하는 것 입니다. 따라서 컬렉션에서 순서가 지정된 요소를 지원해야하는 경우 List를, 중복이 없어야하는 경우 Set 등을 지정해야합니다.

일반 인터페이스 디자인에 대한 참고 사항

제네릭과 함께 Collection 인터페이스를 사용하는 데 관심이 있으므로 다음이 도움이 될 수 있습니다. Joshua Bloch의 효과적인 Java 는 제네릭에 의존하는 인터페이스를 설계 할 때 다음과 같은 접근 방식을 권장합니다. 생산자 확장, 소비자 수퍼

이것은 PECS 규칙 이라고도합니다 . 기본적으로 데이터를 생성하는 일반 컬렉션이 클래스에 전달되면 서명은 다음과 같아야합니다.

public void pushAll(Collection<? extends E> producerCollection) {}

따라서 입력 유형은 E 또는 E의 서브 클래스 일 수 있습니다 (E는 Java 언어에서 자체의 수퍼 클래스 및 서브 클래스로 정의 됨).

반대로, 데이터를 소비하기 위해 전달되는 일반 컬렉션에는 다음과 같은 서명이 있어야합니다.

public void popAll(Collection<? super E> consumerCollection) {}

방법은 올바르게 전달 할 수 있습니다 때문에 사용자에게 인터페이스 덜 놀라운 것이 방법을 사용하여, E. 전체의 슈퍼 클래스를 다루는 것 Collection<Number>하고 Collection<Integer>그들을 올바르게 처리합니다.


6

Collection인터페이스, 그리고 가장 관대 한 형태로 Collection<?>, 좋은 곳입니다 매개 변수를 수락있다. Java 라이브러리 자체에서의 사용을 기반으로 반환 유형보다 매개 변수 유형으로 일반적입니다.

반환 유형의 경우 귀하의 포인트가 유효하다고 생각합니다. 사람들이 액세스 할 것으로 예상되는 경우 수행되는 작업의 순서 (Big-O 의미)를 알아야합니다. Collection반환 된 것을 반복 하여 다른 컬렉션에 추가하지만 containsO (1), O (log n) 또는 O (n) 연산인지 알지 못하면 호출 하는 것이 약간 미친 것 같습니다 . 물론, 당신이 Set그것을 가지고 있다고 해서 그것이 해시 셋이거나 정렬 된 세트라는 것을 의미하지는 않지만, 어느 시점에서 인터페이스가 합리적으로 구현되었다는 가정을 할 것입니다. 잘못된 것으로 표시됨).

Tom이 언급했듯이 때로는 Collection캡슐화를 유지하기 위해 a를 반환해야합니다 . 더 구체적인 것을 반환 할 수 있더라도 구현 세부 정보가 유출되는 것을 원하지 않습니다. 또는 Tom이 언급 한 경우보다 구체적인 컨테이너를 반환 할 수는 있지만 컨테이너를 구성해야합니다.


2
나는 두 번째 점이 약간 약하다고 생각합니다. 컬렉션이든 목록이든 관계없이 컬렉션이 어떻게 수행 될지 모릅니다. 단지 추상화 일뿐입니다. 구체적인 최종 수업이 없으면 실제로 말할 수 없습니다.
Mark H

또한 무언가가 컬렉션이라는 것을 아는 것이라면 복제본을 포함 할 수 있는지 여부는 알 수 없습니다. 컬렉션을 반환하는 것이 적절할 수도 있습니다. 복제물을 포함하지 않고 중요한 순서가없는 컬렉션 (자연스럽게 세트 일 수 있음)이 있지만 어떤 이유로 든 반환 메서드 구현이있는 경우 목록을 사용합니다. 중요한 순서를 의미하기 때문에 List를 반환하고 싶지는 않지만 하나를 만드는 과정을 거치지 않고 Set을 반환 할 수는 없습니다. 컬렉션을 반환합니다.
Tom Anderson

@Tom : 좋은 지적입니다!
Macneil

5

나는 완전히 반대의 관점에서 그것을보고 물었다.

코드 검토를 수행 할 때 List <>를 사용하는 코드를 발견 한 경우 사용법이 정당한지 어떻게 알 수 있습니까?

이것을 정당화하는 것은 매우 쉽습니다. 컬렉션에서 제공하지 않는 일부 기능이 필요할 때 목록을 사용합니다. 추가 기능이 필요하지 않은 경우 어떤 정당화가 있습니까? (그리고 나는 그것을보고 싶지 않다.)

읽기 전용 목적으로 컬렉션을 사용하고 한 번에 모두 채우고 전체를 반복하는 경우가 많이 있습니다. 수동으로 항목을 색인해야합니까?

실제 사례를 제공합니다. 데이터베이스에서 간단한 쿼리를 수행한다고 가정 해보십시오. ( SELECT id,name,rep FROM people WHERE name LIKE '%squared') 관련 데이터를 다시 가져와 Person 객체를 채우고 PersonList에 넣습니다.)

  • 인덱스로 액세스해야합니까? -무의미 해 인덱스와 ID 사이에는 매핑이 없습니다.
  • 색인에 삽입해야합니까? -아니요, DBMS는 추가 할 위치를 결정할 것입니다.

그래서 그 추가 방법에 대해 어떤 정당화가 필요합니까? (어쨌든 내 PersonList에서 구현되지 않은 채로 남을 것입니다)


페어 포인트. 내 질문은 코드 검토를 수행하는 동안 컬렉션을 반환하는 DAO가 계속 표시되는 특정 인스턴스를 참조한다고 가정하지만 이러한 DAO 호출은 항상 엔터티 집합을 반환한다는 것을 알고 있습니다. 내 경합은 이러한 경우 반환 유형이 고유성을 나타내며이 정보는 해당 방법을 사용해야하는 사람에게 도움이된다는 것입니다 (예 : 중복을 확인할 필요가 없음).

DB를 쿼리 한 경우 2 개의 결과 객체를 equals ()와 비교해도 전혀 문제가되지 않아야합니다. 따라서 복제를 위해 객체를 비교하는 다른 방법이 필요합니다 (예 : 동일한 이름, 동일한 ID, 양자 모두?). 복제본 자체를 제거하는 경우 DAO에 비교 방법을 알려 주어야하지만 복제본이 있는지 여부를 결정하는 사용자이기 때문에 호출 코드의 컬렉션으로 수행하는 것이 더 쉽습니다. (DAO에게 지구상에서 가능한 모든 평등 점검을 수행하는 방법을 알리기 위해 더 많은 추상화 계층을 피하기 위해)
Mark H

동의하지만 우리는 최대 절전 모드를 사용하고 있으며 엔티티가 equals ()를 구현하는지 확인하십시오. 따라서 DAO가 엔터티를 반환하면 새로운 HashSet (). addAll (results)을 매우 빠르게 수행하여 호출 된 메서드로 되돌릴 수 있습니다.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.