2017-04-10 13 views
3

많은 수의 요소가있는 목록이 있습니다. 이 목록을 처리하는 동안, 어떤 경우에는 목록을 더 작은 하위 목록으로 분할하고 일부 경우 전체 목록을 처리하려고합니다.Java : 처리 용 List 청크 생성

private void processList(List<X> entireList, int partitionSize) 
{ 
    Iterator<X> entireListIterator = entireList.iterator(); 
    Iterator<List<X>> chunkOfEntireList = Iterators.partition(entireListIterator, partitionSize); 
    while (chunkOfEntireList.hasNext()) { 
     doSomething(chunkOfEntireList.next()); 
     if (chunkOfEntireList.hasNext()) { 
      doSomethingOnlyIfTheresMore(); 
     } 
    } 

저는 파티션 생성을 위해 com.google.common.collect.Iterators를 사용하고 있습니다. 그래서 크기 100 목록을 분할 할 경우 문서 here 의 링크, 제가 목록의 덩어리를 만들 싶지 않을 때, 나는 정수를 전달할 수 있다고 생각, 지금

processList(entireList, 100); 

를 호출합니다. partitionSize로 MAX_VALUE입니다.

processList(entireList, Integer.MAX_VALUE); 

그러나 이것은 메모리 부족으로 이어집니다. 누군가 나를 도울 수 있습니까? 내가 뭘 놓치고 있니? 내부적으로 반복자는 무엇이며 어떻게 극복합니까?

EDIT : 처리 할 목록이 더있는 경우에만 내부에서 "if"절이 필요합니다. 즉 iterator의 hasNext() 함수가 필요합니다.

답변

6

당신은 메모리 부족 오류가 있어요. 반복이 완료 될 때까지 실제 요소 수를 알 수 없으므로 할당 된 배열은 항상 파티션 크기입니다. (그들은 내부적으로 ArrayList 사용했다면 문제가 방지 될 수 있었다, 나는 디자이너가 배열은 일반적인 경우에 더 나은 성능을 제공하는 것이 결정 같아요.)

인, List.subList()에 위임하기 때문에, 이러한 문제를 방지 할 Lists.partition() 사용 기본 목록 만 보기 :

private void processList(List<X> entireList, int partitionSize) { 
    for (List<X> chunk : Lists.partition(entireList, partitionSize)) { 
     doSomething(chunk); 
    } 
} 
0

일반적으로 파티션을 나누는 동안 지정된 partitionSize를 사용하여 새 목록을 할당합니다. 이 경우에는 그러한 오류가 있음이 명백합니다. 단일 파티션 만 필요할 때 원래 목록을 사용하지 않는 이유는 무엇입니까? 가능한 해결책.

  1. 크기를 사용하지 않는 별도의 오버로드 된 메서드를 만듭니다.
  2. 파티션을 필요로하지 않을 때 크기를 -1로 전달하십시오. 메서드에서 값을 확인하고 -1이면 원래 목록을 chunkOfEntireList에 넣습니다. Iterators.partition() 내부적으로 주어진 파티션 길이 배열을 채 웁니다 때문에
+0

이 작업을 고려했습니다. 하지만 그것은 내 경우에 코드를 아주 추악하게 만든다. Iterators.partition()과 별도로 시도 할 수있는 대체 솔루션이 있습니까? –

+0

당신은 partiotion 메서드를 만들 수 있습니다. 그런 다음 해당 메서드에서 2 제안 된 솔루션 중 하나를 구현할 수 있습니다. 코드를 못하게 만들지 않아. – stinepike

0

병렬로 목록의 덩어리를 처리하여 병렬 처리를 해결하기 위해 노력하고 있다고 가정하면, 그것은 더 좋을 수도 더 큰 프레임 워크로 맵리 듀스 같은, 또는 불꽃을 고려할 여기에는 프로세스 관리가 포함됩니다.

그러나 모 놀리 식 응용 프로그램의 일부로 노드 로컬 변형을 고려할 수 있습니다 (Java 8 Streams 포함). List<X>에서도 사용할 수있는 parallelStream() 방법을 기록해 두십시오.