之前有篇博客(http://www.cnblogs.com/lz3018/p/5243503.html)介绍以SequenceFile作为输入源进行矩阵乘法的过程,首先是将矩阵存储到SequenceFile文件中,然后使用hadoop命令:hadoop fs -text /10IntArray  查看此SequenceFile文件中内容的时候,显示如下:

而我们写SequenceFile文件的代码如下:

  1. /**
  2. * Created with IntelliJ IDEA.
  3. * User: hadoop
  4. * Date: 16-3-4
  5. * Time: 上午10:36
  6. * To change this template use File | Settings | File Templates.
  7. */
  8. import org.apache.hadoop.conf.Configuration;
  9. import org.apache.hadoop.fs.FileSystem;
  10. import org.apache.hadoop.fs.Path;
  11. import java.io.IOException;
  12. import java.net.URI;
  13. import org.apache.hadoop.io.IntWritable;
  14. import org.apache.hadoop.io.SequenceFile;
  15. import org.apache.hadoop.io.ArrayWritable;
  16. public class SequenceFileWriterDemo {
  17. public static void main(String[] args) throws IOException {
  18. String uri="/home/hadoop/2016Test/SeqTest/10IntArray";
  19. Configuration conf=new Configuration();
  20. FileSystem fs=FileSystem.get(URI.create(uri),conf);
  21. Path path=new Path(uri);
  22. IntWritable key=new IntWritable();
  23. IntArrayWritable value=new IntArrayWritable();//定义IntArrayWritable类型的alue值。
  24. value.set(new IntWritable[]{new IntWritable(),new IntWritable(),new IntWritable(),
  25. new IntWritable()});
  26. SequenceFile.Writer writer=null;
  27. writer=SequenceFile.createWriter(fs,conf,path,key.getClass(),value.getClass());
  28. int i=;
  29. while(i<){
  30. key.set(i++);
  31. //value.set(intArray);
  32. writer.append(key,value);
  33. }
  34. writer.close();//一定要加上这句,否则写入SequenceFile会失败,结果是一个空文件。
  35. System.out.println("done!");
  36. }
  37. }
  38. class IntArrayWritable extends ArrayWritable {
  39. public IntArrayWritable(){
  40. super(IntWritable.class);
  41. }
  42. }

当我们把[1,2,3,4]转化为IntArrayWritable类型的value之后,再调用writer.append(key,value)就把这个向量写入文件了。其实这就是将一个序列化的过程,将“活对象”持久化存储(因为一般对象只有在JVM运行的时候才能存在),对象的持久化存储可以在JVM停止之后仍然存在。序列化的过程存储的只是对象的“状态”,也就是对象的成员变量,所以类的成员方法以及静态变量是不存储的。

但是,当我们使用命令查看这个文件中的内容时,为什么内容看起来那么奇怪呢?

1)这要从今天遇到的一个问题开始说起。代码如下:

  1. public class test{
  2.  
  3. public static void main(String[] args){
  4. int[] intArray={,,};
  5. String s=intArray.toString(a);//将数组转化为字符串,然后输出,多么朴素的想法,但是,结果...
  6. System.out.println(s);
  7. }
  8. }

当System.out.println()检测到输入是一个对象而不是字符或者数字时就会调用这个对象的toString()方法进行输出。Object是所有类的父类,其有一个toString()方法,而整型数组(int [])并没有重写这个toString()方法,所以调用Object的方法,定义如下:

  1. public String toString() {
  2. return getClass().getName() + "@" + Integer.toHexString(hashCode());
  3. }

