blog.Ring.idv.tw

2009 December

WordCount - HBase 0.20.x

本文是一個簡單的WordCount程式,經由MapReduce的處理之後直接輸出到HBase,實作的範例如下:

import java.io.IOException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.HColumnDescriptor;
import org.apache.hadoop.hbase.HTableDescriptor;
import org.apache.hadoop.hbase.client.HBaseAdmin;
import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.mapreduce.TableOutputFormat;
import org.apache.hadoop.hbase.mapreduce.TableReducer;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.input.TextInputFormat;

public class WordCountHBase
{
    public static class Map extends Mapper<LongWritable,Text,Text, IntWritable>
    {
        private IntWritable i = new IntWritable(1);
        @Override
        public void map(LongWritable key,Text value,Context context) throws IOException, InterruptedException
        {
            String s[] = value.toString().trim().split(" ");
            for( String m : s)
            {
                context.write(new Text(m), i);
            }
        }
    }
    public static class Reduce extends TableReducer<Text, IntWritable, NullWritable>
    {
        @Override
        public void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException
        {
            int sum = 0;
            for(IntWritable i : values)
            {
                sum += i.get();
            }
           
            Put put = new Put(Bytes.toBytes(key.toString()));
            put.add(Bytes.toBytes("content"), Bytes.toBytes("count"), Bytes.toBytes(String.valueOf(sum)));
            context.write(NullWritable.get(), put);
        }
    }
    public static void createHBaseTable(String tablename)throws IOException
    {
        HTableDescriptor htd = new HTableDescriptor(tablename);
        HColumnDescriptor col = new HColumnDescriptor("content:");
        htd.addFamily(col);
       
        HBaseConfiguration config = new HBaseConfiguration();
        HBaseAdmin admin = new HBaseAdmin(config);
        if(admin.tableExists(tablename))
        {
            admin.disableTable(tablename);
            admin.deleteTable(tablename);
        }
       
        System.out.println("create new table: " + tablename);
        admin.createTable(htd);
    }
   
    public static void main(String args[]) throws Exception
    {
        String tablename = "wordcount";
       
        Configuration conf = new Configuration();
        conf.set(TableOutputFormat.OUTPUT_TABLE, tablename);
        createHBaseTable(tablename);

        String input = args[0];
        Job job = new Job(conf, "WordCount table with " + input);
       
        job.setJarByClass(WordCountHBase.class);
        job.setNumReduceTasks(3);
        job.setMapperClass(Map.class);
        job.setReducerClass(Reduce.class);
       
        job.setMapOutputKeyClass(Text.class);
        job.setMapOutputValueClass(IntWritable.class);
       
        job.setInputFormatClass(TextInputFormat.class);
        job.setOutputFormatClass(TableOutputFormat.class);

        FileInputFormat.addInputPath(job, new Path(input));
       
        System.exit(job.waitForCompletion(true)?0:1);
    }
}

從上述程式可以知道Reduce是直接繼承於TableReducer<KEYIN,VALUEIN,KEYOUT>,不過就如同API的說明,KEYOUT在TableOutputFormat當中是被忽略的,而且VALUEOUT也只能是PutDelete,可以從下述的原始碼得知:

TableOutputFormat.java

public void write(KEY key, Writable value) throws IOException
{
	if (value instanceof Put)
		this.table.put(new Put((Put) value));
	else if (value instanceof Delete)
		this.table.delete(new Delete((Delete) value));
	else
		throw new IOException("Pass a Delete or a Put");
}

至於該輸出至哪一個Table,則必須設置「TableOutputFormat.OUTPUT_TABLE」的組態設定,也可以自行設置「hbase.mapred.outputtable」。

TableOutputFormat.java

public static final String OUTPUT_TABLE = "hbase.mapred.outputtable";

2009-12-08 21:55:33 | Comments (2)

AS3在Document Class和Timeline

