zoukankan      html  css  js  c++  java
  • 很多很好的mapreduce Job的代码例子

    访问原网站:http://www.cs.bgu.ac.il/~dsp112/Data_Processing,Chain,Join

     

    Data Processing Examples

    Based on Hadoop in Action, Chuck Lam, 2010, sections 4.1-4.3

    Data: NBER data sets of patents

    Tasks

    Citation list for each patent

    downloadtoggle
    62 lines ...
    1. import java.io.IOException;
    2.  
    3. import org.apache.hadoop.conf.Configuration;
    4. import org.apache.hadoop.fs.Path;
    5. import org.apache.hadoop.io.IntWritable;
    6. import org.apache.hadoop.io.Text;
    7. import org.apache.hadoop.mapreduce.Job;
    8. import org.apache.hadoop.mapreduce.Mapper;
    9. import org.apache.hadoop.mapreduce.Reducer;
    10. import org.apache.hadoop.mapreduce.Mapper.Context;
    11. import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
    12. import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
    13. import org.apache.hadoop.mapreduce.lib.output.TextOutputFormat;
    14.  
    15.  
    16. public class InvertAndGroupCitation {
    17.  
    18.     // The program gets the patent citation file (http://www.nber.org/patents/),
    19.     // which composed of <citing pattent> <cited patent> records,
    20.     // and generates for each patent, a list of the patent that cites it: <patent> [<citing patent>...]
    21.     //
    22.     // A modification of Chuck Lam's example (Hadoop In action, 2010, p. 68)
    23.  
    24.     public static class MapClass  extends Mapper<TextTextTextText{
    25.         // The map method inverts the given key and the value: citing-cited --> cited-citing
    26.         public void map(Text citingText citedContext context) throws IOException,  InterruptedException {
    27.             context.write(citedciting);
    28.         }
    29.     }
    30.  
    31.  
    32.     public static class ReduceClass  extends Reducer<Text,Text,Text,Text{
    33.         public void reduce(Text citedIterable<TextcitingsContext context) throws IOExceptionInterruptedException {
    34.         //The reduce method gets the citing list per cited key, and format the citing patents as a comma separated list
    35.             StringBuilder sb = new StringBuilder();
    36.             int i=0;
    37.             for (Text citing : citings) {
    38.                 if (i>0)
    39.                     sb.append("");
    40.                 sb.append(citing.toString());
    41.             }
    42.             context.write(citednew Text(sb.toString()));
    43.         }
    44.     }
    45.  
    46.  
    47.     public static void main(String[] args) throws Exception {
    48.         Configuration conf = new Configuration();
    49.         conf.set("key.value.separator.in.input.line",",");
    50.         Job job = new Job(conf"InvertAndGroupCitation");
    51.         job.setJarByClass(InvertAndGroupCitation.class);
    52.         job.setMapperClass(MapClass.class);
    53.         job.setReducerClass(ReduceClass.class);
    54.         FileInputFormat.addInputPath(jobnew Path(args[0]));
    55.         FileOutputFormat.setOutputPath(jobnew Path(args[1]));
    56.         job.setInputFormatClass(MyKeyValueTextInputFormat.class);
    57.         job.setOutputFormatClass(TextOutputFormat.class);
    58.         job.setOutputKeyClass(Text.class);
    59.         job.setOutputValueClass(Text.class);
    60.  
    61.         System.exit(job.waitForCompletion(true) ? 0 : 1);
    62.       }
    63. }

    Citations count for each patent

    downloadtoggle
    57 lines ...
    1. import java.io.IOException;
    2.  
    3. import org.apache.hadoop.conf.Configuration;
    4. import org.apache.hadoop.fs.Path;
    5. import org.apache.hadoop.io.IntWritable;
    6. import org.apache.hadoop.io.Text;
    7. import org.apache.hadoop.mapreduce.Job;
    8. import org.apache.hadoop.mapreduce.Mapper;
    9. import org.apache.hadoop.mapreduce.Reducer;
    10. import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
    11. import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
    12. import org.apache.hadoop.mapreduce.lib.output.TextOutputFormat;
    13.  
    14.  
    15. public class InvertAndCountCitation {
    16.  
    17.     // The program gets the patent citation file (http://www.nber.org/patents/),
    18.     // which composed of <citing pattent> <cited patent> records,
    19.     // and generates for each patent, the number of citing patents: <patent> <#citing patents>
    20.     //
    21.     // A modification of Chuck Lam's example (Hadoop In action, 2010, p. 68)
    22.  
    23.     public static class MapClass  extends Mapper<TextTextTextText{
    24.         // The map method inverts the given key and the value: citing-cited --> cited-citing
    25.         public void map(Text citingText citedContext context) throws IOException,  InterruptedException {
    26.             context.write(citedciting);
    27.         }
    28.     }
    29.  
    30.  
    31.     public static class ReduceClass  extends Reducer<Text,Text,Text,IntWritable{
    32.         public void reduce(Text citedIterable<TextcitingsContext context) throws IOExceptionInterruptedException {
    33.             // The reduce method gets the citing list per cited key, and emits the patent and the number of citings
    34.             int count=0;
    35.             for  (Text citing : citings) 
    36.                 count++;
    37.             context.write(citednew IntWritable(count));
    38.         }
    39.     }
    40.  
    41.  
    42.     public static void main(String[] args) throws Exception {
    43.         Configuration conf = new Configuration();
    44.         conf.set("key.value.separator.in.input.line",",");
    45.         Job job = new Job(conf"InverAndCountCitation");
    46.         job.setJarByClass(InvertAndGroupCitation.class);
    47.         job.setMapperClass(MapClass.class);
    48.         job.setReducerClass(ReduceClass.class);
    49.         FileInputFormat.addInputPath(jobnew Path(args[0]));
    50.         FileOutputFormat.setOutputPath(jobnew Path(args[1]));
    51.         job.setInputFormatClass(MyKeyValueTextInputFormat.class);
    52.         job.setOutputFormatClass(TextOutputFormat.class);
    53.         job.setOutputKeyClass(Text.class);
    54.         job.setOutputValueClass(Text.class);
    55.  
    56.         System.exit(job.waitForCompletion(true) ? 0 : 1);
    57.       }
    58. }

    Citations count histogram

    downloadtoggle
    58 lines ...
    1. import java.io.IOException;
    2.  
    3. import org.apache.hadoop.conf.Configuration;
    4. import org.apache.hadoop.fs.Path;
    5. import org.apache.hadoop.io.IntWritable;
    6. import org.apache.hadoop.io.Text;
    7. import org.apache.hadoop.mapreduce.Job;
    8. import org.apache.hadoop.mapreduce.Mapper;
    9. import org.apache.hadoop.mapreduce.Reducer;
    10. import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
    11. import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
    12. import org.apache.hadoop.mapreduce.lib.output.TextOutputFormat;
    13.  
    14.  
    15. public class CitationHistogram {
    16.  
    17.     // The program gets a pair list file of <patent> <number of citing patents>
    18.     // and generates a histogram on the number of citations
    19.     //
    20.     // A modification of Chuck Lam's example (Hadoop In action, 2010, p. 68)
    21.  
    22.     public static class MapClass  extends Mapper<TextIntWritableIntWritableIntWritable{
    23.         // The map procedure gets a pair of patent and its citation counts and emit each citation count
    24.         // with '1' value, indicating one instance of this count
    25.         private final static IntWritable one = new IntWritable(1);
    26.         private IntWritable citationCount = new IntWritable();
    27.         public void map(Text citedIntWritable numberOfCitationsContext context) throws IOException,  InterruptedException {
    28.             citationCount.set(Integer.parseInt(numberOfCitations.toString()));
    29.             context.write(citationCountone);
    30.         }
    31.     }
    32.  
    33.  
    34.     public static class ReduceClass  extends Reducer<IntWritable,IntWritable,IntWritable,IntWritable{
    35.         public void reduce(IntWritable numberOfCitationsIterable<IntWritablecountsContext context) throws IOExceptionInterruptedException {
    36.             // The reduce method sums all instances of each given count, in order to compose the histogram
    37.             int count = 0;
    38.             for (IntWritable count1 : counts)
    39.                 count += count1.get();
    40.             context.write(numberOfCitationsnew IntWritable(count));        }
    41.     }
    42.  
    43.  
    44.     public static void main(String[] args) throws Exception {
    45.         Configuration conf = new Configuration();
    46.         Job job = new Job(conf"CitationHistogram");
    47.         job.setJarByClass(CitationHistogram.class);
    48.         job.setMapperClass(MapClass.class);
    49.         job.setReducerClass(ReduceClass.class);
    50.         FileInputFormat.addInputPath(jobnew Path(args[0]));
    51.         FileOutputFormat.setOutputPath(jobnew Path(args[1]));
    52.         job.setInputFormatClass(MyKeyValueTextInputFormat.class);
    53.         job.setOutputFormatClass(TextOutputFormat.class);
    54.         job.setOutputKeyClass(IntWritable.class);
    55.         job.setOutputValueClass(IntWritable.class);
    56.  
    57.         System.exit(job.waitForCompletion(true) ? 0 : 1);
    58.       }
    59. }

    Distribution of patent attribute values

    downloadtoggle
    66 lines ...
    1. import java.io.IOException;
    2.  
    3. import org.apache.hadoop.conf.Configuration;
    4. import org.apache.hadoop.fs.Path;
    5. import org.apache.hadoop.io.DoubleWritable;
    6. import org.apache.hadoop.io.IntWritable;
    7. import org.apache.hadoop.io.LongWritable;
    8. import org.apache.hadoop.io.Text;
    9. import org.apache.hadoop.mapreduce.Job;
    10. import org.apache.hadoop.mapreduce.Mapper;
    11. import org.apache.hadoop.mapreduce.Reducer;
    12. import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
    13. import org.apache.hadoop.mapreduce.lib.input.TextInputFormat;
    14. import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
    15. import org.apache.hadoop.mapreduce.lib.output.TextOutputFormat;
    16.  
    17.  
    18. public class CountByAttribute {
    19.  
    20.     // The program gets the patent information file (http://www.nber.org/patents/),
    21.     // which composed of  a patent and its attribute, for each record,
    22.     // and generates for a given attribute, count distribution of its values
    23.     //
    24.     // A modification of Chuck Lam's example (Hadoop In action, 2010, p. 68)
    25.  
    26.     public static class MapClass  extends Mapper<LongWritableTextTextIntWritable{
    27.         private final static IntWritable one = new IntWritable(1);
    28.         private Text word = new Text();
    29.  
    30.         public void map(LongWritable keyText valueContext context) throws IOException,  InterruptedException {
    31.             // The map gets a record of a pattern, extracts the relevant attribute value,
    32.             // and emits the attribute and '1' value, indicating its existence
    33.             String fields[] = value.toString().split(",", -20);
    34.             word.set(fields[3])// year
    35.             //word.set(fields[4]); //country
    36.             context.write(word,one);
    37.         }
    38.     }
    39.  
    40.  
    41.     public static class ReduceClass  extends Reducer<Text,IntWritable,Text,IntWritable{
    42.         public void reduce(Text keyIterable<IntWritablevaluesContext context) throws IOExceptionInterruptedException {
    43.             // The reduce methods gets an attribute value and its counts and emits its total count
    44.             int sum = 0;
    45.             for (IntWritable value : values)
    46.                 sum += value.get();
    47.             context.write(keynew IntWritable(sum));
    48.         }
    49.     }
    50.  
    51.  
    52.     public static void main(String[] args) throws Exception {
    53.         Configuration conf = new Configuration();
    54.         Job job = new Job(conf"CountByAttribute");
    55.         job.setJarByClass(CountByAttribute.class);
    56.         job.setMapperClass(MapClass.class);
    57.         job.setReducerClass(ReduceClass.class);
    58.         FileInputFormat.addInputPath(jobnew Path(args[0]));
    59.         FileOutputFormat.setOutputPath(jobnew Path(args[1]));
    60.         job.setOutputFormatClass(TextOutputFormat.class);
    61.         job.setInputFormatClass(TextInputFormat.class);
    62.         job.setOutputKeyClass(Text.class);
    63.         job.setOutputValueClass(DoubleWritable.class);
    64.  
    65.         System.exit(job.waitForCompletion(true) ? 0 : 1);
    66.       }
    67. }

    Task Chain Example

    Pipeline of depending jobs by JobControl

    downloadtoggle
    63 lines ...
    1. import java.util.LinkedList;
    2.  
    3. import org.apache.hadoop.fs.Path;
    4. import org.apache.hadoop.io.IntWritable;
    5. import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
    6. import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
    7. import org.apache.hadoop.mapreduce.lib.output.TextOutputFormat;
    8. import org.apache.hadoop.mapred.InputFormat;
    9. import org.apache.hadoop.mapred.JobConf;
    10. import org.apache.hadoop.mapred.Mapper;
    11. import org.apache.hadoop.mapred.OutputFormat;
    12. import org.apache.hadoop.mapred.Reducer;
    13. import org.apache.hadoop.mapred.jobcontrol.Job;
    14. import org.apache.hadoop.mapred.jobcontrol.JobControl;
    15. import org.apache.hadoop.mapred.lib.ChainMapper;
    16. import org.apache.hadoop.mapreduce.lib.input.TextInputFormat;
    17. import org.apache.hadoop.mapreduce.lib.jobcontrol.ControlledJob;
    18. import org.apache.hadoop.conf.Configuration;
    19. import org.apache.hadoop.io.Text;
    20.  
    21. public class CitationPipeline {
    22.     public static void main(String[] args) {
    23.  
    24.         // Example of applying a pipeline of two mapper/reducer jobs, by using JobControl object,
    25.         // over a depending constraint.
    26.         // The first Job counts the number of citations for each patent,
    27.         // and the second job generate the histogram
    28.         // 0.21.0 compliant! in order to work with 0.20.2 use JobConf/JobClient mechanism
    29.         // Note: The code was not checked!!!
    30.  
    31.         try {
    32.             JobConf jobconf1 = new JobConf(new Configuration());
    33.             Job job1 = new Job(jobconf1);
    34.             jobconf1.setJarByClass(WordCount.class);
    35.             jobconf1.setMapperClass(InvertAndCount.MapClass.class);
    36.             jobconf1.setReducerClass(InvertAndCount.ReduceClass.class);
    37.             jobconf1.setOutputKeyClass(Text.class);
    38.             jobconf1.setOutputValueClass(IntWritable.class);
    39.             FileInputFormat.addInputPath(job1.getJob()new Path(args[0]));
    40.             FileOutputFormat.setOutputPath(job1.getJob()new Path("intermediate"));
    41.  
    42.             JobConf jobconf2 = new JobConf(new Configuration());
    43.             Job job2 = new Job(jobconf2);
    44.             jobconf2.setJarByClass(CitationHistogram.class);
    45.             jobconf2.setMapperClass(CitationHistogram.MapClass.class);
    46.             jobconf2.setReducerClass(CitationHistogram.ReduceClass.class);
    47.             jobconf2.setOutputKeyClass(IntWritable.class);
    48.             jobconf2.setOutputValueClass(IntWritable.class);
    49.             jobconf2.setInputFormat(MyKeyValueTextInputFormat.class);
    50.             jobconf2.setOutputFormat(TextOutputFormat.class);
    51.             FileInputFormat.addInputPath(job1.getJob()new Path("intermediate"));
    52.             FileOutputFormat.setOutputPath(job1.getJob()new Path(args[1]));
    53.  
    54.             job2.addDependingJob(job1);
    55.  
    56.             JobControl jc = new JobControl("JC");
    57.             jc.addJob(job1);
    58.             jc.addJob(job2);
    59.             jc.run();
    60.         } catch (Exception e) {
    61.  
    62.         }
    63.     }
    64. }

    Chaining of pre-processing and post-processing mappers to a reducer

    downloadtoggle
    55 lines ...
    1. import org.apache.hadoop.conf.Configuration;
    2. import org.apache.hadoop.fs.Path;
    3. import org.apache.hadoop.io.IntWritable;
    4. import org.apache.hadoop.io.LongWritable;
    5. import org.apache.hadoop.io.Text;
    6. import org.apache.hadoop.mapreduce.Job;
    7. import org.apache.hadoop.mapreduce.lib.chain.ChainReducer;
    8. import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
    9. import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
    10. import org.apache.hadoop.mapreduce.lib.output.TextOutputFormat;
    11. import org.apache.hadoop.mapred.lib.ChainMapper;
    12. import org.apache.hadoop.mapreduce.lib.input.TextInputFormat;
    13.  
    14. public class SpeechLemmaIndexingChain {
    15.     public static void main(String[] args) {
    16.  
    17.         // Example of direct chaining of several mappers (as preprocessors) to a reducer
    18.         // The first mapper gets a sound file and generate its text extraction
    19.         // The second mapper converts the tokens in the text to the equivalent lexemes
    20.         // The third mapper generates the inverted index
    21.         // The reducer emits the inverted index to the index file
    22.         // 0.21.0 compliant! in order to work with 0.20.2 use JobConf/JobClient mechanism
    23.         // Note: The code was not checked!!!
    24.  
    25.         Configuration conf = new Configuration();
    26.         Job job = new Job(conf"Job with chained tasks");
    27.         job.setJarByClass(SpeechLemmaIndexingChain.class);
    28.         job.setInputFormatClass(TextInputFormat.class);
    29.         job.setOutputFormatClass(TextOutputFormat.class);
    30.         FileInputFormat.setInputPaths(jobnew Path(args[0]));
    31.         FileOutputFormat.setOutputPath(jobnew Path(args[1]));
    32.  
    33.         Configuration mapText2SpeechConf = new Configuration(false);
    34.         ChainMapper.addMapper(jobSpeechRecognitionMapper.class,
    35.                               IntWritable.classSound.class,IntWritable.classText.class,
    36.                               truemapText2SpeechConf);
    37.  
    38.         Configuration mapLemmatizerConf = new Configuration(false);
    39.         ChainMapper.addMapper(jobLematizerMapper.class,
    40.                               IntWritable.classText.class,IntWritable.classText.class,
    41.                               truemapLemmatizerConf);
    42.  
    43.         Configuration mapIndexerConf = new Configuration(false);
    44.         ChainMapper.addMapper(jobIndexMapper.class,
    45.                               IntWritable.classText.class,Text.classIntWritable.class,
    46.                               truemapIndexerConf);
    47.  
    48.         Configuration reduceIndexerConf = new Configuration(false);
    49.         ChainReducer.setReducer(jobIndexReducer.class,
    50.                             LongWritable.classText.class,Text.classText.class,
    51.                             truereduceConf);
    52.  
    53.         System.exit(job.waitForCompletion(true) ? 0 : 1);
    54.  
    55.     }
    56. }

    Data join Example

    Reducer-side join implementation, based on tagged values

    downloadtoggle
    57 lines ...
    1. import java.io.DataInput;
    2. import java.io.DataOutput;
    3. import java.io.IOException;
    4.  
    5.  
    6. import org.apache.hadoop.io.Writable;
    7. import org.apache.hadoop.io.WritableComparable;
    8.  
    9.  
    10. public abstract class TaggedValue<T extends Writable,V extends Writableimplements Writable {
    11.  
    12.     // An implementation of value with tag, as a writable object
    13.  
    14.     protected T tag;
    15.     protected V value;
    16.  
    17.     TaggedValue() {
    18.         init();
    19.     }
    20.  
    21.     TaggedValue(T tag) {
    22.         this.tag = tag;
    23.         this.value = null;
    24.     }
    25.  
    26.     TaggedValue(T tag,V value) {
    27.         this.tag = tag;
    28.         this.value = value;
    29.     }
    30.  
    31.     protected abstract void init();
    32.  
    33.     @Override
    34.     public void readFields(DataInput data) throws IOException {
    35.         tag.readFields(data);
    36.         value.readFields(data);
    37.     }
    38.  
    39.     @Override
    40.     public void write(DataOutput data) throws IOException {
    41.         tag.write(data);
    42.         value.write(data);
    43.     }
    44.  
    45.     public String toString() {
    46.         return tag + ":" + value;
    47.     }
    48.  
    49.     public boolean equals(Object o) {
    50.         TaggedValue<T,Vother = (TaggedValue<T,V>)o;
    51.         return tag.equals(other.tag) && value.equals(other.value);
    52.     }
    53.  
    54.  
    55.     public T getTag() { return tag}
    56.     public V getvalue() { return value}
    57.     public void setValue(V value) { this.value = value}
    58. }
    downloadtoggle
    22 lines ...
    1. import org.apache.hadoop.io.Text;
    2.  
    3.  
    4. public class TextTaggedValue extends TaggedValue<Text,Text{
    5.     public TextTaggedValue() {
    6.         super();
    7.     }
    8.  
    9.     public TextTaggedValue(Text tag) {
    10.         super(tag);
    11.     }
    12.  
    13.     public TextTaggedValue(Text tag,Text value) {
    14.         super(tag,value);
    15.     }
    16.  
    17.     @Override
    18.     protected void init() {
    19.         tag = new Text();
    20.         value = new Text();
    21.     }
    22.  
    23. }
    downloadtoggle
    76 lines ...
    1. import java.io.IOException;
    2.  
    3. import org.apache.hadoop.io.Text;
    4. import org.apache.hadoop.mapred.FileSplit;
    5. import org.apache.hadoop.mapred.KeyValueLineRecordReader;
    6. import org.apache.hadoop.mapreduce.InputSplit;
    7. import org.apache.hadoop.mapreduce.RecordReader;
    8. import org.apache.hadoop.mapreduce.TaskAttemptContext;
    9.  
    10.  
    11. public class KeyTaggedValueLineRecordReader extends RecordReader<TextTextTaggedValue{
    12.  
    13.   // This record reader parses the input file into pairs of text key, and tagged value text,
    14.   // where the tag is based on the name of the input file
    15.   private KeyValueLineRecordReader lineReader;
    16.   private Text lineKeylineValue;
    17.   private Text key;
    18.   private Text tag;
    19.   private TextTaggedValue value;
    20.  
    21.   public static RecordReader<TextTextTaggedValuecreate(InputSplit splitTaskAttemptContext context) throws IOExceptionInterruptedException {
    22.     RecordReader<TextTextTaggedValueret = new KeyTaggedValueLineRecordReader();
    23.     ret.initialize(split,context);
    24.     return ret;
    25.   }
    26.  
    27.   private KeyTaggedValueLineRecordReader() throws IOException {
    28.   }
    29.  
    30.   public void initialize(InputSplit splitTaskAttemptContext context) throws IOException {
    31.       org.apache.hadoop.mapreduce.lib.input.FileSplit fs = (org.apache.hadoop.mapreduce.lib.input.FileSplit)split;
    32.       key = new Text()
    33.       tag = new Text(fs.getPath().getName().split("-")[0]);
    34.       value = new TextTaggedValue(tag);
    35.       lineReader = new KeyValueLineRecordReader(context.getConfiguration(),
    36.             new org.apache.hadoop.mapred.FileSplit(fs.getPath(),fs.getStart(),fs.getLength(),fs.getLocations()))
    37.       lineKey = lineReader.createKey();
    38.       lineValue = lineReader.createValue();
    39.   }
    40.  
    41.   public synchronized boolean nextKeyValue() throws IOException {
    42.     if (!lineReader.next(lineKeylineValue)) {
    43.       return false;
    44.     }
    45.     key.set(lineKey);
    46.     value.setValue(new Text(lineValue.toString()));
    47.     return true;
    48.   }
    49.  
    50.   public TextTaggedValue getCurrentValue() throws IOExceptionInterruptedException {
    51.     return value;
    52.   }
    53.  
    54.   public Text getCurrentKey() throws IOExceptionInterruptedException {
    55.     return key;
    56.   }
    57.  
    58.   public Text createKey() {
    59.     return new Text("");
    60.   }
    61.  
    62.   public Text createValue() {
    63.     return new Text("");
    64.  }
    65.  
    66.   public long getPos() throws IOException {
    67.       return lineReader.getPos();
    68.   }
    69.  
    70.   public float getProgress() throws IOException {
    71.     return lineReader.getProgress();
    72.   }
    73.  
    74.   public void close() throws IOException {
    75.     lineReader.close();
    76.   }
    77. }
    downloadtoggle
    15 lines ...
    1. import java.io.IOException;
    2.  
    3. import org.apache.hadoop.io.Text;
    4. import org.apache.hadoop.mapreduce.InputSplit;
    5. import org.apache.hadoop.mapreduce.RecordReader;
    6. import org.apache.hadoop.mapreduce.TaskAttemptContext;
    7. import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
    8.  
    9.  
    10. public class KeyTaggedValueTextInputFormat extends FileInputFormat<TextTextTaggedValue{
    11.  
    12.   // An implementation of an InputFormat of a text key and text tagged value
    13.   public RecordReader<TextTextTaggedValuecreateRecordReader(InputSplit split,TaskAttemptContext context) throws IOExceptionInterruptedException {
    14.     return KeyTaggedValueLineRecordReader.create(split,context);
    15.   }
    16. }
    downloadtoggle
    73 lines ...
    1. import java.io.IOException;
    2. import java.util.HashMap;
    3. import java.util.LinkedList;
    4. import java.util.List;
    5. import java.util.Map;
    6.  
    7. import org.apache.hadoop.conf.Configuration;
    8. import org.apache.hadoop.fs.Path;
    9. import org.apache.hadoop.io.Text;
    10. import org.apache.hadoop.mapreduce.Job;
    11. import org.apache.hadoop.mapreduce.Mapper;
    12. import org.apache.hadoop.mapreduce.Reducer;
    13. import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
    14. import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
    15. import org.apache.hadoop.mapreduce.lib.output.TextOutputFormat;
    16.  
    17.  
    18. public class ReduceSideJoin {
    19.  
    20.     // This program gets two types of values and produce a join-by-key value sets
    21.     public static class MapClass  extends Mapper<Text,TextTaggedValue,Text,TextTaggedValue{
    22.         // The map gets a key and tagged value (of 2 types) and emits the key and the value
    23.         public void map(Text keyTextTaggedValue valueContext context) throws IOException,  InterruptedException {
    24.             context.write(keyvalue);
    25.         }
    26.     }
    27.  
    28.  
    29.     public static class ReduceClass  extends Reducer<Text,TextTaggedValue,Text,Text{
    30.         public void reduce(Text keyIterable<TextTaggedValuetaggedValuesContext context) throws IOExceptionInterruptedException {
    31.             // The reduce gets a key and a set of values of two types (identified by their tags)
    32.             // and generates a cross product of the two types of values
    33.             Map<Text,List<Text>> mapTag2Values = new HashMap<Text,List<Text>>();
    34.             for (TextTaggedValue taggedValue : taggedValues) {
    35.                 List<Textvalues = mapTag2Values.get(taggedValue.getTag());
    36.                 if (values == null) {
    37.                     values = new LinkedList<Text>();
    38.                     mapTag2Values.put(taggedValue.getTag(),values);
    39.                 }
    40.                 values.add(taggedValue.getvalue());
    41.             }
    42.             crossProduct(key,mapTag2Values,context);
    43.         }
    44.  
    45.  
    46.         protected void crossProduct(Text key,Map<Text,List<Text>> mapTag2Values,Context context) throws IOExceptionInterruptedException {
    47.             // This specific implementation of the cross product, combine the data of the customers and the orders (
    48.             // of a given costumer id).
    49.             Text customer = mapTag2Values.get(new Text("customers")).get(0);
    50.             for (Text order : mapTag2Values.get("orders"))
    51.                 context.write(keynew Text(customer.toString() + "," + order.toString()));
    52.         }
    53.     }
    54.  
    55.  
    56.  
    57.     public static void main(String[] args) throws Exception {
    58.         Configuration conf = new Configuration();
    59.         Job job = new Job(conf"DataJoin");
    60.         job.setJarByClass(ReduceSideJoin.class);
    61.         job.setMapperClass(MapClass.class);
    62.         job.setReducerClass(ReduceClass.class);
    63.         FileInputFormat.addInputPath(jobnew Path(args[0]));
    64.         FileOutputFormat.setOutputPath(jobnew Path(args[1]));
    65.         job.setInputFormatClass(KeyTaggedValueTextInputFormat.class);
    66.         job.setOutputFormatClass(TextOutputFormat.class);
    67.         job.setOutputKeyClass(Text.class);
    68.         job.setOutputValueClass(Text.class);
    69.         job.setMapOutputKeyClass(Text.class);
    70.         job.setMapOutputValueClass(TextTaggedValue.class);
    71.  
    72.         System.exit(job.waitForCompletion(true) ? 0 : 1);
    73.       }
    74. }

    Reducer-side join implementation, based on secondary ordering of tagged keys

    downloadtoggle
    67 lines ...
    1. import java.io.DataInput;
    2. import java.io.DataOutput;
    3. import java.io.IOException;
    4.  
    5.  
    6. import org.apache.hadoop.io.Writable;
    7. import org.apache.hadoop.io.WritableComparable;
    8.  
    9.  
    10. public abstract class TaggedKey<T extends WritableComparable,K extends WritableComparable
    11.     implements WritableComparable {
    12.  
    13.     // An implementation of value with tag, as a writable object
    14.  
    15.     protected T tag;
    16.     protected K key;
    17.     
    18.     TaggedKey() {
    19.         init();
    20.     }
    21.  
    22.     TaggedKey(T tag) {
    23.         this.tag = tag;
    24.         this.key = null;
    25.     }
    26.  
    27.     TaggedKey(T tag,K key) {
    28.         this.tag = tag;
    29.         this.key = key;
    30.     }
    31.  
    32.     protected abstract void init();
    33.  
    34.     @Override
    35.     public void readFields(DataInput data) throws IOException {
    36.         tag.readFields(data);
    37.         key.readFields(data);
    38.     }
    39.  
    40.     @Override
    41.     public void write(DataOutput data) throws IOException {
    42.         tag.write(data);
    43.         key.write(data);
    44.     }
    45.  
    46.     @Override
    47.     public int compareTo(Object arg0) {
    48.         TaggedKey<T,Kother = (TaggedKey<T,K>)arg0;
    49.         int i = key.compareTo(other.key);
    50.         if (i==0)
    51.             i=tag.compareTo(other.tag);
    52.         return i;
    53.     }
    54.     
    55.     public String toString() {
    56.         return tag + ":" + key;
    57.     }
    58.  
    59.     public boolean equals(Object o) {
    60.         TaggedKey<T,Kother = (TaggedKey<T,K>)o;
    61.         return tag.equals(other.tag) && key.equals(other.key);
    62.     }
    63.  
    64.     public T getTag() { return tag}
    65.     public K getKey() { return key}
    66.     public void setKey(K key) { this.key = key}
    67.  
    68. }
    downloadtoggle
    21 lines ...
    1. import org.apache.hadoop.io.Text;
    2.  
    3.  
    4. public class TextTaggedKey extends TaggedKey<Text,Text{
    5.     public TextTaggedKey() {
    6.         super();
    7.     }
    8.  
    9.     public TextTaggedKey(Text tag) {
    10.         super(tag);
    11.     }
    12.  
    13.     public TextTaggedKey(Text tag,Text key) {
    14.         super(tag,key);
    15.     }
    16.  
    17.     @Override
    18.     public void init() {
    19.         tag = new Text();
    20.         key = new Text();
    21.     }
    22. }
    downloadtoggle
    77 lines ...
    1. import java.io.IOException;
    2.  
    3. import org.apache.hadoop.io.Text;
    4. import org.apache.hadoop.mapred.FileSplit;
    5. import org.apache.hadoop.mapred.KeyValueLineRecordReader;
    6. import org.apache.hadoop.mapreduce.InputSplit;
    7. import org.apache.hadoop.mapreduce.RecordReader;
    8. import org.apache.hadoop.mapreduce.TaskAttemptContext;
    9.  
    10.  
    11. public class TaggedKeyValueLineRecordReader extends RecordReader<TextTaggedKey,Text{
    12.  
    13.   // This record reader parses the input file into pairs of text key, and tagged value text,
    14.   // where the tag is based on the name of the input file
    15.   private KeyValueLineRecordReader lineReader;
    16.   private Text lineKeylineValue;
    17.   private Text tag;
    18.   private TextTaggedKey key;
    19.   private Text value;
    20.  
    21.   public static RecordReader<TextTaggedKey,Textcreate(InputSplit splitTaskAttemptContext context) throws IOExceptionInterruptedException {
    22.     RecordReader<TextTaggedKey,Textret = new TaggedKeyValueLineRecordReader();
    23.     ret.initialize(split,context);
    24.     return ret;
    25.   }
    26.  
    27.   private TaggedKeyValueLineRecordReader() throws IOException {
    28.   }
    29.  
    30.   public void initialize(InputSplit splitTaskAttemptContext context) throws IOException {
    31.       org.apache.hadoop.mapreduce.lib.input.FileSplit fs = (org.apache.hadoop.mapreduce.lib.input.FileSplit)split;
    32.       tag = new Text(fs.getPath().getName().split("-")[0]);
    33.       key = new TextTaggedKey(tag);
    34.       value = new Text();
    35.       lineReader = new KeyValueLineRecordReader(context.getConfiguration(),
    36.             new org.apache.hadoop.mapred.FileSplit(fs.getPath(),fs.getStart(),fs.getLength(),fs.getLocations()))
    37.       lineKey = lineReader.createKey();
    38.       lineValue = lineReader.createValue();
    39.  
    40.   }
    41.  
    42.   public synchronized boolean nextKeyValue() throws IOException {
    43.     if (!lineReader.next(lineKeylineValue)) {
    44.       return false;
    45.     }
    46.     key.setKey(new Text(lineKey.toString()));
    47.     value.set(lineValue);
    48.     return true;
    49.   }
    50.  
    51.   public Text getCurrentValue() throws IOExceptionInterruptedException {
    52.     return value;
    53.   }
    54.  
    55.   public TextTaggedKey getCurrentKey() throws IOExceptionInterruptedException {
    56.     return key;
    57.   }
    58.  
    59.   public Text createKey() {
    60.     return new Text("");
    61.   }
    62.  
    63.   public Text createValue() {
    64.     return new Text("");
    65.  }
    66.  
    67.   public long getPos() throws IOException {
    68.       return lineReader.getPos();
    69.   }
    70.  
    71.   public float getProgress() throws IOException {
    72.     return lineReader.getProgress();
    73.   }
    74.  
    75.   public void close() throws IOException {
    76.     lineReader.close();
    77.   }
    78. }
    downloadtoggle
    15 lines ...
    1. import java.io.IOException;
    2.  
    3. import org.apache.hadoop.io.Text;
    4. import org.apache.hadoop.mapreduce.InputSplit;
    5. import org.apache.hadoop.mapreduce.RecordReader;
    6. import org.apache.hadoop.mapreduce.TaskAttemptContext;
    7. import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
    8.  
    9.  
    10. public class TaggedKeyValueTextInputFormat extends FileInputFormat<TextTaggedKey,Text{
    11.  
    12.   // An InputFormat implementation of an InputFormat of text key and tagged value text
    13.   public RecordReader<TextTaggedKey,TextcreateRecordReader(InputSplit split,TaskAttemptContext context) throws IOExceptionInterruptedException {
    14.     return TaggedKeyValueLineRecordReader.create(split,context);
    15.   }
    16. }
    downloadtoggle
    102 lines ...
    1. import java.io.IOException;
    2. import java.util.HashMap;
    3. import java.util.LinkedList;
    4. import java.util.List;
    5. import java.util.Map;
    6.  
    7. import org.apache.hadoop.conf.Configuration;
    8. import org.apache.hadoop.fs.Path;
    9. import org.apache.hadoop.io.Text;
    10. import org.apache.hadoop.mapreduce.Job;
    11. import org.apache.hadoop.mapreduce.Mapper;
    12. import org.apache.hadoop.mapreduce.Partitioner;
    13. import org.apache.hadoop.mapreduce.Reducer;
    14. import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
    15. import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
    16. import org.apache.hadoop.mapreduce.lib.output.TextOutputFormat;
    17.  
    18.  
    19. public class ReduceSideJoinWithSecondaryOrdering {
    20.  
    21.     // In contrast to ReduceSideJoin, the joined data are written on-the-fly to the context,
    22.     // without aggregating the data in the memory, by using a secondary sort on the tagged keys
    23.     public static class MapClass  extends Mapper<TextTaggedKey,Text,TextTaggedKey,Text{
    24.         // The map gets a tagged key and a value and emits the key and the value
    25.         public void map(TextTaggedKey keyText valueContext context) throws IOException,  InterruptedException {
    26.             context.write(keyvalue);
    27.         }
    28.     }
    29.  
    30.  
    31.     public static class ReduceClass  extends Reducer<TextTaggedKey,Text,Text,Text{
    32.  
    33.         Text currentTag = new Text("");
    34.         Text currentKey = new Text("");
    35.         List<Textrelation1ValuesList = new LinkedList<Text>();
    36.         boolean writeMode = false;
    37.  
    38.         public void reduce(TextTaggedKey taggedKeyIterable<TextvaluesContext context) throws IOExceptionInterruptedException {
    39.             // The reduce gets a tagged key and a set of values
    40.             // In case the first data set (sorted by the tagged key) was completely received,
    41.             // any set of the second dataset is written on-the-fly to the context,
    42.             // by applying the cross product method.
    43.             if (!currentKey.equals(taggedKey.getKey())) {
    44.                 relation1ValuesList.clear();
    45.                 writeMode = false;
    46.             } else
    47.                 writeMode = !currentTag.equals(taggedKey.getTag());
    48.  
    49.             if (writeMode)
    50.                 crossProduct(taggedKey.getKey(),values,context);
    51.             else {
    52.                 for (Text value : values)
    53.                     relation1ValuesList.add(new Text(value.toString()));
    54.             }
    55.  
    56.             currentTag = new Text (taggedKey.getTag().toString());
    57.             currentKey = new Text (taggedKey.getKey().toString());
    58.         }
    59.  
    60.         protected void crossProduct(Text key,Iterable<Textrelation2Values ,Context context) throws IOExceptionInterruptedException {
    61.             // This specific implementation of the cross product, combine the data of the customers and the orders (
    62.             // of a given costumer id).
    63.             StringBuilder sb = new StringBuilder();
    64.             for (Text value1 : relation1ValuesList) {
    65.                 sb.append(",");
    66.                 sb.append(value1);
    67.             }
    68.             for (Text relation2Value : relation2Values ) {
    69.                 sb.append(",");
    70.                 sb.append(relation2Value);
    71.             }
    72.             context.write(keynew Text(sb.toString()));
    73.         }
    74.     }
    75.  
    76.     public static class PartitionerClass extends Partitioner<TextTaggedKey,Text{
    77.         // ensure that keys with same key are directed to the same reducer
    78.       public int getPartition(TextTaggedKey key,Text valueint numPartitions) {
    79.         return  Math.abs(key.getKey().hashCode()) % numPartitions;
    80.       }
    81.     }
    82.  
    83.  
    84.     public static void main(String[] args) throws Exception {
    85.         Configuration conf = new Configuration();
    86.         Job job = new Job(conf"DataJoin");
    87.         job.setJarByClass(ReduceSideJoinWithSecondaryOrdering.class);
    88.         job.setMapperClass(MapClass.class);
    89.         job.setReducerClass(ReduceClass.class);
    90.         job.setPartitionerClass(PartitionerClass.class);
    91.         FileInputFormat.addInputPath(jobnew Path(args[0]));
    92.         FileOutputFormat.setOutputPath(jobnew Path(args[1]));
    93.         job.setInputFormatClass(TaggedKeyValueTextInputFormat.class);
    94.         job.setOutputFormatClass(TextOutputFormat.class);
    95.         job.setOutputKeyClass(Text.class);
    96.         job.setOutputValueClass(Text.class);
    97.         job.setMapOutputKeyClass(TextTaggedKey.class);
    98.         job.setMapOutputValueClass(Text.class);
    99.  
    100.  
    101.         System.exit(job.waitForCompletion(true) ? 0 : 1);
    102.       }
    103. }

    Reducer-side join with Hadoop's 0.20.0 DataJoinReducerBase pattern

    Based on Hadoop in Action, Chuck Lam, 2010, section 5.2.1

    downloadtoggle
    106 lines ...
    1. import java.io.DataOutput;
    2. import java.io.IOException;
    3.  
    4. import org.apache.hadoop.conf.Configuration;
    5. import org.apache.hadoop.conf.Configured;
    6. import org.apache.hadoop.fs.Path;
    7. import org.apache.hadoop.io.Text;
    8. import org.apache.hadoop.io.Writable;
    9. import org.apache.hadoop.mapred.FileInputFormat;
    10. import org.apache.hadoop.mapred.FileOutputFormat;
    11. import org.apache.hadoop.mapred.JobClient;
    12. import org.apache.hadoop.mapred.JobConf;
    13. import org.apache.hadoop.util.Tool;
    14. import org.apache.hadoop.util.ToolRunner;
    15.  
    16.  
    17. // A demonstration of Hadoop's 0.20.0 DataJoinReducerBase pattern
    18. public class ReduceSideJoinByPattern extends Configured implements Tool {
    19.   public static class MapClass extends DataJoinMapperBase {
    20.     protected Text generateInputTag(String inputFile) {
    21.     String datasource = inputFile.split("-")[0];
    22.     return new Text(datasource);
    23.   }
    24.     protected Text generateGroupKey(TaggedMapOutput aRecord) {
    25.       String line = ((Text) aRecord.getData()).toString();
    26.       String[] tokens = line.split(",");
    27.       String groupKey = tokens[0];
    28.       return new Text(groupKey);
    29.     }
    30.   
    31.     protected TaggedMapOutput generateTaggedMapOutput(Object value) {
    32.       TaggedWritable retv = new TaggedWritable((Text) value);
    33.       retv.setTag(this.inputTag);
    34.       return retv;
    35.     }
    36.   }
    37.  
    38.   public static class Reduce extends DataJoinReducerBase {
    39.   
    40.   protected TaggedMapOutput combine(Object[] tagsObject[] valuesvalues) {
    41.     if (tags.length < 2) 
    42.       return null;
    43.     String joinedStr = "";
    44.     for (int i=0i<values.lengthi++) {
    45.     if (i > 0) 
    46.       joinedStr += ",";
    47.        TaggedWritable tw = (TaggedWritable) values[i];
    48.        String line = ((Text) tw.getData()).toString();
    49.        String[] tokens = line.split(","2);
    50.        joinedStr += tokens[1];
    51.     }
    52.     TaggedWritable retv = new TaggedWritable(new Text(joinedStr));
    53.     retv.setTag((Text) tags[0]);
    54.     return retv;
    55.   }
    56. }
    57.  
    58. public static class TaggedWritable extends TaggedMapOutput {
    59.  
    60.   private Writable data;
    61.     
    62.   public TaggedWritable(Writable data) {
    63.     this.tag = new Text("");
    64.     this.data = data;
    65.   }
    66.  
    67.   public Writable getData() {
    68.     return data;
    69.   }
    70.  
    71.   public void write(DataOutput out) throws IOException {
    72.     this.tag.write(out);
    73.     this.data.write(out);
    74.   }
    75.  
    76.   public void readFields(DataInput in) throws IOException {
    77.     this.tag.readFields(in);
    78.     this.data.readFields(in);
    79.   }
    80. }
    81.  
    82. public int run(String[] args) throws Exception {
    83.   Configuration conf = getConf();
    84.   JobConf job = new JobConf(confReduceSideJoinByPattern.class);
    85.   Path in = new Path(args[0]);
    86.   Path out = new Path(args[1]);
    87.   FileInputFormat.setInputPaths(jobin);
    88.   FileOutputFormat.setOutputPath(jobout);
    89.   job.setJobName("DataJoinByPattern");
    90.   job.setMapperClass(MapClass.class);
    91.   job.setReducerClass(Reduce.class);
    92.   job.setInputFormat(TextInputFormat.class);
    93.   job.setOutputFormat(TextOutputFormat.class);
    94.   job.setOutputKeyClass(Text.class);
    95.   job.setOutputValueClass(TaggedWritable.class);
    96.   job.set("mapred.textoutputformat.separator"",");
    97.   JobClient.runJob(job);
    98.   return 0;
    99. }
    100.  
    101.   public static void main(String[] args) throws Exception {
    102.     int res = ToolRunner.run(new Configuration(),
    103.     new ReduceSideJoin(),
    104.     args);
    105.     System.exit(res);
    106.   }
    107. }

    Mapper-side join with DistributedCache

    Based on Hadoop in Action, Chuck Lam, 2010, section 5.2.2

    downloadtoggle
    86 lines ...
    1. import java.io.BufferedReader;
    2. import java.io.FileReader;
    3. import java.io.IOException;
    4. import java.util.Hashtable;
    5.  
    6. import org.apache.hadoop.conf.Configuration;
    7. import org.apache.hadoop.conf.Configured;
    8. import org.apache.hadoop.filecache.DistributedCache;
    9. import org.apache.hadoop.fs.Path;
    10. import org.apache.hadoop.io.Text;
    11. import org.apache.hadoop.mapred.FileInputFormat;
    12. import org.apache.hadoop.mapred.FileOutputFormat;
    13. import org.apache.hadoop.mapred.InputFormat;
    14. import org.apache.hadoop.mapred.JobClient;
    15. import org.apache.hadoop.mapred.JobConf;
    16. import org.apache.hadoop.mapred.MapReduceBase;
    17. import org.apache.hadoop.mapred.Mapper;
    18. import org.apache.hadoop.mapred.OutputCollector;
    19. import org.apache.hadoop.mapred.Reporter;
    20. import org.apache.hadoop.mapred.TextOutputFormat;
    21. import org.apache.hadoop.util.Tool;
    22. import org.apache.hadoop.util.ToolRunner;
    23.  
    24. // A demostration of Hadoop's DistributedCache tool
    25. // 
    26.  
    27. public class MapperSideJoinWithDistributedCache extends Configured implements Tool {
    28.  
    29. public static class MapClass extends MapReduceBase implements Mapper<TextTextTextText{
    30.  
    31.   private Hashtable<StringStringjoinData = new Hashtable<StringString>();
    32.     
    33.   @Override
    34.   public void configure(JobConf conf) {
    35.     try {
    36.       Path [] cacheFiles = DistributedCache.getLocalCacheFiles(conf);
    37.       if (cacheFiles != null && cacheFiles.length > 0) {
    38.         String line;
    39.         String[] tokens;
    40.         BufferedReader joinReader = new BufferedReader(new FileReader(cacheFiles[0].toString()));
    41.         try {
    42.           while ((line = joinReader.readLine()) != null) {
    43.           tokens = line.split(","2);
    44.           joinData.put(tokens[0]tokens[1]);
    45.         }
    46.         } finally {
    47.           joinReader.close();
    48.         }
    49.       }
    50.     } catch(IOException e) {
    51.       System.err.println("Exception reading DistributedCache: " + e);
    52.     }
    53.   }
    54.  
    55.   public void map(Text keyText valueOutputCollector<TextTextoutput,  Reporter reporter) throws IOException {
    56.     String joinValue = joinData.get(key);
    57.     if (joinValue != null) {
    58.     output.collect(key,new Text(value.toString() + "," + joinValue));
    59.     }
    60.   }
    61. }
    62.  
    63.  
    64. public int run(String[] args) throws Exception {
    65.   Configuration conf = getConf();
    66.   JobConf job = new JobConf(confMapperSideJoinWithDistributedCache.class);
    67.   DistributedCache.addCacheFile(new Path(args[0]).toUri()conf)
    68.   Path in = new Path(args[1]);
    69.   Path out = new Path(args[2]);
    70.   FileInputFormat.setInputPaths(jobin);
    71.   FileOutputFormat.setOutputPath(jobout);
    72.   job.setJobName("DataJoin with DistributedCache");
    73.   job.setMapperClass(MapClass.class);
    74.   job.setNumReduceTasks(0);
    75.   job.setInputFormat((Class<? extends InputFormat>) MyKeyValueTextInputFormat.class);
    76.   job.setOutputFormat(TextOutputFormat.class);
    77.   job.set("key.value.separator.in.input.line"",");
    78.   JobClient.runJob(job);
    79.   return 0;
    80. }
    81.  
    82.   public static void main(String[] args) throws Exception {
    83.       int res = ToolRunner.run(new Configuration(),
    84.       new MapperSideJoinWithDistributedCache(),args);
    85.       System.exit(res);
    86.   }
    87. }
  • 相关阅读:
    hdu 2822 Dogs (BFS+优先队列)
    hdu 2757 Ocean Currents(BFS+DFS)
    hdu2844 Coins(普通的多重背包 + 二进制优化)
    hdu1495 && pku3414
    hdu1054 Strategic Game(树形DP)
    FckEditor V2.6 fckconfig.js中文注释
    数字文本控件
    统计在线用户列表 for .net WebForm
    智能客户端
    模拟Confirm的Web自定义控件
  • 原文地址:https://www.cnblogs.com/hengli/p/2834589.html
Copyright © 2011-2022 走看看