NullPointerException in toString() method of CustomArrayWritable class, MapReduce - java

I'm trying to use Time_Ant10s(custom ArrayWritable class) as the Reducer's output.
I refer to this nice question: MapReduce Output ArrayWritable, but I get NullPointerException in context.write() in the last line of the Reducer.
I suppose get() in Time_Ant10s.toString() may return null, but I have no idea why this happens. Could you help me?
Main Method
public static void main(String[] args) throws Exception {
Configuration conf = new Configuration();
Job job = Job.getInstance(conf, "something");
// general
job.setJarByClass(CommutingTime1.class);
job.setMapperClass(Mapper1.class);
job.setReducerClass(Reducer1.class);
job.setNumReduceTasks(1);
job.setInputFormatClass (TextInputFormat.class);
// mapper output
job.setMapOutputKeyClass(Date_Uid.class);
job.setMapOutputValueClass(Time_Ant10.class);
// reducer output
job.setOutputFormatClass(CommaTextOutputFormat.class);
job.setOutputKeyClass(IntWritable.class);
job.setOutputValueClass(Time_Ant10s.class);
FileInputFormat.addInputPath(job, new Path(args[0]));
FileOutputFormat.setOutputPath(job, new Path(args[1]));
System.exit(job.waitForCompletion(true) ? 0 : 1);
}
Mapper
public static class Mapper1 extends Mapper<LongWritable, Text, Date_Uid, Time_Ant10> {
/* map as <date_uid, time_ant10> */
// omitted
}
}
Reducer
public static class Reducer1 extends Reducer<Date_Uid, Time_Ant10, IntWritable, Time_Ant10s> {
/* <date_uid, time_ant10> -> <date, time_ant10s> */
private IntWritable date = new IntWritable();
#Override
protected void reduce(Date_Uid date_uid, Iterable<Time_Ant10> time_ant10s, Context context) throws IOException, InterruptedException {
date.set(date_uid.getDate());
// count ants
int num = 0;
for(Time_Ant10 time_ant10 : time_ant10s){
num++;
}
if(num>=1){
Time_Ant10[] temp = new Time_Ant10[num];
int i=0;
for(Time_Ant10 time_ant10 : time_ant10s){
String time = time_ant10.getTimeStr();
int ant10 = time_ant10.getAnt10();
temp[i] = new Time_Ant10(time, ant10);
i++;
}
context.write(date, new Time_Ant10s(temp));
}
}
}
Writer
public static class CommaTextOutputFormat extends TextOutputFormat<IntWritable, Time_Ant10s> {
#Override
public RecordWriter<IntWritable, Time_Ant10s> getRecordWriter(TaskAttemptContext job) throws IOException, InterruptedException {
Configuration conf = job.getConfiguration();
String extension = ".txt";
Path file = getDefaultWorkFile(job, extension);
FileSystem fs = file.getFileSystem(conf);
FSDataOutputStream fileOut = fs.create(file, false);
return new LineRecordWriter<IntWritable, Time_Ant10s>(fileOut, ",");
}
}
Custom Writables
// Time
public static class Time implements Writable {
private int h, m, s;
public Time() {}
public Time(int h, int m, int s) {
this.h = h;
this.m = m;
this.s = s;
}
public Time(String time) {
String[] hms = time.split(":", 0);
this.h = Integer.parseInt(hms[0]);
this.m = Integer.parseInt(hms[1]);
this.s = Integer.parseInt(hms[2]);
}
public void set(int h, int m, int s) {
this.h = h;
this.m = m;
this.s = s;
}
public void set(String time) {
String[] hms = time.split(":", 0);
this.h = Integer.parseInt(hms[0]);
this.m = Integer.parseInt(hms[1]);
this.s = Integer.parseInt(hms[2]);
}
public int[] getTime() {
int[] time = new int[3];
time[0] = this.h;
time[1] = this.m;
time[2] = this.s;
return time;
}
public String getTimeStr() {
return String.format("%1$02d:%2$02d:%3$02d", this.h, this.m, this.s);
}
public int getTimeInt() {
return this.h * 10000 + this.m * 100 + this.s;
}
#Override
public void readFields(DataInput in) throws IOException {
h = in.readInt();
m = in.readInt();
s = in.readInt();
}
#Override
public void write(DataOutput out) throws IOException {
out.writeInt(h);
out.writeInt(m);
out.writeInt(s);
}
}
// Time_Ant10
public static class Time_Ant10 implements Writable {
private Time time;
private int ant10;
public Time_Ant10() {
this.time = new Time();
}
public Time_Ant10(Time time, int ant10) {
this.time = time;
this.ant10 = ant10;
}
public Time_Ant10(String time, int ant10) {
this.time = new Time(time);
this.ant10 = ant10;
}
public void set(Time time, int ant10) {
this.time = time;
this.ant10 = ant10;
}
public void set(String time, int ant10) {
this.time = new Time(time);
this.ant10 = ant10;
}
public int[] getTime() {
return this.time.getTime();
}
public String getTimeStr() {
return this.time.getTimeStr();
}
public int getTimeInt() {
return this.time.getTimeInt();
}
public int getAnt10() {
return this.ant10;
}
#Override
public void readFields(DataInput in) throws IOException {
time.readFields(in);
ant10 = in.readInt();
}
#Override
public void write(DataOutput out) throws IOException {
time.write(out);
out.writeInt(ant10);
}
}
// Time_Ant10s
public static class Time_Ant10s extends ArrayWritable {
public Time_Ant10s(){
super(Time_Ant10.class);
}
public Time_Ant10s(Time_Ant10[] time_ant10s){
super(Time_Ant10.class, time_ant10s);
}
#Override
public Time_Ant10[] get() {
return (Time_Ant10[]) super.get();
}
#Override
public String toString() {
int time, ant10;
Time_Ant10[] time_ant10s = get();
String output = "";
for(Time_Ant10 time_ant10: time_ant10s){
time = time_ant10.getTimeInt();
ant10 = time_ant10.getAnt10();
output += time + "," + ant10 + ",";
}
return output;
}
}
// Data_Uid
public static class Date_Uid implements WritableComparable<Date_Uid> {
// omitted
}
Error Message
java.lang.Exception: java.lang.NullPointerException
at org.apache.hadoop.mapred.LocalJobRunner$Job.runTasks(LocalJobRunner.java:462)
at org.apache.hadoop.mapred.LocalJobRunner$Job.run(LocalJobRunner.java:529)
Caused by: java.lang.NullPointerException
at CommutingTime1$Time_Ant10s.toString(CommutingTime1.java:179)
at org.apache.hadoop.mapreduce.lib.output.TextOutputFormat$LineRecordWriter.writeObject(TextOutputFormat.java:85)
at org.apache.hadoop.mapreduce.lib.output.TextOutputFormat$LineRecordWriter.write(TextOutputFormat.java:104)
at org.apache.hadoop.mapred.ReduceTask$NewTrackingRecordWriter.write(ReduceTask.java:558)
at org.apache.hadoop.mapreduce.task.TaskInputOutputContextImpl.write(TaskInputOutputContextImpl.java:89)
at org.apache.hadoop.mapreduce.lib.reduce.WrappedReducer$Context.write(WrappedReducer.java:105)
at CommutingTime1$Reducer1.reduce(CommutingTime1.java:323)
at CommutingTime1$Reducer1.reduce(CommutingTime1.java:291)
at org.apache.hadoop.mapreduce.Reducer.run(Reducer.java:171)
at org.apache.hadoop.mapred.ReduceTask.runNewReducer(ReduceTask.java:627)
at org.apache.hadoop.mapred.ReduceTask.run(ReduceTask.java:389)
at org.apache.hadoop.mapred.LocalJobRunner$Job$ReduceTaskRunnable.run(LocalJobRunner.java:319)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)

