由SequenceFile.Writer(key,value)谈toString()方法
之前有篇博客(http://www.cnblogs.com/lz3018/p/5243503.html)介绍以SequenceFile作为输入源进行矩阵乘法的过程,首先是将矩阵存储到SequenceFile文件中,然后使用hadoop命令:hadoop fs -text /10IntArray 查看此SequenceFile文件中内容的时候,显示如下:
而我们写SequenceFile文件的代码如下:
- /**
- * Created with IntelliJ IDEA.
- * User: hadoop
- * Date: 16-3-4
- * Time: 上午10:36
- * To change this template use File | Settings | File Templates.
- */
- import org.apache.hadoop.conf.Configuration;
- import org.apache.hadoop.fs.FileSystem;
- import org.apache.hadoop.fs.Path;
- import java.io.IOException;
- import java.net.URI;
- import org.apache.hadoop.io.IntWritable;
- import org.apache.hadoop.io.SequenceFile;
- import org.apache.hadoop.io.ArrayWritable;
- public class SequenceFileWriterDemo {
- public static void main(String[] args) throws IOException {
- String uri="/home/hadoop/2016Test/SeqTest/10IntArray";
- Configuration conf=new Configuration();
- FileSystem fs=FileSystem.get(URI.create(uri),conf);
- Path path=new Path(uri);
- IntWritable key=new IntWritable();
- IntArrayWritable value=new IntArrayWritable();//定义IntArrayWritable类型的alue值。
- value.set(new IntWritable[]{new IntWritable(),new IntWritable(),new IntWritable(),
- new IntWritable()});
- SequenceFile.Writer writer=null;
- writer=SequenceFile.createWriter(fs,conf,path,key.getClass(),value.getClass());
- int i=;
- while(i<){
- key.set(i++);
- //value.set(intArray);
- writer.append(key,value);
- }
- writer.close();//一定要加上这句,否则写入SequenceFile会失败,结果是一个空文件。
- System.out.println("done!");
- }
- }
- class IntArrayWritable extends ArrayWritable {
- public IntArrayWritable(){
- super(IntWritable.class);
- }
- }
当我们把[1,2,3,4]转化为IntArrayWritable类型的value之后,再调用writer.append(key,value)就把这个向量写入文件了。其实这就是将一个序列化的过程,将“活对象”持久化存储(因为一般对象只有在JVM运行的时候才能存在),对象的持久化存储可以在JVM停止之后仍然存在。序列化的过程存储的只是对象的“状态”,也就是对象的成员变量,所以类的成员方法以及静态变量是不存储的。
但是,当我们使用命令查看这个文件中的内容时,为什么内容看起来那么奇怪呢?
1)这要从今天遇到的一个问题开始说起。代码如下:
- public class test{
- public static void main(String[] args){
- int[] intArray={,,};
- String s=intArray.toString(a);//将数组转化为字符串,然后输出,多么朴素的想法,但是,结果...
- System.out.println(s);
- }
- }
当System.out.println()检测到输入是一个对象而不是字符或者数字时就会调用这个对象的toString()方法进行输出。Object是所有类的父类,其有一个toString()方法,而整型数组(int [])并没有重写这个toString()方法,所以调用Object的方法,定义如下:
- public String toString() {
- return getClass().getName() + "@" + Integer.toHexString(hashCode());
- }
hashCode()的返回值是jdk根据对象地址算出来的可以唯一标识这个对象的int型数值。而Integer.toHexString(int i)就是将这个int的数值首先转化为16进制表示的无符号整形数,然后再将这个数转化为字符串,示例如下(http://www.yiibai.com/javalang/integer_tohexstring.html):
- import java.lang.*;
- public class IntegerDemo {
- public static void main(String[] args) {
- int i = 170;
- System.out.println("Number = " + i);
- /* returns the string representation of the unsigned integer value
- represented by the argument in hexadecimal (base 16) */
- System.out.println("Hex = " + Integer.toHexString(i));
- }
- }
输出结果如下:
- Number = 170
- Hex = aa
至此,我们就明白了以下结果的含义:
- [I@74a14482
int[] intArray={1,2,3},"["应该是表示这个是说明对象数组类型,"I"表示是整型变量,然后就是"@",最后是74a14482就是对象的哈希值的16进制表示形式。原因我们已经搞清楚了,那么怎么才能使其输出正常呢(http://www.linuxidc.com/Linux/2014-12/110127.htm)?
2)使用Arrays.toStrings()将数组转化为字符串,代码如下:
- /**
- * Created by hfz on 2016/2/28.
- */
- import java.util.Arrays;
- public class Main {
- public static void main(String[] args){
- int[] a=new int[]{1,2,3};
- String s= Arrays.toString(a);
- System.out.println(s);
- }
- }
Arrays.toString()上的实现如下:
- public static String toString(int[] a) {
- if (a == null)
- return "null";
- int iMax = a.length - 1;
- if (iMax == -1)
- return "[]";
- StringBuilder b = new StringBuilder();
- b.append('[');
- for (int i = 0; ; i++) {
- b.append(a[i]);
- if (i == iMax)
- return b.append(']').toString();
- b.append(", ");
- }
- }
结果如下所示:
做个总结,使用system.out.print(var)输出变量var时,当检测到var是引用类型的话,也就是对象,就会自动调用其toString()方法,然后输出对象对应的字符串。当我们使用writer.append(key,value)时(写文件时应该也是会检测写入变量的类型),检测到value是对象,所以会调用其toString()方法,因为我们自定义的IntArrayWritable并没有覆盖父类Object的toString()方法,所以是调用了Object的toString()方法,
- public String toString() {
- return getClass().getName() + "@" + Integer.toHexString(hashCode());
- }
所以写入文件的value是“IntArrayWritable@5dcf0778”(数组类型会在类名称之前加“[”),后来我们使用命令查看文件内容时看到的自然就是:
key可以正常显示?因为IntWritable重载了toString()方法呀,所以我们还需要在IntArrayWritable中增加一个toString()方法才可以正常显示。那么,怎么才能使IntArrayWritable也正常显示呢?只需要IntArrayWritable重载toString()方法就可以了。其最新定义如下:
- class IntArrayWritable extends ArrayWritable {
- public IntArrayWritable(){
- super(IntWritable.class);
- }
- public String toString(){
- StringBuilder sb=new StringBuilder();
- for (Writable val:get()){
- IntWritable intWritable=(IntWritable)val;
- sb.append(intWritable.get());
- sb.append(",");
- }
- return sb.toString();
- }
有一点需要注意,就是ArrayWritable的get方法以Writable[]返回值values,而我们需要的是IntWriable型的值,如果采用下列方法:
- IntWritable[] intArray=(IntWritable[])get();
不过会报错,“Writable[] can't cast to IntWritable[]”。
正确的方法是采用以下的方法(http://qiuqiang1985.iteye.com/blog/1622065):
- for (Writable val:get()){
- IntWritable intWritable=(IntWritable)val;
- }
然后看到的就如我们希望的那样。
由SequenceFile.Writer(key,value)谈toString()方法的更多相关文章
- 源码浅谈(一):java中的 toString()方法
前言: toString()方法 相信大家都用到过,一般用于以字符串的形式返回对象的相关数据. 最近项目中需要对一个ArrayList<ArrayList<Integer>> ...
- Map集合中key不存在时使用toString()方法、valueOf()方法和强制转换((String))之间的区别
1.toString()方法 底层代码 public String toString() { return this; } 其返回值为String类型的字符串本身 Map<String, Obj ...
- 从toString()方法到Object.prototype.toString.call()方法
一.toString方法和Object.prototype.toSting.call()的区别 var arr=[1,2]; 直接对一个数组调用toString()方法, console.log(ar ...
- 【原创】关于java对象需要重写equals方法,hashcode方法,toString方法 ,compareto()方法的说明
在项目开发中,我们都有这样的经历,就是在新增表时,会相应的增加java类,在java类中都存在常见的几个方法,包括:equals(),hashcode(),toString() ,compareto( ...
- 采用重写tostring方法使ComboBox显示对象属性
当ComboBox中添加的是对象集合的时候,如果运行就会发现显示是的命令空间.类名,而如果我们想显示对象属性名的时候,我们就可以在对象类中重写object基类中的tostring方法.
- ECMAScript toString() 方法
ECMAScript 定义所有对象都有 toString() 方法,无论它是伪对象,还是真对象. ECMAScript 的 Boolean 值.数字和字符串的原始值的有趣之处在于它们是伪对象,这意味着 ...
- 利用Object.prototype.toString方法,实现比typeof更准确的type校验
Object.prototype.toString方法返回对象的类型字符串,因此可以用来判断一个值的类型. 调用方法: Object.prototype.toString.call(value) 不同 ...
- 重写toString()方法来描述一个类
package com.zch.test; /* toString方法以及重写toString方法 toString方法是一个自我描述方法 方法本身返回的是该对象的实现类的 类名 + @ + hash ...
- Object类的toString方法
Object类是所有Java类的祖先.每个类都使用 Object 作为超类.所有对象(包括数组)都实现这个类的方法.在不明确给出超类的情况下,Java会自动把Object作为要定义类的超类 ...
随机推荐
- 最适合初学者学习的idea教程
https://github.com/judasn/IntelliJ-IDEA-Tutorial
- 【BZOJ2227】【ZJOI2011】看电影 [组合数][质因数分解]
看电影 Time Limit: 10 Sec Memory Limit: 259 MB[Submit][Status][Discuss] Description 到了难得的假期,小白班上组织大家去看 ...
- R的农场
R的农场 题目描述 最近,R 终于获得了一片他梦寐以求的农场,但如此大的一片农场,想要做好防卫工作可不是一件容易的事.所以 R 购买了 N 个守卫,分别让他们站在一定的位置上(守卫不可移动,同一位置上 ...
- pychart
Pychart PyChart is a Python library for creating high quality Encapsulated Postscript, PDF, PNG, or ...
- SpringMvc基础知识(二) springmvc和mybatis整合
1 springmvc和mybatis整合 1.1 需求 使用springmvc和mybatis完成商品列表查询. 1.2 整合思路 springmvc+mybaits的系统架构: 第一步:整合dao ...
- postman发送post请求,报405 Method Not Allowed
postman发送post请求,报405 Method Not Allowed: 亲测有效的方案一: 检查请求header是否缺少必要信息.如果不清可以把所有的头部信息全部粘贴到header中,尝试是 ...
- Oracle rman 全备份的一个小例子
run{ allocate channel d1 type disk; backup database format='/u01/backup/%T_%d_%s.bak'; sql 'alter ...
- Mac自带的SSH客户端
https://segmentfault.com/q/1010000002806469 还能设置连接成持久连接,方便使用: ttps://www.zhihu.com/question/20541129 ...
- 自建yum镜像
#!/usr/bin/python #-*- coding: utf-8 -*- import requests import sys,logging,traceback from bs4 impor ...
- php常用的系统函数
字符串函数 strlen:获取字符串长度,字节长度 substr_count 某字符串出现的次数 substr:字符串截取,获取字符串(按照字节进行截取) mb_strlenmb_substr str ...