2017-10-21 89 views
0

J'essaie de comprendre un code Java. (Connaissance de base de Java)Comment l'objet est généré dans le code ci-dessous?

Voici son est

WordCountMapper Classe

package com.company; 

import org.apache.hadoop.io.IntWritable; 
import org.apache.hadoop.io.LongWritable; 
import org.apache.hadoop.io.Text; 
import org.apache.hadoop.mapreduce.Mapper; 
import java.io.IOException; 

public class WordCountMapper extends Mapper<LongWritable, Text, Text, IntWritable> { 
    @Override 
    public void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException { 

     String line = value.toString(); 
     for (String word : line.split(" ")) { 

      if (word.length() > 0) { 
       context.write(new Text(word), new IntWritable(1)); 

     } 

    } 

Mapper Classe

package org.apache.hadoop.mapreduce; 

import java.io.IOException; 
import org.apache.hadoop.classification.InterfaceAudience.Public; 
import org.apache.hadoop.classification.InterfaceStability.Stable; 

@InterfaceAudience.Public 
@InterfaceStability.Stable 
public class Mapper<KEYIN, VALUEIN, KEYOUT, VALUEOUT> { 
    public Mapper() { 
    } 

    protected void setup(Mapper<KEYIN, VALUEIN, KEYOUT, VALUEOUT>.Context context) 
      throws IOException, InterruptedException { 
    } 

    protected void map(KEYIN key, VALUEIN value, Mapper<KEYIN, VALUEIN, KEYOUT, VALUEOUT>.Context context) 
      throws IOException, InterruptedException { 
     context.write(key, value); 
    } 

    protected void cleanup(Mapper<KEYIN, VALUEIN, KEYOUT, VALUEOUT>.Context context) 
      throws IOException, InterruptedException { 
    } 

    public void run(Mapper<KEYIN, VALUEIN, KEYOUT, VALUEOUT>.Context context) throws IOException, InterruptedException { 
     setup(context); 
     while (context.nextKeyValue()) { 
      map(context.getCurrentKey(), context.getCurrentValue(), context); 
     } 
     cleanup(context); 
    } 

    public abstract class Context implements MapContext<KEYIN, VALUEIN, KEYOUT, VALUEOUT> { 
     public Context() { 
     } 

} 

}

classe Méthode principale

package com.company; 
import org.apache.hadoop.conf.Configuration; 
import org.apache.hadoop.fs.Path; 
import org.apache.hadoop.io.IntWritable; 
import org.apache.hadoop.io.Text; 
import org.apache.hadoop.mapreduce.Job; 
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat; 
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat; 

public class WordCount { 
public static void main(String[] args) throws Exception { 
if(args.length !=2){ 
System.err.println("Invalid Command"); 
System.err.println("Usage: WordCount <input path> <output path>"); 
System.exit(0); 
} 
Configuration conf = new Configuration(); 
Job job = new Job(conf, "wordcount"); 
job.setJarByClass(WordCount.class); 
FileInputFormat.addInputPath(job, new Path(args[0])); 
FileOutputFormat.setOutputPath(job, new Path(args[1])); 
job.setMapperClass(WordCountMapper.class); 
job.setReducerClass(WordCountReducer.class); 
job.setOutputKeyClass(Text.class); 
job.setOutputValueClass(IntWritable.class); 
} 

Mon doute est dans la classe WordCount comment la valeur de texte entre en vigueur? Je veux dire c'est un objet mais là où il est généré, il n'y a aucun signe dans la classe de méthode principale pour instancier l'instance de la classe Text.

Et ce que cela signifie -, je n'ai jamais vu cela avant de créer la classe comme dans le format ci-dessous

public class Mapper<KEYIN, VALUEIN, KEYOUT, VALUEOUT> 
{ 

Toutes les suggestions?

+0

Je pense que vous posez deux questions. Et votre code ne construit pas en raison d'erreurs de syntaxe. – nicomp

+2

Votre code est également illisible car il n'est pas correctement mis en retrait. –

+0

@nicomp, Peut-être ne va-t-il pas s'accumuler, mais j'essaie de comprendre seulement comment la valeur du texte est apparue? – JonyLinux

Répondre

3

Le code que vous avez collé est destiné à s'exécuter à l'aide de Hadoop MapReduce framework.

Fondamentalement, vous avez ici trois classes:

  • Le WordCount mappeur qui semble diviser les chaînes et les écrire dans le contexte de streaming Hadoop
  • Le Mapper de classe qui fait partie de la diffusion en continu Hadoop bibliothèques
  • Le pilote WordCount qui soumet le travail au cluster Hadoop

En fait, je m'attendais à une classe WordCountReducer dans votre question, mais cela ne semble pas être là. De toute façon: le texte apparaîtra en le copiant comme un fichier sur votre cluster Hadoop et doit être sur HDFS (Hadoop File System) avant d'exécuter le travail.

Cette ligne de code fait référence à un chemin HDFS:

FileInputFormat.addInputPath(job, new Path(args[0])); 

Et en ce qui concerne la question sur le code:

public class Mapper<KEYIN, VALUEIN, KEYOUT, VALUEOUT> 

Ce sont des types génériques (voir ce tutorial ici) qui doivent être déclaré chaque fois que vous sous-classez un mappeur.

Votre WordCount cartographe fait cette classe sous-classe Mapper et précise les quatre types:

public class WordCountMapper extends Mapper<LongWritable,Text,Text,IntWritable> 

Ce sont les correspondances:

KEYIN = LongWritable 
VALUEIN = Text 
KEYOUT = Text 
VALUEOUT = IntWritable 
+0

vous voulez dire, l'objet Text est instancié par framework hadoop lorsque nous mettons les données dans HDFS. Est-ce ce que vous essayez de dire? Parce que l'objet du texte contient les données qui sont dans HDFS, mais que cet objet ne semble pas être généré à partir de la classe de méthode principale, il ne reste plus que Hadoop lui-même. N'est-ce pas? – JonyLinux

+1

Oui, vous enregistrez le fichier dans HDFS, puis lorsque le pilote est exécuté, il se connecte au cluster Hadoop qui récupérera le fichier de HDFS pour vous et le mettra à la disposition de votre mappeur. L'objet Text est instancié par le framework Hadoop pour ainsi dire. –

+0

Ce n'est pas un code Hadoop Streaming. Le streaming lit stdin et écrit sur stdout. Ceci est un code MapReduce régulier –

0

L'API Hadoop crée les classes nécessaires.

Vous pouvez éventuellement définir un InputFormat, et cela doit être le même que les formats d'entrée utilisés par la classe dans le setMapperClass (les champs KEYIN, VALUEIN). De même, un format de sortie est également défini, et il y a des entrées et des sorties pour un réducteur.

Le format par défaut est TextInputFormat qui lit LongWritable, Text paires de valeurs de clé. La classe InputSplit est chargée de lire les octets du FileSystem et de créer les classes Writable qui sont transmises au mappeur.

Il convient de mentionner que rien ne se crée jusqu'à ce que vous commencez le travail comme

System.exit(job.waitForCompletion(true) ? 0 : 1);