2017-09-27 3 views
1

나는 을 구현하는 Pair이라는 간단한 클래스가 있습니다. 두 개의 필드를 포함하며 MapReduce 프로세스의 Value로 사용됩니다.Hadoop의 감속기에서 이상한 동작

각 키에 대해 쌍의 필드 중 가장 큰 값 (preco)으로 쌍을 찾고 싶습니다.

float max = 0; 
String country = ""; 
for (Pair p : values){ 
    if (p.getPreco().get() > max) 
    { 
     max = p.getPreco().get(); 
     country = p.getPais().toString(); 
    } 
} 
context.write(key, new Pair(new FloatWritable(max), new Text(country))); 

다음 코드, 다른 한편으로는,하지 않는 : 감속기에서 다음 코드는 예상 된 결과 생산

Pair max = new Pair(); 
for (Pair p : values) 
    if (p.getPreco().get() > max.getPreco().get()) 
     max = p; 

context.write(key, max); 

두 번째 코드는 각각의 키, 마지막 값, 생산을 그 가장 높은 값이 아닌 입력 파일에서이 값과 연관됩니다.

이 이상한 행동이 나타나는 이유는 무엇입니까?

답변

0

감속기가 객체를 재사용하므로 값의 반복자가 항상 동일한 객체를 전달하므로이 문제가 발생합니다. 따라서이 코드 :

max = p;

항상 p의 현재 값을 참조 할 것. 이 작업을 올바르게 수행하고 객체를 참조하지 않으려면 데이터를 max에 복사해야합니다. 이것이 코드의 첫 번째 버전이 작동하는 이유입니다.

일반적으로 하둡에서는 사용자 정의 쓰기 가능 방법으로 .set() 메서드를 구현합니다. 이는 일반적인 패턴입니다. 그래서 Pair 클래스는 (그것의 인터페이스 방법 등없는)처럼 조금 보일 수 있습니다 :

public class Pair implements Writable { 

    public FloatWritable max = new FloatWritable(); 
    public Text country = new Text(); 

    public void set(Pair p) { 
     this.max.set(p.max.get()); 
     this.country.set(p.country); 
    } 
} 

을 그리고 당신은 당신의 코드를 변경 것이다 : 나는 그래서 Pairgetters를 작성하지 않은

Pair max = new Pair(); 
for (Pair p : values) { 
    if (p.max().get() > max.max.get()) { 
     max.set(p); 
    } 
} 
context.write(key, max); 

코드가 공개 클래스 변수에 직접 액세스하기 위해 약간 변경되었습니다.