I found that the problem is Iterable in reduce can't be iterated twice. So I refer to this page and change the reducer and Time_Ant10s as below. Now everything is going fine.
#redflar3: Thank you very much for giving me hints. I totally misunderstood where my code has bug.
Reducer
public static class Reducer1 extends Reducer<Date_Uid, Time_Ant10, IntWritable, Time_Ant10s> {
private IntWritable date = new IntWritable();
#Override
protected void reduce(Date_Uid date_uid, Iterable<Time_Ant10> time_ant10s, Context context) throws IOException, InterruptedException {
String time = "";
int ant10;
date.set(date_uid.getDate());
ArrayList<Time_Ant10> temp_list = new ArrayList<Time_Ant10>();
for (Time_Ant10 time_ant10 : time_ant10s){
time = time_ant10.getTimeStr();
ant10 = time_ant10.getAnt10();
temp_list.add(new Time_Ant10(time, ant10));
}
if(temp_list.size() >= 1){
Time_Ant10[] temp_array = temp_list.toArray(new Time_Ant10[temp_list.size()]);
context.write(date, new Time_Ant10s(temp_array));
}
}
}
Time_Ant10s
public static class Time_Ant10s extends ArrayWritable {
public Time_Ant10s(){
super(Time_Ant10.class);
}
public Time_Ant10s(Time_Ant10[] time_ant10s){
super(Time_Ant10.class, time_ant10s);
}
#Override
public Time_Ant10[] get() {
return (Time_Ant10[]) super.get();
}
#Override
public String toString() {
int time, ant10;
Time_Ant10[] time_ant10s = get();
String output = "";
for(Time_Ant10 time_ant10: time_ant10s){
time = time_ant10.getTimeInt();
ant10 = time_ant10.getAnt10();
output += time + "," + ant10 + ",";
}
return output;
}
}

