[HADOOP] 값을 두 번 반복 (MapReduce)
HADOOP값을 두 번 반복 (MapReduce)
인수로서 반복자를 받고 값을 두 번 반복하고 싶습니다.
public void reduce(Pair<String,String> key, Iterator<IntWritable> values,
Context context)
가능한가? 어떻게? 서명은 내가 사용하고있는 프레임 워크 (즉, Hadoop)에 의해 부과됩니다.
-- 편집하다 -- 마지막으로 reduce 메소드의 실제 서명은 반복 가능합니다. 나는이 위키 페이지 (실제로는 내가 찾은 단어 수의 유일한 비 - 비추천 (그러나 잘못된) 예이다)에 속아 넘어졌다.
해결법
-
==============================
1.다시 반복하려는 경우 반복기에서 값을 캐시해야합니다. 적어도 우리는 첫 번째 반복과 캐싱을 결합 할 수 있습니다.
다시 반복하려는 경우 반복기에서 값을 캐시해야합니다. 적어도 우리는 첫 번째 반복과 캐싱을 결합 할 수 있습니다.
Iterator<IntWritable> it = getIterator(); List<IntWritable> cache = new ArrayList<IntWritable>(); // first loop and caching while (it.hasNext()) { IntWritable value = it.next(); doSomethingWithValue(); cache.add(value); } // second loop for(IntWritable value:cache) { doSomethingElseThatCantBeDoneInFirstLoop(value); }
(코드에 대한 답을 추가하기 위해서, 당신이 당신의 코멘트에이 솔루션을 언급했다는 것을 알고 있어야합니다.))
캐싱 없이는 불가능한 이유는 무엇입니까? Iterator는 인터페이스를 구현하고 Iterator 객체가 실제로 값을 저장한다는 단일 요구 사항이 아닙니다. 두 번 반복하면 반복자를 재설정하거나 (복제 할 수 없음) 다시 복제해야합니다.
복제 / 재설정이 의미가없는 반복자에 대한 예제를 제공하려면 다음을 수행하십시오.
public class Randoms implements Iterator<Double> { private int counter = 10; @Override public boolean hasNext() { return counter > 0; } @Override public boolean next() { count--; return Math.random(); } @Override public boolean remove() { throw new UnsupportedOperationException("delete not supported"); } }
-
==============================
2.안타깝게도 Andreas_D의 대답처럼 값을 캐싱하지 않으면이 작업을 수행 할 수 없습니다.
안타깝게도 Andreas_D의 대답처럼 값을 캐싱하지 않으면이 작업을 수행 할 수 없습니다.
Reducer가 Iterator가 아닌 Iterable을받는 새 API를 사용하더라도 두 번 반복 할 수 없습니다. 다음과 같은 것을 시도하는 것은 매우 유혹적입니다.
for (IntWritable value : values) { // first loop } for (IntWritable value : values) { // second loop }
하지만 실제로는 작동하지 않습니다. 그 Iterable의 iterator () 메소드로부터받는 Iterator는 특별하다. 값이 모두 메모리에 있지 않을 수도 있습니다. Hadoop이 디스크에서 스트리밍 중일 수 있습니다. 컬렉션에 의해 뒷받침되지는 않으므로 여러 번 반복 할 수 있습니다.
Reducer 및 ReduceContext 코드에서 직접 확인할 수 있습니다.
콜렉션에서 값을 일종의 캐시로 저장하는 것이 가장 쉬운 방법 일 수 있지만 대용량 데이터 세트에서 작업하는 경우에는 힙을 쉽게 날려 버릴 수 있습니다. 문제에 대해 더 자세한 정보를 제공 할 수 있다면 여러 번의 반복을 필요로하지 않는 솔루션을 찾을 수 있습니다.
-
==============================
3.지정된 반복자를 다시 사용합니다.
지정된 반복자를 다시 사용합니다.
하지만 ArrayList의 값을 처음부터 반복 한 다음 생성 된 ArrayList를 반복 할 때 ArrayList에 값을 저장할 수 있습니다. (또는 멋진 컬렉션 메서드를 사용하여 직접 빌드 한 다음 해당 컬렉션에 직접 반복 할 수 있습니다. ArrayList 두 번, 그것은 맛의 문제입니다).
어쨌든, 반복자를 전달하는 것이 처음부터 좋은 일인 지 확실합니까? 반복자는 컬렉션을 통해 선형 스캔을 수행하는 데 사용되므로 이러한 방식으로 "되감기"메소드가 노출되지 않습니다.
이미 다른 답변에서 제안 된 Collection
또는 Iterable 와 같이 다른 것을 전달해야합니다. -
==============================
4.반복자는 하나의 순회 전용입니다. 일부 반복자 유형은 복제 가능하므로 탐색하기 전에 복제 할 수는 있지만 일반적으로 발생하는 것은 아닙니다.
반복자는 하나의 순회 전용입니다. 일부 반복자 유형은 복제 가능하므로 탐색하기 전에 복제 할 수는 있지만 일반적으로 발생하는 것은 아닙니다.
당신이 그것을 달성 할 수 있다면, 대신에 당신의 함수가 반복 가능하도록 만들어야한다.
-
==============================
5.메서드 서명을 변경할 수 없다면 Apache Commons IteratorUtils를 사용하여 Iterator를 ListIterator로 변환하는 것이 좋습니다. 값을 두 번 반복하는 다음 예제 메서드를 고려하십시오.
메서드 서명을 변경할 수 없다면 Apache Commons IteratorUtils를 사용하여 Iterator를 ListIterator로 변환하는 것이 좋습니다. 값을 두 번 반복하는 다음 예제 메서드를 고려하십시오.
void iterateTwice(Iterator<String> it) { ListIterator<?> lit = IteratorUtils.toListIterator(it); System.out.println("Using ListIterator 1st pass"); while(lit.hasNext()) System.out.println(lit.next()); // move the list iterator back to start while(lit.hasPrevious()) lit.previous(); System.out.println("Using ListIterator 2nd pass"); while(lit.hasNext()) System.out.println(lit.next()); }
위의 코드를 사용하면 코드에서 List 요소의 복사본을 저장하지 않고도 값 목록을 반복 할 수있었습니다.
-
==============================
6.Reducer에서 아래와 같이 두 번 반복하려는 경우
Reducer에서 아래와 같이 두 번 반복하려는 경우
ListIterator<DoubleWritable> lit = IteratorUtils.toListIterator(it); System.out.println("Using ListIterator 1st pass"); while(lit.hasNext()) System.out.println(lit.next()); // move the list iterator back to start while(lit.hasPrevious()) lit.previous(); System.out.println("Using ListIterator 2nd pass"); while(lit.hasNext()) System.out.println(lit.next());
우리는 다음과 같이 출력 할 것입니다.
Using ListIterator 1st pass 5.3 4.9 5.3 4.6 4.6 Using ListIterator 2nd pass 5.3 5.3 5.3 5.3 5.3
Inorder를 올바른 방법으로 얻으려면 다음과 같이 반복해야합니다.
ArrayList<DoubleWritable> cache = new ArrayList<DoubleWritable>(); for (DoubleWritable aNum : values) { System.out.println("first iteration: " + aNum); DoubleWritable writable = new DoubleWritable(); writable.set(aNum.get()); cache.add(writable); } int size = cache.size(); for (int i = 0; i < size; ++i) { System.out.println("second iteration: " + cache.get(i)); }
산출
first iteration: 5.3 first iteration: 4.9 first iteration: 5.3 first iteration: 4.6 first iteration: 4.6 second iteration: 5.3 second iteration: 4.9 second iteration: 5.3 second iteration: 4.6 second iteration: 4.6
-
==============================
7.너는 그걸 할 수있어.
너는 그걸 할 수있어.
MarkableIterator<Text> mitr = new MarkableIterator<Text>(values.iterator()); mitr.mark(); while (mitr.hasNext()) { //do your work } mitr.reset(); while(mitr.hasNext()) { //again do your work }
-
==============================
8.이 시도:
이 시도:
ListIterator it = list.listIterator(); while(it.hasNext()){ while(it.hasNext()){ System.out.println("back " + it.next() +" "); } while(it.hasPrevious()){ it.previous(); } }
-
==============================
9.값을 변경하려면 listIterator를 사용하고 set () 메서드를 사용하는 것이 좋습니다.
값을 변경하려면 listIterator를 사용하고 set () 메서드를 사용하는 것이 좋습니다.
ListIterator lit = list.listIterator(); while(lit.hasNext()){ String elem = (String) lit.next(); System.out.println(elem); lit.set(elem+" modified"); } lit = null; lit = list.listIterator(); while(lit.hasNext()){ System.out.println(lit.next()); }
.previous ()를 호출하는 대신, 같은 list iterator 객체에서 .listIterator ()의 또 다른 인스턴스를 얻는다.
-
==============================
10.검색과 많은 시도와 오류를 한 후에 해결책을 찾았습니다.
검색과 많은 시도와 오류를 한 후에 해결책을 찾았습니다.
from https://stackoverflow.com/questions/6111248/iterate-twice-on-values-mapreduce by cc-by-sa and MIT license
'HADOOP' 카테고리의 다른 글
[HADOOP] Sqoop 가져 오기 : 복합 기본 키 및 텍스트 기본 키 (0) | 2019.05.29 |
---|---|
[HADOOP] 감속기에서 매퍼 카운터에 액세스 (0) | 2019.05.29 |
[HADOOP] hadoop의 MultipleOutputFormat (0) | 2019.05.29 |
[HADOOP] 로컬 Hadoop 2.6 설치에서 S3 / S3n에 어떻게 액세스합니까? (0) | 2019.05.29 |
[HADOOP] .txt 파일을 Hadoop의 시퀀스 파일 형식으로 변환하는 방법 (0) | 2019.05.29 |