在Flash IDE的開發環境下,我們不僅可以透過Document Class的方式來寫AS3程式,另外也可以透過時間軸(Timeline)的方式來達成,甚至還可以混合這兩種方式,那究竟寫在Document ClassTimeline兩者的寫法有何差異,底下各別來探討:

Document Class - Hello

Hello.as

package
{
	import flash.display.*;
	
	public class Hello extends MovieClip
	{
		public function Hello()
		{
			trace("Hello");
		}
	}
}

直接在Document Class中設為「Hello」並輸出swf檔案。

Decompiling:

package 
{
    import flash.display.*;

    public class Hello extends MovieClip
    {
        public function Hello()
        {
            trace("Hello");
            return;
        }
    }
}

從結果上來看,程式的結構上並沒有太大的變化,接下來看時間軸的作法。

Timeline - Hello

直接在時間軸Frame[0]寫下:

trace("Hello");

並直接發佈成swf檔案。

Decompiling:

package hello_fla
{
    import flash.display.*;

    dynamic public class MainTimeline extends MovieClip
    {
        public function MainTimeline()
        {
            addFrameScript(0, this.frame1);
            return;
        }
        function frame1()
        {
            trace("Hello");
            return;
        }
    }
}

經由時間軸的寫法可以發現,只有一行「trace("Hello");」程式完全被重新包裝,Flash編譯器自動產生了一個Dynamic Class「MainTimeline」來達成,而且原先的「trace("Hello");」程式並不是被寫在MainTimeline的Constructor之中,而是透過「addFrameScript」函式來明確地指定「Frame 0」位置來達成,那如果混合Document ClassTimeline的作法又是如何呢?

Document Class & Timeline - Hello

將上述「Hello.as」直接拿來使用,並在時間軸Frame[0]的位置加上「trace("Hello2");」來測試。

Decompiling:

package 
{
    import flash.display.*;

    public class Hello extends MovieClip
    {
        public function Hello()
        {
            addFrameScript(0, this.frame1);
            trace("Hello");
            return;
        }
        function frame1()
        {
            trace("Hello2");
            return;
        }
    }
}

透過Document ClassTimeline混合的作法可以發現,Flash編譯器會將Timeline上的程式加到Document ClassConstructor之中,所以如果從Runtime的「執行順序」上來看(非程式順序),該程式即會印出:

Hello
Hello2

2009-12-07 22:16:28 | Add Comment

Panasonic LX3 割愛了~

昨天.陪著我371天的LX3已經轉賣給有緣人了~ 因為我想要有一台基本的單眼來使用,不過這並不足以當做理由,其實最重要的是小時候長大的地方「鹿港」,現在位於鹿港的老家竟然要賣掉了..Orz,其實有蠻多小時候的回憶都在那裡~ 之前參加比賽時也曾拿鹿港來當作題材,而現在只能說有些事情發生的真是無常~

所以這個月月底要趁還沒售出之前去拍一些照片,本來想用LX3來搞定... 但是前陣子有人在我旁邊用D90一直卡嚓、卡嚓 (請來自首!),我的LX3拍好一張.. 它不曉得已經拍好幾張了!! 加上差不多時候也該升級相機配備了,所以就分期給它敗了Sony α550DT Carl Zeiss 16-80mm f/3.5-4.5 Zoom

對我來說這樣的配備應該足夠我用上個三年吧~ 但其實如果還有一顆定焦鏡的話會更完整,果然是條不歸路...

不過如果你想要隨身機的話,其實LX3真的蠻不錯用的~ 又有24mm廣角、1cm近拍和HD錄影品質,值得的! 只是筆者需要換現金來升級...Orz 才割愛~

順便貼上幾張昨天清空LX3記憶卡時的保存照:

2009-12-06 21:25:19 | Comments (2)

Next Posts
Copyright (C) Ching-Shen Chen. All rights reserved.

::: 搜尋 :::

::: 分類 :::

::: 最新文章 :::

::: 最新回應 :::

::: 訂閱 :::

Atom feed
Atom Comment