Related

How to add remaining batch of n elements into arrayList?

I'm currently learning to develop a simple blockchain program that reads sample data from .txt and creates a new block for every 10 transactions. I was wondering if the given sample data was 23 lines of transactions, is there a way to make a new block that consist of the last 3 transactions ?
Current Output
Block[header=Header[index=0,currHash=51aa6b7cf5fb821189d58b5c995b4308370888efcaac469d79ad0a5d94fb0432, prevHash=0, timestamp=1654785847112], tranx=null]
Block[header=Header[index=0,currHash=92b3582095e2403c68401448e8a34864e8465d0ea51c05f11c23810ec36b4868, prevHash=0, timestamp=1654785847385], tranx=Transaction [tranxLst=[alice|bob|credit|1.0, alice|bob|debit|2.0, alice|bob|debit|3.0, alice|bob|credit|4.0, alice|bob|debit|5.0, alice|bob|credit|6.0, alice|bob|debit|7.0, alice|bob|debit|8.0, alice|bob|debit|9.0, alice|bob|debit|10.0]]]
Block[header=Header[index=0,currHash=7488c600433d78e0fb8586e71a010b1d39a040cb101cc6e3418668d21b614519, prevHash=0, timestamp=1654785847386], tranx=Transaction [tranxLst=[alice|bob|credit|11.0, alice|bob|credit|12.0, alice|bob|debit|13.0, alice|bob|debit|14.0, alice|bob|credit|15.0, alice|bob|credit|16.0, alice|bob|credit|17.0, alice|bob|debit|18.0, alice|bob|credit|19.0, alice|bob|credit|20.0]]]
What I want
Block[header=Header[index=0,currHash=51aa6b7cf5fb821189d58b5c995b4308370888efcaac469d79ad0a5d94fb0432, prevHash=0, timestamp=1654785847112], tranx=null]
Block[header=Header[index=0,currHash=92b3582095e2403c68401448e8a34864e8465d0ea51c05f11c23810ec36b4868, prevHash=0, timestamp=1654785847385], tranx=Transaction [tranxLst=[alice|bob|credit|1.0, alice|bob|debit|2.0, alice|bob|debit|3.0, alice|bob|credit|4.0, alice|bob|debit|5.0, alice|bob|credit|6.0, alice|bob|debit|7.0, alice|bob|debit|8.0, alice|bob|debit|9.0, alice|bob|debit|10.0]]]
Block[header=Header[index=0,currHash=7488c600433d78e0fb8586e71a010b1d39a040cb101cc6e3418668d21b614519, prevHash=0, timestamp=1654785847386], tranx=Transaction [tranxLst=[alice|bob|credit|11.0, alice|bob|credit|12.0, alice|bob|debit|13.0, alice|bob|debit|14.0, alice|bob|credit|15.0, alice|bob|credit|16.0, alice|bob|credit|17.0, alice|bob|debit|18.0, alice|bob|credit|19.0, alice|bob|credit|20.0]]]
Block[header=Header[index=0,currHash=7488c600433d78e0fb8586e71a010b1d39a040cb101cc6e3418668d21b614520, prevHash=0, timestamp=1654785847387], tranx=Transaction [tranxLst=[alice|bob|credit|21.0, alice|bob|credit|22.0, alice|bob|debit|23.0]]]
my code:
Client app
public static void main(String[] args) throws IOException {
homework();
}
static void homework() throws IOException {
int count = 0;
Transaction tranxLst = new Transaction();
Block genesis = new Block("0");
System.out.println(genesis);
BufferedReader bf = new BufferedReader(new FileReader("dummytranx.txt"));
String line = bf.readLine();
while (line != null) {
tranxLst.add(line);
line = bf.readLine();
count++;
if (count % 10 == 0) {
Block newBlock = new Block(genesis.getHeader().getPrevHash());
newBlock.setTranx(tranxLst);
System.out.println(newBlock);
tranxLst.getTranxLst().clear();
}
}
bf.close();
}
Transaction class
public class Transaction implements Serializable {
public static final int SIZE = 10;
/**
* we will comeback to generate the merkle root ie., hash of merkle tree
* merkleRoot = hash
*/
private String merkleRoot = "9a0885f8cd8d94a57cd76150a9c4fa8a4fed2d04c244f259041d8166cdfeca1b8c237b2c4bca57e87acb52c8fa0777da";
// private String merkleRoot;
public String getMerkleRoot() {
return merkleRoot;
}
public void setMerkleRoot(String merkleRoot) {
this.merkleRoot = merkleRoot;
}
/**
* For the data collection, u may want to choose classic array or collection api
*/
private List<String> tranxLst;
public List<String> getTranxLst() {
return tranxLst;
}
public Transaction() {
tranxLst = new ArrayList<>(SIZE);
}
/**
* add()
*/
public void add(String tranx) {
tranxLst.add(tranx);
}
#Override
public String toString() {
return "Transaction [tranxLst=" + tranxLst + "]";
}
}
Block class
public class Block implements Serializable {
private Header header;
public Header getHeader() {
return header;
}
private Transaction tranx;
public Block(String previousHash) {
header = new Header();
header.setTimestamp(new Timestamp(System.currentTimeMillis()).getTime());
header.setPrevHash(previousHash);
String blockHash = Hasher.sha256(getBytes());
header.setCurrHash(blockHash);
}
/**
* getBytes of the Block object
*/
private byte[] getBytes() {
try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(baos);) {
out.writeObject(this);
return baos.toByteArray();
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public Transaction getTranx() {
return tranx;
}
/**
* aggregation rel
*/
public void setTranx(Transaction tranx) {
this.tranx = tranx;
}
/**
* composition rel
*/
public class Header implements Serializable {
private int index;
private String currHash, prevHash;
private long timestamp;
// getset methods
public String getCurrHash() {
return currHash;
}
public int getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
public void setCurrHash(String currHash) {
this.currHash = currHash;
}
public String getPrevHash() {
return prevHash;
}
public void setPrevHash(String prevHash) {
this.prevHash = prevHash;
}
public long getTimestamp() {
return timestamp;
}
public void setTimestamp(long timestamp) {
this.timestamp = timestamp;
}
#Override
public String toString() {
return "Header [index=" + index + ", currHash=" + currHash + ", prevHash=" + prevHash + ", timestamp="
+ timestamp + "]";
}
}
#Override
public String toString() {
return "Block [header=" + header + ", tranx=" + tranx + "]";
}
}
enter code here
Instead of using a counter in the conditional statement, try ForLoop.
static void homework() throws IOException {
Transaction tranxLst = new Transaction();
Block genesis = new Block("0");
System.out.println(genesis);
BufferedReader bf = new BufferedReader(new FileReader("dummytranx.txt"));
String line = bf.readLine();
while (line != null) {
for (int i = 0; i < 10; i++) {
tranxLst.add(line);
line = bf.readLine();
if (line == null) {
break;
}
}
Block newBlock = new Block(genesis.getHeader().getPrevHash());
newBlock.setTranx(tranxLst);
System.out.println(newBlock);
tranxLst.getTranxLst().clear();
}
bf.close();
}

Reduce does not start, After map completes

Below is the code for my Implementation of a simple MapReduce Job using a custom writable comparable.
public class MapReduceKMeans {
public static class MapReduceKMeansMapper extends
Mapper<Object, Text, SongDataPoint, Text> {
public void map(Object key, Text value, Context context)
throws InterruptedException, IOException {
String str = value.toString();
// Reading Line one by one from the input CSV.
String split[] = str.split(",");
String trackId = split[0];
String title = split[1];
String artistName = split[2];
SongDataPoint songDataPoint =
new SongDataPoint(new Text(trackId), new Text(title),
new Text(artistName));
context.write(songDataPoint, new Text());
}
}
public static class MapReduceKMeansReducer extends
Reducer<SongDataPoint, Text, Text, NullWritable> {
public void reduce(SongDataPoint key, Iterable<Text> values,
Context context) throws IOException, InterruptedException {
StringBuilder sb = new StringBuilder();
sb.append(key.getTrackId()).append("\t").
append(key.getTitle()).append("\t")
.append(key.getArtistName()).append("\t");
String write = sb.toString();
context.write(new Text(write), NullWritable.get());
}
}
public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
Configuration conf = new Configuration();
String[] otherArgs = new GenericOptionsParser(conf, args)
.getRemainingArgs();
if (otherArgs.length != 2) {
System.err
.println("Usage:<CsV Out Path> <Final Out Path>");
System.exit(2);
}
Job job = new Job(conf, "Song Data Trial");
job.setJarByClass(MapReduceKMeans.class);
job.setMapperClass(MapReduceKMeansMapper.class);
job.setReducerClass(MapReduceKMeansReducer.class);
job.setOutputKeyClass(SongDataPoint.class);
job.setOutputValueClass(Text.class);
FileInputFormat.addInputPath(job, new Path(otherArgs[0]));
FileOutputFormat.setOutputPath(job, new Path(otherArgs[1]));
System.exit(job.waitForCompletion(true) ? 0 : 1);
}
}
When I debug my code reads all the rows in the CSV file but it does not enter the reduce job at all.
I also have made use of the SongDataPoint as my custom writable.
Its code is as below.
public class SongDataPoint implements WritableComparable<SongDataPoint> {
Text trackId;
Text title;
Text artistName;
public SongDataPoint() {
this.trackId = new Text();
this.title = new Text();
this.artistName = new Text();
}
public SongDataPoint(Text trackId, Text title, Text artistName) {
this.trackId = trackId;
this.title = title;
this.artistName = artistName;
}
#Override
public void readFields(DataInput in) throws IOException {
this.trackId.readFields(in);
this.title.readFields(in);
this.artistName.readFields(in);
}
#Override
public void write(DataOutput out) throws IOException {
}
public Text getTrackId() {
return trackId;
}
public void setTrackId(Text trackId) {
this.trackId = trackId;
}
public Text getTitle() {
return title;
}
public void setTitle(Text title) {
this.title = title;
}
public Text getArtistName() {
return artistName;
}
public void setArtistName(Text artistName) {
this.artistName = artistName;
}
#Override
public int compareTo(SongDataPoint o) {
// TODO Auto-generated method stub
int compare = getTrackId().compareTo(o.getTrackId());
return compare;
}
}
Any help is appreciated. Thanks.
Your output key class class as per Driver is SongDataPoint.class and output value class as Text.class but actually you are writing Text as key in Reducer and Nullwritable as value in Reducer.
you should also specify the Mapper output values as following.
job.setMapOutputKeyClass(SongDataPoint.class);
job.setMapOutputValueClass(Text.class);
My write method in my CustomWritable Class was left blank by mistake. It solved the problem after writing the proper code in it.
public void write(DataOutput out) throws IOException {
}

