Java의 ArrayList에서 ArrayList를 슬라이스하려면 어떻게해야합니까?


80

ArrayListJava에서 배열 조각을 어떻게 얻 습니까? 구체적으로 다음과 같이하고 싶습니다.

ArrayList<Integer> inputA = input.subList(0, input.size()/2);
// where 'input' is a prepouplated ArrayList<Integer>

그래서 이것이 작동 할 것으로 예상했지만 Java는 List-를 반환 하므로 호환되지 않습니다. 그리고 캐스팅하려고 할 때 Java가 허용하지 않습니다. 나는 ArrayList-내가 무엇을 할 수 있습니까?


4
왜 사용을 고집 ArrayList합니까? 난 당신이 인터페이스가 있기 때문에 어떻게 작동하는지 이해하는 조금 부족한 것 같아요 ListArrayList"호환되지 않는"아니다 - ArrayList구현을 List하고, List아마 당신이 필요로하는 모든 필요한 메서드가 포함되어 있습니다.
Bombe

2
엄격한 메서드 프로토 타입을 사용하는 inteview 질문이기 때문에 ArrayList를 사용하도록 고집합니다. subList는 List 형식을 반환해야하는데, 반환 된 List를 ArrayList로 캐스팅 할 수 없기 때문에 분명히 이해가 부족합니다. 그러니 말해봐 ..
BT

4
그것은 그가 필요하다고 전적으로 가능성이 ArrayList그 다음을 받아 그것으로 메소드를 호출 할 필요가 있기 때문에 ArrayList. 틀림없이 그러한 방법은 잘못 설계되어 List대신 받아 들여야 하지만 그러한 상황은 인터뷰 질문뿐만 아니라 다른 사람이 작성한 코드에서 발생할 수 있으며 그냥 갈 수 없습니다. 동료와 도서관이 항상 완벽한 것은 아닙니다.
Gravity

답변:


124

Java에서는 API의 구체적인 클래스보다는 인터페이스 유형을 사용하는 것이 좋습니다.

당신의 문제는 ArrayList당신이 실제로 사용해야 할 곳 (아마 많은 곳에서)을 사용하고 있다는 것 List입니다. 결과적으로 목록이 ArrayList.

코드는 다음과 같습니다.

List input = new ArrayList(...);

public void doSomething(List input) {
   List inputA = input.subList(0, input.size()/2);
   ...
}

this.doSomething(input);

문제에 대해 제안한 "해결 방법"은 다음과 같습니다.

new ArrayList(input.subList(0, input.size()/2))

하위 목록을 복사하여 작동합니다. 정상적인 의미에서 슬라이스가 아닙니다. 또한 하위 목록이 크면 복사본을 만드는 데 비용이 많이 듭니다.


당신은 당신이 있음 API에서 제한하는 경우 변경할 수 없습니다 당신이 있도록, 해야 선언 inputAint로서 ArrayList, 당신의 사용자 정의 서브 클래스 구현 할 수있을 ArrayList하는 subList방법의 서브 클래스를 반환합니다 ArrayList. 하나:

  1. 설계, 구현 및 테스트하는 데 많은 작업이 필요할 것입니다.
  2. 이제 클래스의 문서화되지 않은 측면 (따라서 "변경 될 수 있음") 측면에 대한 종속성이있는 중요한 새 클래스를 코드베이스에 추가했습니다 ArrayList.
  3. ArrayList대신에 하위 클래스의 인스턴스를 만들기 위해 인스턴스를 만드는 코드베이스의 관련 위치를 변경해야합니다 .

"배열 복사"솔루션이 더 실용적입니다. 이것이 진정한 슬라이스가 아니라는 점을 염두에 두십시오.


6
실제로 subList는 복사본을 만들지 않습니다. 원래 목록 ( docs.oracle.com/javase/6/docs/api/java/util/… ) 에보기를 반환합니다.
Matt

3
실제로 @Matthew, 나는 그가 이것을하는 곳에서 OP의 자기 대답을 언급하고있다 :new ArrayList(input.subList(0, input.size()/2))
Stephen C

1
+1 : Java에서는 API의 구체적인 클래스보다는 인터페이스 유형을 사용하는 것이 좋습니다.
Ilonpilaaja 19

6

ArrayList에서 제거해야하는 요소의 startIndex 및 endIndex를 알고있는 경우 방법을 찾았습니다.

하자 al원래의 ArrayList하고 startIndex, endIndex각각 상기 어레이로부터 제거되기 시작 및 종료 인덱스 수 :

al.subList(startIndex, endIndex + 1).clear();

6

기존 메서드가 없으면 0에서으로 반복 input.size()/2하여 각 연속 요소를 가져와 새 ArrayList에 추가 할 수 있다고 생각합니다 .

편집 : 사실, 나는 당신이 그 목록을 가지고 그것을 사용 하여 ArrayList 생성자 중 하나를 사용하여 새로운 ArrayList를 인스턴스화 할 수 있다고 생각합니다 .


2
그게 정확히 내가 한 일입니다 (편집을 읽기 전에 내 답변을 게시했습니다). 감사합니다
BT

그러나 그것은 새로운 ArrayList를 만들기 위해 List를 복사 합니다.
Joren

2
@BT-기록을 위해이 문맥에서 "슬라이스"라는 용어가 일반적으로 의미하는 것은 아닙니다.
Stephen C


-4

이것이 내가 그것을 해결 한 방법입니다. 하위 목록이 원래 목록의 요소에 대한 직접적인 참조라는 것을 잊었으므로 작동하지 않는 이유가 이해가됩니다.

ArrayList<Integer> inputA = new ArrayList<Integer>(input.subList(0, input.size()/2));
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.