[HADOOP] java.lang.ClassCastException 가져 오기 : 간단한 MapReduce 프로그램 실행시 클래스 java.lang.String
HADOOPjava.lang.ClassCastException 가져 오기 : 간단한 MapReduce 프로그램 실행시 클래스 java.lang.String
간단한 MapReduce 프로그램을 실행하려고합니다.지도는 입력을 가져 와서 두 부분으로 나눕니다 (key => String and value => Integer) 감속기는 해당 키의 값을 합산 매번 ClassCastException이 발생합니다. 코드 에서이 오류의 원인을 이해할 수 없습니다.
내 코드 :
import java.io.IOException;
import java.util.Iterator;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapred.FileInputFormat;
import org.apache.hadoop.mapred.FileOutputFormat;
import org.apache.hadoop.mapred.JobClient;
import org.apache.hadoop.mapred.JobConf;
import org.apache.hadoop.mapred.MapReduceBase;
import org.apache.hadoop.mapred.Mapper;
import org.apache.hadoop.mapred.OutputCollector;
import org.apache.hadoop.mapred.Reducer;
import org.apache.hadoop.mapred.Reporter;
import org.apache.hadoop.mapred.TextInputFormat;
import org.apache.hadoop.mapred.TextOutputFormat;
public class Test {
public static class Map extends MapReduceBase implements
Mapper<LongWritable, Text, String, Integer> {
@Override
public void map(LongWritable key, Text value,
OutputCollector<String, Integer> output, Reporter reporter)
throws IOException {
String line = value.toString();
String[] lineParts = line.split(",");
output.collect(lineParts[0], Integer.parseInt(lineParts[1]));
}
}
public static class Reduce extends MapReduceBase implements
Reducer<String, Integer, String, Integer> {
@Override
public void reduce(String key, Iterator<Integer> values,
OutputCollector<String, Integer> output, Reporter reporter)
throws IOException {
int sum = 0;
while (values.hasNext()) {
sum = sum + values.next();
}
output.collect(key, sum);
}
}
public static void main(String[] args) throws Exception {
JobConf conf = new JobConf(Test.class);
conf.setJobName("ProductCount");
conf.setMapOutputKeyClass(String.class);
conf.setMapOutputValueClass(Integer.class);
conf.setOutputKeyClass(String.class);
conf.setOutputValueClass(Integer.class);
conf.setMapperClass(Map.class);
conf.setReducerClass(Reduce.class);
conf.setInputFormat(TextInputFormat.class);
conf.setOutputFormat(TextOutputFormat.class);
FileInputFormat.setInputPaths(conf, new Path(args[0]));
FileOutputFormat.setOutputPath(conf, new Path(args[1]));
JobClient.runJob(conf);
}
}
샘플 데이터 :
abc,10
abc,10
abc,10
def,9
def,9
다음은 스택 추적입니다. 키-값과 관련이 있습니까?
14/02/11 23:57:35 INFO mapred.JobClient: Task Id : attempt_201402110240_0013_m_000001_2, Status : FAILED
java.lang.ClassCastException: class java.lang.String
at java.lang.Class.asSubclass(Class.java:3018)
at org.apache.hadoop.mapred.JobConf.getOutputKeyComparator(JobConf.java:795)
at org.apache.hadoop.mapred.MapTask$MapOutputBuffer.<init>(MapTask.java:816)
at org.apache.hadoop.mapred.MapTask.runOldMapper(MapTask.java:382)
at org.apache.hadoop.mapred.MapTask.run(MapTask.java:324)
at org.apache.hadoop.mapred.Child$4.run(Child.java:268)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.Subject.doAs(Subject.java:396)
at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1115)
at org.apache.hadoop.mapred.Child.main(Child.java:262)
Exception in thread "main" java.io.IOException: Job failed!
at org.apache.hadoop.mapred.JobClient.runJob(JobClient.java:1246)
at Test.main(Test.java:69)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.hadoop.util.RunJar.main(RunJar.java:186)
해결법
-
==============================
1.출력에 올바른 클래스를 사용하지 않는 것처럼 보입니다.
출력에 올바른 클래스를 사용하지 않는 것처럼 보입니다.
MapReduce 튜토리얼 중 하나에서 :
따라서 String.class를 Text.class로 바꾸고 Integer.class를 IntWritable.class로 바꾸어야합니다.
문제가 해결되기를 바랍니다.
기본 String 또는 Integer 클래스를 사용할 수없는 이유는 무엇입니까?
정수 및 문자열은 문서에서 볼 수 있듯이 Java의 표준 직렬화 가능 인터페이스를 구현합니다. 문제는 MapReduce가이 표준 인터페이스를 사용하지 않고 자체 인터페이스 (쓰기 가능)라고하는 값을 직렬화 / 역 직렬화한다는 것입니다.
그렇다면 왜 기본 Java 인터페이스를 사용하지 않습니까?
짧은 대답 : 더 효율적이기 때문입니다. MapReduce 코드에서 입력 / 출력의 유형을 이미 정의 했으므로 쓰기 가능한 인터페이스는 직렬화 할 때 유형 정의를 생략합니다. 코드는 이미 다음과 같은 것을 알고 있으므로 다음과 같이 문자열을 직렬화하는 대신
String: "theStringItself"
다음과 같이 직렬화 될 수 있습니다.
theStringItself
보시다시피 이것은 엄청난 양의 메모리를 절약합니다.
긴 대답 :이 멋진 블로그 게시물을 읽으십시오.
from https://stackoverflow.com/questions/21722173/getting-java-lang-classcastexception-class-java-lang-string-in-running-a-simple by cc-by-sa and MIT license
'HADOOP' 카테고리의 다른 글
[HADOOP] Apache Nutch를 사용하여 .pdf 링크를 크롤링하는 방법 (0) | 2019.08.09 |
---|---|
[HADOOP] 하이브 다중 열 변경 (0) | 2019.08.09 |
[HADOOP] Amazon EMR : 데이터 노드에서 스토리지 구성 (0) | 2019.08.08 |
[HADOOP] 하둡 맵리 듀스 프로그래밍 (0) | 2019.08.08 |
[HADOOP] HDFS에서 1 백만 개 이상의 파일이있는 이진 파일 ()로 인한 스파크 시간 초과 (0) | 2019.08.08 |