web-dev-qa-db-fra.com

Hadoop: Java.lang.ClassCastException: org.Apache.hadoop.io.LongWritable ne peut pas être casté en org.Apache.hadoop.io.Text

Mon programme ressemble à

public class TopKRecord extends Configured implements Tool {

    public static class MapClass extends Mapper<Text, Text, Text, Text> {

        public void map(Text key, Text value, Context context) throws IOException, InterruptedException {
            // your map code goes here
            String[] fields = value.toString().split(",");
            String year = fields[1];
            String claims = fields[8];

            if (claims.length() > 0 && (!claims.startsWith("\""))) {
                context.write(new Text(year.toString()), new Text(claims.toString()));
            }
        }
    }
   public int run(String args[]) throws Exception {
        Job job = new Job();
        job.setJarByClass(TopKRecord.class);

        job.setMapperClass(MapClass.class);

        FileInputFormat.setInputPaths(job, new Path(args[0]));
        FileOutputFormat.setOutputPath(job, new Path(args[1]));

        job.setJobName("TopKRecord");
        job.setMapOutputValueClass(Text.class);
        job.setNumReduceTasks(0);
        boolean success = job.waitForCompletion(true);
        return success ? 0 : 1;
    }

    public static void main(String args[]) throws Exception {
        int ret = ToolRunner.run(new TopKRecord(), args);
        System.exit(ret);
    }
}

Les données ressemblent

"PATENT","GYEAR","GDATE","APPYEAR","COUNTRY","POSTATE","ASSIGNEE","ASSCODE","CLAIMS","NCLASS","CAT","SUBCAT","CMADE","CRECEIVE","RATIOCIT","GENERAL","ORIGINAL","FWDAPLAG","BCKGTLAG","SELFCTUB","SELFCTLB","SECDUPBD","SECDLWBD"
3070801,1963,1096,,"BE","",,1,,269,6,69,,1,,0,,,,,,,
3070802,1963,1096,,"US","TX",,1,,2,6,63,,0,,,,,,,,,
3070803,1963,1096,,"US","IL",,1,,2,6,63,,9,,0.3704,,,,,,,
3070804,1963,1096,,"US","OH",,1,,2,6,63,,3,,0.6667,,,,,,,

En exécutant ce programme, je vois ce qui suit sur la console

12/08/02 12:43:34 INFO mapred.JobClient: Task Id : attempt_201208021025_0007_m_000000_0, Status : FAILED
Java.lang.ClassCastException: org.Apache.hadoop.io.LongWritable cannot be cast to org.Apache.hadoop.io.Text
    at com.hadoop.programs.TopKRecord$MapClass.map(TopKRecord.Java:26)
    at org.Apache.hadoop.mapreduce.Mapper.run(Mapper.Java:144)
    at org.Apache.hadoop.mapred.MapTask.runNewMapper(MapTask.Java:764)
    at org.Apache.hadoop.mapred.MapTask.run(MapTask.Java:370)
    at org.Apache.hadoop.mapred.Child$4.run(Child.Java:255)
    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:1121)
    at org.Apache.hadoop.mapred.Child.main(Child.Java:249)

Je crois que les types de classe sont correctement mappés, Class Mapper ,

Veuillez me faire savoir ce que je fais mal ici?

23
daydreamer

Lorsque vous lisez un fichier avec un programme M/R, la clé d'entrée de votre mappeur doit être l'index de la ligne dans le fichier, tandis que la valeur d'entrée sera la ligne complète.

Donc, ici, ce qui se passe, c'est que vous essayez d'avoir l'index de ligne en tant qu'objet Text ce qui est faux, et vous avez besoin d'un LongWritable à la place pour que Hadoop ne se plaint pas du type.

Essayez plutôt ceci:

public class TopKRecord extends Configured implements Tool {

    public static class MapClass extends Mapper<LongWritable, Text, Text, Text> {

        public void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
            // your map code goes here
            String[] fields = value.toString().split(",");
            String year = fields[1];
            String claims = fields[8];

            if (claims.length() > 0 && (!claims.startsWith("\""))) {
                context.write(new Text(year.toString()), new Text(claims.toString()));
            }
        }
    }

    ...
}

Vous devez également reconsidérer une chose dans votre code: vous créez 2 Text objets pour chaque enregistrement que vous traitez. Vous ne devez créer ces 2 objets qu'au début, puis dans votre mappeur, définissez simplement leurs valeurs en utilisant la méthode set. Cela vous fera gagner beaucoup de temps si vous traitez une quantité décente de données.

44
Charles Menguy

vous devez définir la classe de format d'entrée

job.setInputFormatClass(KeyValueTextInputFormat.class);
job.setOutputFormatClass(TextOutputFormat.class);
10
user3690041