How can I find the line numbers of a method invocation in Java

I need to get the line numbers a specific method is invoked in a .class file.
I took a look at How can I find all the methods that call a given method in Java? It returns the methods that call a method but I need the line numbers in the caller methods, as well.
I solved it by manipulating the code on that link a little
import java.io.InputStream;
import org.objectweb.asm.*;
import org.objectweb.asm.commons.*;
public class App{
public static void main( String[] args ) {
try {
Test test = new Test();
test.findCallers();
}catch (Exception e){
e.printStackTrace();
}
}
}
class Test {
private String targetClass;
private Method targetMethod;
private AppClassVisitor cv;
class AppMethodVisitor extends MethodVisitor {
boolean callsTarget;
int line;
public AppMethodVisitor() {
super(Opcodes.ASM5);
}
public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
if (owner.equals("Fibonacci") && name.equals("join") && desc.equals("()V")) {
callsTarget = true;
System.out.println("Function join called on " + this.line);
}
super.visitMethodInsn(opcode, owner, name, desc, itf);
}
public void visitCode() {
callsTarget = false;
}
public void visitLineNumber(int line, Label start) {
this.line = line;
}
public void visitEnd() {
if (callsTarget){
System.out.println(cv.className + cv.methodName + cv.methodDesc + line);
}
}
}
class AppClassVisitor extends ClassVisitor {
private AppMethodVisitor mv = new AppMethodVisitor();
public String className;
public String methodName;
public String methodDesc;
public AppClassVisitor() {
super(Opcodes.ASM5);
}
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
className = name;
}
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
methodName = name;
methodDesc = desc;
return mv;
}
}
public void findCallers() throws Exception {
InputStream stream = App.class.getResourceAsStream("Fibonacci.class");
ClassReader reader = new ClassReader(stream);
cv = new AppClassVisitor();
reader.accept(cv, 0);
stream.close();
}
}
Fibonacci.java content:
public class Fibonacci extends Thread{
int n;
int result;
public Fibonacci(int n){
this.n = n;
}
public void run(){
if((n == 0) || (n == 1)){
result = 1;
}else{
Fibonacci f1 = new Fibonacci(n - 1);
Fibonacci f2 = new Fibonacci(n - 2);
f1.start();
f2.start();
try{
f1.join();
f2.join();
}catch(InterruptedException e){
e.printStackTrace();
}
result = f1.getResult() + f2.getResult();
}
}
public int getResult(){
return result;
}
public static void main(String[] args) {
Fibonacci f1 = new Fibonacci(5);
f1.start();
try{
f1.join();
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println("Answer is " + f1.getResult());
}
}

Performing multiple computations with Hadoop Map Reduce

I have a map reduce program for finding the min/max for 2 separate properties for each year. This works, for the most part, using a single node cluster in hadoop. Here is my currently setup:
public class MaxTemperatureReducer extends
Reducer<Text, Stats, Text, Stats> {
private Stats result = new Stats();
#Override
public void reduce(Text key, Iterable<Stats> values, Context context)
throws IOException, InterruptedException {
int maxValue = Integer.MIN_VALUE;
int minValue = Integer.MAX_VALUE;
int sum = 0;
for (Stats value : values) {
result.setMaxTemp(Math.max(maxValue, value.getMaxTemp()));
result.setMinTemp(Math.min(minValue, value.getMinTemp()));
result.setMaxWind(Math.max(maxValue, value.getMaxWind()));
result.setMinWind(Math.min(minValue, value.getMinWind()));
sum += value.getCount();
}
result.setCount(sum);
context.write(key, result);
}
}
public class MaxTemperatureMapper extends
Mapper<Object, Text, Text, Stats> {
private static final int MISSING = 9999;
private Stats outStat = new Stats();
#Override
public void map(Object key, Text value, Context context)
throws IOException, InterruptedException {
String[] split = value.toString().split("\\s+");
String year = split[2].substring(0, 4);
int airTemperature;
airTemperature = (int) Float.parseFloat(split[3]);
outStat.setMinTemp((float)airTemperature);
outStat.setMaxTemp((float)airTemperature);
outStat.setMinWind(Float.parseFloat(split[12]));
outStat.setMaxWind(Float.parseFloat(split[14]));
outStat.setCount(1);
context.write(new Text(year), outStat);
}
}
public class MaxTemperatureDriver extends Configured implements Tool {
public int run(String[] args) throws Exception {
if (args.length != 2) {
System.err
.println("Usage: MaxTemperatureDriver <input path> <outputpath>");
System.exit(-1);
}
Job job = new Job();
job.setJarByClass(MaxTemperatureDriver.class);
job.setJobName("Max Temperature");
job.setMapperClass(MaxTemperatureMapper.class);
job.setCombinerClass(MaxTemperatureReducer.class);
job.setReducerClass(MaxTemperatureReducer.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(Stats.class);
FileInputFormat.addInputPath(job, new Path(args[0]));
FileOutputFormat.setOutputPath(job, new Path(args[1]));
System.exit(job.waitForCompletion(true) ? 0 : 1);
boolean success = job.waitForCompletion(true);
return success ? 0 : 1;
}
public static void main(String[] args) throws Exception {
MaxTemperatureDriver driver = new MaxTemperatureDriver();
int exitCode = ToolRunner.run(driver, args);
System.exit(exitCode);
}
}
Currently it only prints the Min/Max for the temp and windspeed for each year. I am sure it is a simple implementation but cannot find a answer anywhere. I want to try and find the top 5 min/max for each year. Any suggestions?
Let me assume the following signature for your Stats class.
/* the stats class need to be a writable, the below is just a demo*/
public class Stats {
public float getTemp() {
return temp;
}
public void setTemp(float temp) {
this.temp = temp;
}
public float getWind() {
return wind;
}
public void setWind(float wind) {
this.wind = wind;
}
private float temp;
private float wind;
}
With this, let us change the reducer as below.
SortedSet<Float> tempSetMax = new TreeSet<Float>();
SortedSet<Float> tempSetMin = new TreeSet<Float>();
SortedSet<Float> windSetMin = new TreeSet<Float>();
SortedSet<Float> windSetMax = new TreeSet<Float>();
List<Stats> values = new ArrayList<Float>();
for (Stats value : values) {
float temp = value.getTemp();
float wind = value.getWind();
if (tempSetMax.size() < 5) {
tempSetMax.add(temp);
} else {
float currentMinValue = tempSetMax.first();
if (temp > currentMinValue) {
tempSetMax.remove(currentMinValue);
tempSetMax.add(temp);
}
}
if (tempSetMin.size() < 5) {
tempSetMin.add(temp);
} else {
float currentMaxValue = tempSetMin.last();
if (temp < currentMaxValue) {
tempSetMax.remove(currentMaxValue);
tempSetMax.add(temp);
}
}
if (windSetMin.size() < 5) {
windSetMin.add(wind);
} else {
float currentMaxValue = windSetMin.last();
if (wind < currentMaxValue) {
windSetMin.remove(currentMaxValue);
windSetMin.add(temp);
}
}
if (windSetMax.size() < 5) {
windSetMax.add(wind);
} else {
float currentMinValue = windSetMax.first();
if (wind > currentMinValue) {
windSetMax.remove(currentMinValue);
windSetMax.add(temp);
}
}
}
Now you can write to context the toString() of each list, or you can create a custom writable. In my code, please change the Stats according to your requirement. It needs to be a Writable. The above is just for demonstrating the example flow.
Here is the code from the MR Design Patterns Book to get the top 10. There is also code for other MR design patterns in the same GitHub location.

Java warning and error (read object)

My goal: save one ArrayList to a .dat file, after read this file and in the end print this array.
To save the ArrayList, "equipas" is one ArrayList< Equipa>, I use this function:
saveMyFile("Equipas.dat", (Object) equipas);
To read:
public static ArrayList<Equipa> readMyFile(String s){
ArrayList<Equipa> novo = new ArrayList<Equipa>();
try {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(s));
novo = (ArrayList<Equipa>) ois.readObject();
ois.close();
}
catch(IOException er) { System.out.println(er.getMessage()); }
catch(ClassNotFoundException er) { System.out.println(er.getMessage()); }
return novo;}
In this read function, I have one Compilation Warning: "…uses unchecked or unsafe operations. Recompile with - Xlint:unchecked for details."
To save:
public static void saveMyFile(String s, Object o)
{
try {
ObjectOutputStream oos = new ObjectOutputStream( new FileOutputStream(s));
oos.writeObject(o);
oos.flush();
oos.close();
}
catch(IOException e) { System.out.println(e.getMessage()); }
}
Finally, I want to print the ArrayList's info:
ArrayList<Equipa> cena = new ArrayList<Equipa>();
cena=(ArrayList<Equipa>) readMyFile("Equipas.dat");
for(Equipa e:cena)
e.toString();
Error when I try to run:
" writing aborted; java.io.NotSerializableException: Equipa"
Equipa havs the Serializable:
import java.util.*;
import java.io.*;
public class Equipa implements Serializable
{
private String nome;
private Carro carro;
private ArrayList<Piloto> pilotos;
private double tempoDecorrido;
private int pontos;
private boolean desistiu;
private int voltaDesistencia;
private Piloto piloto;
/**
* Constructor for objects of class Equipa
*/
public Equipa()
{
this.nome = "NA";
this.carro = null;
this.pilotos = new ArrayList<Piloto>();
this.tempoDecorrido = 0;
this.pontos = 0;
this.desistiu = false;
this.voltaDesistencia = 0;
this.piloto = null;
}
public Equipa(String nome, Carro carro, ArrayList<Piloto> pilotos)
{
this.nome = nome;
this.carro = carro;
//this.pilotos = new ArrayList<Piloto>(pilotos);
this.pilotos = pilotos;
this.tempoDecorrido = 0;
this.pontos = 0;
this.desistiu = false;
this.voltaDesistencia = 0;
//this.piloto = pilotos.get(0);
}
public Equipa (Equipa e)
{
this.nome = e.getNome();
this.carro = e.getCarro();
this.pilotos = e.getPilotos();
this.tempoDecorrido = e.getTempoDecorrido();
this.pontos = e.getPontos();
this.desistiu = e.getDesistiu();
this.voltaDesistencia = e.getVoltaDesistencia();
//this.piloto = e.getPiloto();
}
/** Getters */
public String getNome()
{
return this.nome;
}
public Carro getCarro()
{
return this.carro;
}
public ArrayList<Piloto> getPilotos()
{
return new ArrayList<Piloto>(this.pilotos);
}
public double getTempoDecorrido()
{
return this.tempoDecorrido;
}
public int getPontos()
{
return this.pontos;
}
public boolean getDesistiu()
{
return this.desistiu;
}
public int getVoltaDesistencia()
{
return this.voltaDesistencia;
}
public Piloto getPiloto()
{
return this.piloto;
}
/** Setters */
public void setNome(String nome)
{
this.nome = nome;
}
public void setCarro(Carro carro)
{
this.carro = carro;
}
public void setPilotos(ArrayList<Piloto> pilotos)
{
this.pilotos = new ArrayList<Piloto>(pilotos);
}
public void setTempoDecorrido(double tempoDecorrido)
{
this.tempoDecorrido = tempoDecorrido;
}
public void setPontos(int pontos)
{
this.pontos = pontos;
}
public void setDesistiu(boolean desistiu)
{
this.desistiu = desistiu;
}
public void setVoltaDesistencia(int voltaDesistencia)
{
this.voltaDesistencia = voltaDesistencia;
}
public void setPiloto(Piloto piloto)
{
this.piloto = piloto;
}
/** Outros Métodos */
public Equipa clone()
{
return new Equipa(this);
}
public boolean equals(Equipa e)
{
if(this.nome == e.getNome())
return true;
else
return false;
}
public String getStringPilotos()
{
String s = new String();
for(Piloto p: this.pilotos)
s = (s + ", " + p.getNome());
return s;
}
public String toString()
{
return new String("Nome da equipa: " + nome + "; Categoria do carro: " + carro.getClass().getName() + "; Marca e modelo: " + carro.getMarca() + " " + carro.getModelo() + "; Pilotos: " + getStringPilotos())+"\n";
}
Implementing Serializable means that serialization is permitted, but not necessarily that it is possible. For it to work, everything referenced by Equipa must also be either primitive or Serializable (and so on, recursively). Is this the case?
Warning in the read function is the result of generics in java. You won't be able to suppress it, unless you use #SuppressWarnings("unchecked") to ignore it.
If you are sure you are reading an ArrayList<Equipa>, you can ignore it without any problem.
With the Equipa code, I can try to point to the Serializable problem: make sure that Carro and Piloto classes are also Serializables. You can add the code of theses classes if you are not sure.
The only type-safer way would be do a custom serialization, using writeObject(OutputStream) and readObjectInputStream say on a class ArrayListOfEquipa maybe using Equipa[] (ArrayList.toArray()).
Not really attractive, if the warning would be the only reason.

Categories