hashCode()的返回值是jdk根据对象地址算出来的可以唯一标识这个对象的int型数值。而Integer.toHexString(int i)就是将这个int的数值首先转化为16进制表示的无符号整形数,然后再将这个数转化为字符串,示例如下(http://www.yiibai.com/javalang/integer_tohexstring.html):

  1. import java.lang.*;
  2. public class IntegerDemo {
  3. public static void main(String[] args) {
  4. int i = 170;
  5. System.out.println("Number = " + i);
  6. /* returns the string representation of the unsigned integer value
  7. represented by the argument in hexadecimal (base 16) */
  8. System.out.println("Hex = " + Integer.toHexString(i));
  9. }
  10. }

输出结果如下:

  1. Number = 170
  2. Hex = aa

至此,我们就明白了以下结果的含义:

  1. [I@74a14482

int[] intArray={1,2,3},"["应该是表示这个是说明对象数组类型,"I"表示是整型变量,然后就是"@",最后是74a14482就是对象的哈希值的16进制表示形式。原因我们已经搞清楚了,那么怎么才能使其输出正常呢(http://www.linuxidc.com/Linux/2014-12/110127.htm)?

2)使用Arrays.toStrings()将数组转化为字符串,代码如下:

  1. /**
  2. * Created by hfz on 2016/2/28.
  3. */
  4. import java.util.Arrays;
  5. public class Main {
  6. public static void main(String[] args){
  7. int[] a=new int[]{1,2,3};
  8. String s= Arrays.toString(a);
  9. System.out.println(s);
  10.  
  11. }
  12.  
  13. }

Arrays.toString()上的实现如下:

  1. public static String toString(int[] a) {
  2. if (a == null)
  3. return "null";
  4. int iMax = a.length - 1;
  5. if (iMax == -1)
  6. return "[]";
  7.  
  8. StringBuilder b = new StringBuilder();
  9. b.append('[');
  10. for (int i = 0; ; i++) {
  11. b.append(a[i]);
  12. if (i == iMax)
  13. return b.append(']').toString();
  14. b.append(", ");
  15. }
  16. }

结果如下所示:

做个总结,使用system.out.print(var)输出变量var时,当检测到var是引用类型的话,也就是对象,就会自动调用其toString()方法,然后输出对象对应的字符串。当我们使用writer.append(key,value)时(写文件时应该也是会检测写入变量的类型),检测到value是对象,所以会调用其toString()方法,因为我们自定义的IntArrayWritable并没有覆盖父类Object的toString()方法,所以是调用了Object的toString()方法,

  1. public String toString() {
  2. return getClass().getName() + "@" + Integer.toHexString(hashCode());
  3. }

所以写入文件的value是“IntArrayWritable@5dcf0778”(数组类型会在类名称之前加“[”),后来我们使用命令查看文件内容时看到的自然就是:

key可以正常显示?因为IntWritable重载了toString()方法呀,所以我们还需要在IntArrayWritable中增加一个toString()方法才可以正常显示。那么,怎么才能使IntArrayWritable也正常显示呢?只需要IntArrayWritable重载toString()方法就可以了。其最新定义如下:

  1. class IntArrayWritable extends ArrayWritable {
  2. public IntArrayWritable(){
  3. super(IntWritable.class);
  4. }
  5. public String toString(){
  6. StringBuilder sb=new StringBuilder();
  7. for (Writable val:get()){
  8. IntWritable intWritable=(IntWritable)val;
  9. sb.append(intWritable.get());
  10. sb.append(",");
  11. }
  12. return sb.toString();
  13. }

有一点需要注意,就是ArrayWritable的get方法以Writable[]返回值values,而我们需要的是IntWriable型的值,如果采用下列方法:

  1. IntWritable[] intArray=(IntWritable[])get();

不过会报错,“Writable[] can't cast to IntWritable[]”。

正确的方法是采用以下的方法(http://qiuqiang1985.iteye.com/blog/1622065):

  1. for (Writable val:get()){
  2. IntWritable intWritable=(IntWritable)val;

然后看到的就如我们希望的那样。

由SequenceFile.Writer(key,value)谈toString()方法的更多相关文章

  1. 源码浅谈(一):java中的 toString()方法

    前言: toString()方法 相信大家都用到过,一般用于以字符串的形式返回对象的相关数据. 最近项目中需要对一个ArrayList<ArrayList<Integer>> ...

  2. Map集合中key不存在时使用toString()方法、valueOf()方法和强制转换((String))之间的区别

    1.toString()方法 底层代码 public String toString() { return this; } 其返回值为String类型的字符串本身 Map<String, Obj ...

  3. 从toString()方法到Object.prototype.toString.call()方法

    一.toString方法和Object.prototype.toSting.call()的区别 var arr=[1,2]; 直接对一个数组调用toString()方法, console.log(ar ...

  4. 【原创】关于java对象需要重写equals方法,hashcode方法,toString方法 ,compareto()方法的说明

    在项目开发中,我们都有这样的经历,就是在新增表时,会相应的增加java类,在java类中都存在常见的几个方法,包括:equals(),hashcode(),toString() ,compareto( ...

  5. 采用重写tostring方法使ComboBox显示对象属性

    当ComboBox中添加的是对象集合的时候,如果运行就会发现显示是的命令空间.类名,而如果我们想显示对象属性名的时候,我们就可以在对象类中重写object基类中的tostring方法.

  6. ECMAScript toString() 方法

    ECMAScript 定义所有对象都有 toString() 方法,无论它是伪对象,还是真对象. ECMAScript 的 Boolean 值.数字和字符串的原始值的有趣之处在于它们是伪对象,这意味着 ...

  7. 利用Object.prototype.toString方法,实现比typeof更准确的type校验

    Object.prototype.toString方法返回对象的类型字符串,因此可以用来判断一个值的类型. 调用方法: Object.prototype.toString.call(value) 不同 ...

  8. 重写toString()方法来描述一个类

    package com.zch.test; /* toString方法以及重写toString方法 toString方法是一个自我描述方法 方法本身返回的是该对象的实现类的 类名 + @ + hash ...

  9. Object类的toString方法

          Object类是所有Java类的祖先.每个类都使用 Object 作为超类.所有对象(包括数组)都实现这个类的方法.在不明确给出超类的情况下,Java会自动把Object作为要定义类的超类 ...

随机推荐

  1. 慕课网javascript 进阶篇 第九章 编程练习

    把平常撸的码来博客上再撸一遍既可以加深理解,又可以理清思维.还是很纯很纯的小白,各位看官老爷们,不要嫌弃.最近都是晚睡,昨晚也不例外,两点多睡的.故,八点起来的人不是很舒服,脑袋有点晕呼呼,鉴于昨晚看 ...

  2. 【数据结构】bzoj1651专用牛棚

    Description Oh those picky N (1 <= N <= 50,000) cows! They are so picky that each one will onl ...

  3. SSL步骤

    SSL步骤 被认证的服务器 1.创建keystore 2.创建信任证书 3.导出信任证书供客户端使用 客户端 1.创建keystore(如果不存在) 2.导入信任证书

  4. 端到端测试,protractor测试的教程

    之前我们介绍了如何测试某段js代码的逻辑是否正确,考虑的情况是否全面,但是在ui界面上我们每次做好的功能都要自己去填写内容,点击按钮等,那么是否存在自动化测试的工具呢,让这些事情可以自动完成,答案是肯 ...

  5. 工作技能===开发不改bug?给你支个招

    在测试过程中,不免会遇到开发人员因为一些原因不想修改个别bug的情况.那一般遇到这种问题时,我们该如何去推进开发修改bug呢? 我们先来分析下到底会有哪些原因会导致开发不修改bug 1. 开发与测试对 ...

  6. Entity Framework 6.1.2 offset row fetch next 错误解决办法

    本地测试环境用的SqlServer2012,生产环境2008R2.然后在查询分页数据时生产环境悲剧的报错了. 原因是EF6.1.2以上版本在编译SQL时使用了新的语法对低版本的SqlServer不兼容 ...

  7. 【 Linux】脚本导入格式

    在从windows文本(*.txt)格式导入到Linux中时,需要注意. 如果是直接将*.txt 导入到Linux系统,然后重命名使用会有问题,建议在linux系统中创建文件,然后直接复制内容到lin ...

  8. 原创 gif png bmp jeg 显示方法

    /// <summary> /// 注意不要忘记引用那几个图片单元哦,除了bmp格式不需要引用任何单元, /// 其它图片格式都需要引用对应的图片单元 /// png ---> Vc ...

  9. 网站js埋点

    js埋点 1.埋点作用:  页面埋点的作用:其实就是用于流量分析.而流量的意思,包含了很多:页面浏览数(PV).独立访问者数量(UV).IP.页面停留时间.页面操作时间.页面访问次数.按钮点击次数.文 ...

  10. paramiko 使用总结(SSH 操作远端机器)

    1.用户名.密码登陆方式 import paramikoparamiko.util.log_to_file('paramiko.log') # 记录日志文件ssh = paramiko.SSHClie ...